Add validators and services for Product Galleries and Product Tags
- Implemented Create, Delete, Get, and Update validators for Product Galleries. - Added Create, Delete, Get, and Update validators for Product Tags. - Created service classes for handling Discount Categories, Discount Orders, Discount Products, Discount Shopping Cart, Product Categories, Product Galleries, and Product Tags. - Each service class integrates with CQRS for command and query handling. - Established mapping profiles for Product Galleries.
This commit is contained in:
@@ -34,28 +34,14 @@ public static class ConfigureServices
|
||||
services.AddScoped<IUserNotificationService, UserNotificationService>();
|
||||
services.AddScoped<IDayaLoanApiService, MockDayaLoanApiService>(); // Mock - جایگزین با Real برای Production
|
||||
|
||||
// Payment Gateway Service - برای Development از Mock استفاده میشود
|
||||
// برای Production یکی از سرویسهای واقعی را فعال کنید
|
||||
// Payment Gateway Service - فقط Daya (درگاه اینترنتی از Gateway میاد نه CMS)
|
||||
var useRealPaymentGateway = configuration.GetValue<bool>("UseRealPaymentGateway", false);
|
||||
|
||||
if (useRealPaymentGateway)
|
||||
{
|
||||
var paymentProvider = configuration.GetValue<string>("PaymentProvider", "BankMellat");
|
||||
|
||||
if (paymentProvider == "Daya")
|
||||
{
|
||||
services.AddHttpClient<IPaymentGatewayService, DayaPaymentService>()
|
||||
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
|
||||
}
|
||||
else if (paymentProvider == "BankMellat")
|
||||
{
|
||||
services.AddHttpClient<IPaymentGatewayService, BankMellatPaymentService>()
|
||||
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid PaymentProvider: {paymentProvider}. Valid values: Daya, BankMellat");
|
||||
}
|
||||
// فقط Daya برای پرداخت به کاربران (Payout)
|
||||
services.AddHttpClient<IPaymentGatewayService, DayaPaymentService>()
|
||||
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace CMSMicroservice.Infrastructure.Data.Seeding;
|
||||
|
||||
/// <summary>
|
||||
/// Seeder for migrating existing User.ParentId to User.NetworkParentId
|
||||
/// این Seeder فقط یک بار اجرا میشود و دادههای قدیمی را به ساختار Binary Tree جدید منتقل میکند
|
||||
/// NOTE: ParentId has been removed from User entity, so this seeder is now obsolete
|
||||
/// </summary>
|
||||
public class NetworkParentIdMigrationSeeder
|
||||
{
|
||||
@@ -25,147 +25,12 @@ public class NetworkParentIdMigrationSeeder
|
||||
|
||||
public async Task SeedAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
_logger.LogInformation("=== Starting ParentId → NetworkParentId Migration ===");
|
||||
|
||||
// Step 1: Validation - Check if migration already done
|
||||
var alreadyMigrated = await _context.Users
|
||||
.Where(u => u.ParentId != null && u.NetworkParentId != null)
|
||||
.AnyAsync(cancellationToken);
|
||||
|
||||
if (alreadyMigrated)
|
||||
{
|
||||
_logger.LogWarning("⚠️ Migration already completed! Skipping...");
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 2: Find users with ParentId but no NetworkParentId
|
||||
var usersToMigrate = await _context.Users
|
||||
.Where(u => u.ParentId != null && u.NetworkParentId == null)
|
||||
.OrderBy(u => u.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (usersToMigrate.Count == 0)
|
||||
{
|
||||
_logger.LogInformation("✅ No users to migrate. All done!");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation($"📊 Found {usersToMigrate.Count} users to migrate");
|
||||
|
||||
// Step 3: Group by ParentId to check binary tree constraint
|
||||
var parentGroups = usersToMigrate.GroupBy(u => u.ParentId);
|
||||
|
||||
int migratedCount = 0;
|
||||
int skippedCount = 0;
|
||||
|
||||
foreach (var group in parentGroups)
|
||||
{
|
||||
var parentId = group.Key;
|
||||
var children = group.OrderBy(u => u.Id).ToList(); // ترتیب بر اساس Id
|
||||
|
||||
if (children.Count > 2)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"⚠️ Parent {ParentId} has {Count} children! Binary tree allows max 2. Taking first 2...",
|
||||
parentId, children.Count);
|
||||
|
||||
children = children.Take(2).ToList();
|
||||
skippedCount += (group.Count() - 2);
|
||||
}
|
||||
|
||||
// Assign NetworkParentId and LegPosition
|
||||
for (int i = 0; i < children.Count && i < 2; i++)
|
||||
{
|
||||
var child = children[i];
|
||||
child.NetworkParentId = parentId;
|
||||
child.LegPosition = i == 0 ? NetworkLeg.Left : NetworkLeg.Right;
|
||||
|
||||
_logger.LogDebug(
|
||||
"✅ Migrated User {UserId}: Parent={ParentId}, Leg={Leg}",
|
||||
child.Id, parentId, child.LegPosition);
|
||||
|
||||
migratedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Save changes
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
_logger.LogInformation(
|
||||
"✅ Migration Completed! Migrated={Migrated}, Skipped={Skipped}",
|
||||
migratedCount, skippedCount);
|
||||
|
||||
// Step 5: Post-Migration Validation
|
||||
await ValidateMigrationAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task ValidateMigrationAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("🔍 Validating Migration...");
|
||||
|
||||
// Check 1: Orphaned nodes (NetworkParent doesn't exist)
|
||||
var orphanedUsers = await _context.Users
|
||||
.Where(u => u.NetworkParentId != null &&
|
||||
!_context.Users.Any(p => p.Id == u.NetworkParentId))
|
||||
.Select(u => new { u.Id, u.NetworkParentId })
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (orphanedUsers.Any())
|
||||
{
|
||||
_logger.LogError(
|
||||
"❌ Found {Count} orphaned users (NetworkParent doesn't exist): {Ids}",
|
||||
orphanedUsers.Count,
|
||||
string.Join(", ", orphanedUsers.Select(u => u.Id)));
|
||||
}
|
||||
|
||||
// Check 2: Binary tree violation (more than 2 children per parent)
|
||||
var parentsWithTooManyChildren = await _context.Users
|
||||
.Where(u => u.NetworkParentId != null)
|
||||
.GroupBy(u => u.NetworkParentId)
|
||||
.Select(g => new { ParentId = g.Key, Count = g.Count() })
|
||||
.Where(x => x.Count > 2)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (parentsWithTooManyChildren.Any())
|
||||
{
|
||||
_logger.LogError(
|
||||
"❌ Binary tree violation! {Count} parents have more than 2 children",
|
||||
parentsWithTooManyChildren.Count);
|
||||
|
||||
foreach (var parent in parentsWithTooManyChildren)
|
||||
{
|
||||
_logger.LogError(" Parent {ParentId} has {Count} children", parent.ParentId, parent.Count);
|
||||
}
|
||||
}
|
||||
|
||||
// Check 3: Statistics
|
||||
var stats = await _context.Users
|
||||
.GroupBy(u => 1)
|
||||
.Select(g => new
|
||||
{
|
||||
TotalUsers = g.Count(),
|
||||
UsersWithNetworkParent = g.Count(u => u.NetworkParentId != null),
|
||||
LeftChildren = g.Count(u => u.LegPosition == NetworkLeg.Left),
|
||||
RightChildren = g.Count(u => u.LegPosition == NetworkLeg.Right)
|
||||
})
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (stats != null)
|
||||
{
|
||||
_logger.LogInformation("📊 Migration Statistics:");
|
||||
_logger.LogInformation(" Total Users: {Total}", stats.TotalUsers);
|
||||
_logger.LogInformation(" Users with NetworkParent: {Count}", stats.UsersWithNetworkParent);
|
||||
_logger.LogInformation(" Left Children: {Count}", stats.LeftChildren);
|
||||
_logger.LogInformation(" Right Children: {Count}", stats.RightChildren);
|
||||
}
|
||||
|
||||
if (!orphanedUsers.Any() && !parentsWithTooManyChildren.Any())
|
||||
{
|
||||
_logger.LogInformation("✅ Validation Passed! Binary tree is intact.");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("❌ Validation Failed! Please fix issues manually.");
|
||||
}
|
||||
_logger.LogInformation("=== NetworkParentIdMigrationSeeder: ParentId Removed ===");
|
||||
|
||||
// ParentId has been removed from User entity
|
||||
// This seeder is no longer necessary
|
||||
_logger.LogInformation("ParentId field has been removed. Migration is obsolete.");
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
using System.Reflection;
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
using CMSMicroservice.Domain.Entities.Payment;
|
||||
using CMSMicroservice.Domain.Entities.Message;
|
||||
using CMSMicroservice.Domain.Entities.Order;
|
||||
using CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
using CMSMicroservice.Infrastructure.Persistence.Interceptors;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@@ -43,29 +47,37 @@ public class ApplicationDbContext : DbContext, IApplicationDbContext
|
||||
|
||||
return await base.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
public DbSet<UserAddress> UserAddresss => Set<UserAddress>();
|
||||
public DbSet<UserAddress> UserAddresses => Set<UserAddress>();
|
||||
public DbSet<Package> Packages => Set<Package>();
|
||||
public DbSet<Role> Roles => Set<Role>();
|
||||
public DbSet<Category> Categorys => Set<Category>();
|
||||
public DbSet<Category> Categories => Set<Category>();
|
||||
public DbSet<UserRole> UserRoles => Set<UserRole>();
|
||||
public DbSet<UserCarts> UserCartss => Set<UserCarts>();
|
||||
public DbSet<ProductGallerys> ProductGalleryss => Set<ProductGallerys>();
|
||||
public DbSet<FactorDetails> FactorDetailss => Set<FactorDetails>();
|
||||
public DbSet<Products> Productss => Set<Products>();
|
||||
public DbSet<ProductImages> ProductImagess => Set<ProductImages>();
|
||||
public DbSet<UserCart> UserCarts => Set<UserCart>();
|
||||
public DbSet<ProductGallery> ProductGalleries => Set<ProductGallery>();
|
||||
public DbSet<FactorDetails> FactorDetails => Set<FactorDetails>();
|
||||
public DbSet<Product> Products => Set<Product>();
|
||||
public DbSet<ProductImage> ProductImages => Set<ProductImage>();
|
||||
public DbSet<User> Users => Set<User>();
|
||||
public DbSet<OtpToken> OtpTokens => Set<OtpToken>();
|
||||
public DbSet<Contract> Contracts => Set<Contract>();
|
||||
public DbSet<UserContract> UserContracts => Set<UserContract>();
|
||||
public DbSet<Tag> Tags => Set<Tag>();
|
||||
public DbSet<PruductCategory> PruductCategorys => Set<PruductCategory>();
|
||||
public DbSet<PruductTag> PruductTags => Set<PruductTag>();
|
||||
public DbSet<Transactions> Transactionss => Set<Transactions>();
|
||||
public DbSet<ProductCategory> ProductCategories => Set<ProductCategory>();
|
||||
public DbSet<ProductTag> ProductTags => Set<ProductTag>();
|
||||
public DbSet<Transaction> Transactions => Set<Transaction>();
|
||||
public DbSet<UserOrder> UserOrders => Set<UserOrder>();
|
||||
public DbSet<OrderVAT> OrderVATs => Set<OrderVAT>();
|
||||
public DbSet<UserPackagePurchase> UserPackagePurchases => Set<UserPackagePurchase>();
|
||||
public DbSet<UserWallet> UserWallets => Set<UserWallet>();
|
||||
public DbSet<UserWalletChangeLog> UserWalletChangeLogs => Set<UserWalletChangeLog>();
|
||||
public DbSet<DayaLoanContract> DayaLoanContracts => Set<DayaLoanContract>();
|
||||
|
||||
// Payment
|
||||
public DbSet<ManualPayment> ManualPayments => Set<ManualPayment>();
|
||||
|
||||
// Message
|
||||
public DbSet<PublicMessage> PublicMessages => Set<PublicMessage>();
|
||||
|
||||
// ============= Network Club System DbSets =============
|
||||
|
||||
// Configuration
|
||||
@@ -87,4 +99,12 @@ public class ApplicationDbContext : DbContext, IApplicationDbContext
|
||||
public DbSet<UserCommissionPayout> UserCommissionPayouts => Set<UserCommissionPayout>();
|
||||
public DbSet<CommissionPayoutHistory> CommissionPayoutHistories => Set<CommissionPayoutHistory>();
|
||||
public DbSet<WorkerExecutionLog> WorkerExecutionLogs => Set<WorkerExecutionLog>();
|
||||
|
||||
// ============= Discount Shop DbSets =============
|
||||
public DbSet<DiscountProduct> DiscountProducts => Set<DiscountProduct>();
|
||||
public DbSet<DiscountCategory> DiscountCategories => Set<DiscountCategory>();
|
||||
public DbSet<DiscountProductCategory> DiscountProductCategories => Set<DiscountProductCategory>();
|
||||
public DbSet<DiscountShoppingCart> DiscountShoppingCarts => Set<DiscountShoppingCart>();
|
||||
public DbSet<DiscountOrder> DiscountOrders => Set<DiscountOrder>();
|
||||
public DbSet<DiscountOrderDetail> DiscountOrderDetails => Set<DiscountOrderDetail>();
|
||||
}
|
||||
|
||||
@@ -111,6 +111,14 @@ public class ApplicationDbContextInitialiser
|
||||
Scope = ConfigurationScope.Club,
|
||||
IsActive = true
|
||||
},
|
||||
new SystemConfiguration
|
||||
{
|
||||
Key = "Club.MembershipGiftValue",
|
||||
Value = "25200000",
|
||||
Description = "مبلغ هدیه حق عضویت باشگاه (ریال) - این مبلغ از کیف پول کم نمیشود",
|
||||
Scope = ConfigurationScope.Club,
|
||||
IsActive = true
|
||||
},
|
||||
|
||||
// System Configuration
|
||||
new SystemConfiguration
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ public class CategoryConfiguration : IEntityTypeConfiguration<Category>
|
||||
builder.Property(entity => entity.ImagePath).IsRequired(false);
|
||||
builder
|
||||
.HasOne(entity => entity.Parent)
|
||||
.WithMany(entity => entity.Categorys)
|
||||
.WithMany(entity => entity.Categories)
|
||||
.HasForeignKey(entity => entity.ParentId)
|
||||
.IsRequired(false);
|
||||
builder.Property(entity => entity.IsActive).IsRequired(true);
|
||||
|
||||
+1
@@ -20,6 +20,7 @@ public class ClubMembershipConfiguration : IEntityTypeConfiguration<ClubMembersh
|
||||
builder.Property(entity => entity.IsActive).IsRequired();
|
||||
builder.Property(entity => entity.ActivatedAt).IsRequired(false);
|
||||
builder.Property(entity => entity.InitialContribution).IsRequired();
|
||||
builder.Property(entity => entity.GiftValue).IsRequired();
|
||||
builder.Property(entity => entity.TotalEarned).IsRequired();
|
||||
|
||||
// رابطه یکبهیک با User
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
using CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// تنظیمات EF Core برای دستهبندی فروشگاه تخفیفی
|
||||
/// </summary>
|
||||
public class DiscountCategoryConfiguration : IEntityTypeConfiguration<DiscountCategory>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<DiscountCategory> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
|
||||
builder.HasKey(entity => entity.Id);
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
|
||||
builder.Property(entity => entity.Name)
|
||||
.IsRequired()
|
||||
.HasMaxLength(100);
|
||||
|
||||
builder.Property(entity => entity.Title)
|
||||
.IsRequired()
|
||||
.HasMaxLength(200);
|
||||
|
||||
builder.Property(entity => entity.Description)
|
||||
.HasMaxLength(1000);
|
||||
|
||||
builder.Property(entity => entity.ImagePath)
|
||||
.HasMaxLength(500);
|
||||
|
||||
builder.Property(entity => entity.IsActive)
|
||||
.IsRequired()
|
||||
.HasDefaultValue(true);
|
||||
|
||||
// Self-referencing relationship for parent/child categories
|
||||
builder
|
||||
.HasOne(entity => entity.ParentCategory)
|
||||
.WithMany(entity => entity.ChildCategories)
|
||||
.HasForeignKey(entity => entity.ParentCategoryId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
using CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// تنظیمات EF Core برای سفارش فروشگاه تخفیفی
|
||||
/// </summary>
|
||||
public class DiscountOrderConfiguration : IEntityTypeConfiguration<DiscountOrder>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<DiscountOrder> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
|
||||
builder.HasKey(entity => entity.Id);
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
|
||||
builder.Property(entity => entity.UserId).IsRequired();
|
||||
builder.Property(entity => entity.TotalAmount).IsRequired();
|
||||
builder.Property(entity => entity.DiscountBalanceUsed).IsRequired();
|
||||
builder.Property(entity => entity.GatewayAmountPaid).IsRequired();
|
||||
builder.Property(entity => entity.VatAmount).IsRequired();
|
||||
builder.Property(entity => entity.PaymentStatus).IsRequired();
|
||||
builder.Property(entity => entity.UserAddressId).IsRequired();
|
||||
builder.Property(entity => entity.DeliveryStatus).IsRequired();
|
||||
|
||||
builder.Property(entity => entity.TrackingCode)
|
||||
.HasMaxLength(100);
|
||||
|
||||
builder.Property(entity => entity.DeliveryDescription)
|
||||
.HasMaxLength(500);
|
||||
|
||||
// Relationship: User -> Orders
|
||||
builder
|
||||
.HasOne(entity => entity.User)
|
||||
.WithMany(entity => entity.DiscountOrders)
|
||||
.HasForeignKey(entity => entity.UserId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// Relationship: Transaction (nullable)
|
||||
builder
|
||||
.HasOne(entity => entity.Transaction)
|
||||
.WithMany()
|
||||
.HasForeignKey(entity => entity.TransactionId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// Relationship: UserAddress
|
||||
builder
|
||||
.HasOne(entity => entity.UserAddress)
|
||||
.WithMany()
|
||||
.HasForeignKey(entity => entity.UserAddressId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
using CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// تنظیمات EF Core برای جزئیات سفارش فروشگاه تخفیفی
|
||||
/// </summary>
|
||||
public class DiscountOrderDetailConfiguration : IEntityTypeConfiguration<DiscountOrderDetail>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<DiscountOrderDetail> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
|
||||
builder.HasKey(entity => entity.Id);
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
|
||||
builder.Property(entity => entity.DiscountOrderId).IsRequired();
|
||||
builder.Property(entity => entity.ProductId).IsRequired();
|
||||
builder.Property(entity => entity.Count).IsRequired();
|
||||
builder.Property(entity => entity.UnitPrice).IsRequired();
|
||||
builder.Property(entity => entity.DiscountPercentUsed).IsRequired();
|
||||
builder.Property(entity => entity.DiscountAmount).IsRequired();
|
||||
builder.Property(entity => entity.FinalPrice).IsRequired();
|
||||
|
||||
// Relationship: Order -> OrderDetails
|
||||
builder
|
||||
.HasOne(entity => entity.DiscountOrder)
|
||||
.WithMany(entity => entity.OrderDetails)
|
||||
.HasForeignKey(entity => entity.DiscountOrderId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Relationship: Product
|
||||
builder
|
||||
.HasOne(entity => entity.Product)
|
||||
.WithMany(entity => entity.OrderDetails)
|
||||
.HasForeignKey(entity => entity.ProductId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
using CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// تنظیمات EF Core برای رابطه محصول و دستهبندی
|
||||
/// </summary>
|
||||
public class DiscountProductCategoryConfiguration : IEntityTypeConfiguration<DiscountProductCategory>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<DiscountProductCategory> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
|
||||
builder.HasKey(entity => entity.Id);
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
|
||||
builder.Property(entity => entity.ProductId).IsRequired();
|
||||
builder.Property(entity => entity.CategoryId).IsRequired();
|
||||
|
||||
// Many-to-Many relationship: Product <-> Category
|
||||
builder
|
||||
.HasOne(entity => entity.Product)
|
||||
.WithMany(entity => entity.ProductCategories)
|
||||
.HasForeignKey(entity => entity.ProductId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder
|
||||
.HasOne(entity => entity.Category)
|
||||
.WithMany(entity => entity.ProductCategories)
|
||||
.HasForeignKey(entity => entity.CategoryId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Unique constraint: یک محصول فقط یکبار در یک دسته
|
||||
builder.HasIndex(e => new { e.ProductId, e.CategoryId }).IsUnique();
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
using CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// تنظیمات EF Core برای محصول فروشگاه تخفیفی
|
||||
/// </summary>
|
||||
public class DiscountProductConfiguration : IEntityTypeConfiguration<DiscountProduct>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<DiscountProduct> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
|
||||
builder.HasKey(entity => entity.Id);
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
|
||||
builder.Property(entity => entity.Title)
|
||||
.IsRequired()
|
||||
.HasMaxLength(200);
|
||||
|
||||
builder.Property(entity => entity.ShortInfomation)
|
||||
.IsRequired()
|
||||
.HasMaxLength(500);
|
||||
|
||||
builder.Property(entity => entity.FullInformation)
|
||||
.IsRequired()
|
||||
.HasMaxLength(2000);
|
||||
|
||||
builder.Property(entity => entity.Price)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(entity => entity.MaxDiscountPercent)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(entity => entity.ImagePath)
|
||||
.IsRequired()
|
||||
.HasMaxLength(500);
|
||||
|
||||
builder.Property(entity => entity.ThumbnailPath)
|
||||
.IsRequired()
|
||||
.HasMaxLength(500);
|
||||
|
||||
builder.Property(entity => entity.IsActive)
|
||||
.IsRequired()
|
||||
.HasDefaultValue(true);
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
using CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// تنظیمات EF Core برای سبد خرید فروشگاه تخفیفی
|
||||
/// </summary>
|
||||
public class DiscountShoppingCartConfiguration : IEntityTypeConfiguration<DiscountShoppingCart>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<DiscountShoppingCart> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
|
||||
builder.HasKey(entity => entity.Id);
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
|
||||
builder.Property(entity => entity.UserId).IsRequired();
|
||||
builder.Property(entity => entity.ProductId).IsRequired();
|
||||
builder.Property(entity => entity.Count).IsRequired();
|
||||
|
||||
// Relationship: User -> ShoppingCarts
|
||||
builder
|
||||
.HasOne(entity => entity.User)
|
||||
.WithMany(entity => entity.DiscountShoppingCarts)
|
||||
.HasForeignKey(entity => entity.UserId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Relationship: Product -> ShoppingCarts
|
||||
builder
|
||||
.HasOne(entity => entity.Product)
|
||||
.WithMany(entity => entity.ShoppingCarts)
|
||||
.HasForeignKey(entity => entity.ProductId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Unique constraint: کاربر فقط یک ردیف برای هر محصول در سبد دارد
|
||||
builder.HasIndex(e => new { e.UserId, e.ProductId }).IsUnique();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -13,7 +13,7 @@ public class FactorDetailsConfiguration : IEntityTypeConfiguration<FactorDetails
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
builder
|
||||
.HasOne(entity => entity.Product)
|
||||
.WithMany(entity => entity.FactorDetailss)
|
||||
.WithMany(entity => entity.FactorDetails)
|
||||
.HasForeignKey(entity => entity.ProductId)
|
||||
.IsRequired(true);
|
||||
builder.Property(entity => entity.Count).IsRequired(true);
|
||||
@@ -21,7 +21,7 @@ public class FactorDetailsConfiguration : IEntityTypeConfiguration<FactorDetails
|
||||
builder.Property(entity => entity.UnitDiscount).IsRequired(true);
|
||||
builder
|
||||
.HasOne(entity => entity.Order)
|
||||
.WithMany(entity => entity.FactorDetailss)
|
||||
.WithMany(entity => entity.FactorDetails)
|
||||
.HasForeignKey(entity => entity.OrderId)
|
||||
.IsRequired(true);
|
||||
builder.Property(entity => entity.UnitDiscountPrice).IsRequired(true);
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
using CMSMicroservice.Domain.Entities.Payment;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
|
||||
public class ManualPaymentConfiguration : IEntityTypeConfiguration<ManualPayment>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ManualPayment> builder)
|
||||
{
|
||||
builder.ToTable("ManualPayments");
|
||||
|
||||
builder.HasKey(x => x.Id);
|
||||
|
||||
builder.Property(x => x.UserId)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.Amount)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.Type)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.Description)
|
||||
.IsRequired()
|
||||
.HasMaxLength(1000);
|
||||
|
||||
builder.Property(x => x.ReferenceNumber)
|
||||
.HasMaxLength(100);
|
||||
|
||||
builder.Property(x => x.Status)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.RequestedBy)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.ApprovedBy);
|
||||
|
||||
builder.Property(x => x.ApprovedAt);
|
||||
|
||||
builder.Property(x => x.RejectionReason)
|
||||
.HasMaxLength(500);
|
||||
|
||||
builder.Property(x => x.TransactionId);
|
||||
|
||||
// Relations
|
||||
builder.HasOne(x => x.User)
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.UserId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
builder.HasOne(x => x.Transaction)
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.TransactionId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// Indexes
|
||||
builder.HasIndex(x => x.UserId);
|
||||
builder.HasIndex(x => x.Status);
|
||||
builder.HasIndex(x => x.RequestedBy);
|
||||
builder.HasIndex(x => x.ApprovedBy);
|
||||
builder.HasIndex(x => x.Created);
|
||||
builder.HasIndex(x => new { x.UserId, x.Status });
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
using CMSMicroservice.Domain.Entities.Order;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
|
||||
public class OrderVATConfiguration : IEntityTypeConfiguration<OrderVAT>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<OrderVAT> builder)
|
||||
{
|
||||
builder.ToTable("OrderVATs");
|
||||
|
||||
builder.HasKey(x => x.Id);
|
||||
|
||||
builder.Property(x => x.OrderId)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.VATRate)
|
||||
.IsRequired()
|
||||
.HasColumnType("decimal(5,4)"); // 0.0900 (9%)
|
||||
|
||||
builder.Property(x => x.BaseAmount)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.VATAmount)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.TotalAmount)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.IsPaid)
|
||||
.IsRequired()
|
||||
.HasDefaultValue(false);
|
||||
|
||||
builder.Property(x => x.Note)
|
||||
.HasMaxLength(500);
|
||||
|
||||
// Foreign Key
|
||||
builder.HasOne(x => x.Order)
|
||||
.WithOne()
|
||||
.HasForeignKey<OrderVAT>(x => x.OrderId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// Indexes
|
||||
builder.HasIndex(x => x.OrderId)
|
||||
.IsUnique()
|
||||
.HasDatabaseName("IX_OrderVATs_OrderId");
|
||||
|
||||
builder.HasIndex(x => x.IsPaid)
|
||||
.HasDatabaseName("IX_OrderVATs_IsPaid");
|
||||
|
||||
builder.HasIndex(x => x.Created)
|
||||
.HasDatabaseName("IX_OrderVATs_Created");
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
public class ProductCategoryConfiguration : IEntityTypeConfiguration<ProductCategory>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ProductCategory> builder)
|
||||
{
|
||||
builder.ToTable("ProductCategories", "CMS");
|
||||
builder.HasKey(e => e.Id);
|
||||
|
||||
builder.HasOne(d => d.Product)
|
||||
.WithMany(p => p.ProductCategories)
|
||||
.HasForeignKey(d => d.ProductId);
|
||||
|
||||
builder.HasOne(d => d.Category)
|
||||
.WithMany(p => p.ProductCategories)
|
||||
.HasForeignKey(d => d.CategoryId);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -2,10 +2,10 @@ using CMSMicroservice.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
//توکن Otp
|
||||
public class ProductsConfiguration : IEntityTypeConfiguration<Products>
|
||||
//محصول
|
||||
public class ProductConfiguration : IEntityTypeConfiguration<Product>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Products> builder)
|
||||
public void Configure(EntityTypeBuilder<Product> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
+9
-9
@@ -2,24 +2,24 @@ using CMSMicroservice.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
//برچسب محصول
|
||||
public class PruductTagConfiguration : IEntityTypeConfiguration<PruductTag>
|
||||
//تنظیمات گالری تصاویر محصول
|
||||
public class ProductGalleriesConfiguration : IEntityTypeConfiguration<ProductGallery>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PruductTag> builder)
|
||||
public void Configure(EntityTypeBuilder<ProductGallery> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
builder.HasKey(entity => entity.Id);
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
builder
|
||||
.HasOne(entity => entity.Product)
|
||||
.WithMany(entity => entity.PruductTags)
|
||||
.HasForeignKey(entity => entity.ProductId)
|
||||
.HasOne(entity => entity.ProductImage)
|
||||
.WithMany(entity => entity.ProductGalleries)
|
||||
.HasForeignKey(entity => entity.ProductImageId)
|
||||
.IsRequired(true);
|
||||
builder
|
||||
.HasOne(entity => entity.Tag)
|
||||
.WithMany(entity => entity.PruductTags)
|
||||
.HasForeignKey(entity => entity.TagId)
|
||||
.HasOne(entity => entity.Product)
|
||||
.WithMany(entity => entity.ProductGalleries)
|
||||
.HasForeignKey(entity => entity.ProductId)
|
||||
.IsRequired(true);
|
||||
|
||||
}
|
||||
+9
-9
@@ -2,24 +2,24 @@ using CMSMicroservice.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
//دسته بندی
|
||||
public class PruductCategoryConfiguration : IEntityTypeConfiguration<PruductCategory>
|
||||
//تنظیمات گالری تصاویر محصول
|
||||
public class ProductGalleryConfiguration : IEntityTypeConfiguration<ProductGallery>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PruductCategory> builder)
|
||||
public void Configure(EntityTypeBuilder<ProductGallery> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
builder.HasKey(entity => entity.Id);
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
builder
|
||||
.HasOne(entity => entity.Product)
|
||||
.WithMany(entity => entity.PruductCategorys)
|
||||
.HasForeignKey(entity => entity.ProductId)
|
||||
.HasOne(entity => entity.ProductImage)
|
||||
.WithMany(entity => entity.ProductGalleries)
|
||||
.HasForeignKey(entity => entity.ProductImageId)
|
||||
.IsRequired(true);
|
||||
builder
|
||||
.HasOne(entity => entity.Category)
|
||||
.WithMany(entity => entity.PruductCategorys)
|
||||
.HasForeignKey(entity => entity.CategoryId)
|
||||
.HasOne(entity => entity.Product)
|
||||
.WithMany(entity => entity.ProductGalleries)
|
||||
.HasForeignKey(entity => entity.ProductId)
|
||||
.IsRequired(true);
|
||||
|
||||
}
|
||||
+4
-4
@@ -3,9 +3,9 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
//توکن Otp
|
||||
public class ProductGallerysConfiguration : IEntityTypeConfiguration<ProductGallerys>
|
||||
public class ProductGallerysConfiguration : IEntityTypeConfiguration<ProductGallery>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ProductGallerys> builder)
|
||||
public void Configure(EntityTypeBuilder<ProductGallery> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
@@ -13,12 +13,12 @@ public class ProductGallerysConfiguration : IEntityTypeConfiguration<ProductGall
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
builder
|
||||
.HasOne(entity => entity.ProductImage)
|
||||
.WithMany(entity => entity.ProductGalleryss)
|
||||
.WithMany(entity => entity.ProductGalleries)
|
||||
.HasForeignKey(entity => entity.ProductImageId)
|
||||
.IsRequired(true);
|
||||
builder
|
||||
.HasOne(entity => entity.Product)
|
||||
.WithMany(entity => entity.ProductGalleryss)
|
||||
.WithMany(entity => entity.ProductGalleries)
|
||||
.HasForeignKey(entity => entity.ProductId)
|
||||
.IsRequired(true);
|
||||
|
||||
|
||||
+3
-3
@@ -2,10 +2,10 @@ using CMSMicroservice.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
//توکن Otp
|
||||
public class ProductImagesConfiguration : IEntityTypeConfiguration<ProductImages>
|
||||
//تصاویر محصول
|
||||
public class ProductImageConfiguration : IEntityTypeConfiguration<ProductImage>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ProductImages> builder)
|
||||
public void Configure(EntityTypeBuilder<ProductImage> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
public class ProductTagConfiguration : IEntityTypeConfiguration<ProductTag>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ProductTag> builder)
|
||||
{
|
||||
builder.ToTable("ProductTags", "CMS");
|
||||
builder.HasKey(e => e.Id);
|
||||
|
||||
builder.HasOne(d => d.Product)
|
||||
.WithMany(p => p.ProductTags)
|
||||
.HasForeignKey(d => d.ProductId);
|
||||
|
||||
builder.HasOne(d => d.Tag)
|
||||
.WithMany(p => p.ProductTags)
|
||||
.HasForeignKey(d => d.TagId);
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
using CMSMicroservice.Domain.Entities.Message;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
|
||||
public class PublicMessageConfiguration : IEntityTypeConfiguration<PublicMessage>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PublicMessage> builder)
|
||||
{
|
||||
builder.ToTable("PublicMessages");
|
||||
|
||||
builder.HasKey(x => x.Id);
|
||||
|
||||
builder.Property(x => x.Title)
|
||||
.IsRequired()
|
||||
.HasMaxLength(200);
|
||||
|
||||
builder.Property(x => x.Content)
|
||||
.IsRequired()
|
||||
.HasMaxLength(2000);
|
||||
|
||||
builder.Property(x => x.Type)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.Priority)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.IsActive)
|
||||
.IsRequired()
|
||||
.HasDefaultValue(true);
|
||||
|
||||
builder.Property(x => x.StartsAt)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.ExpiresAt)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.CreatedByUserId)
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(x => x.ViewCount)
|
||||
.IsRequired()
|
||||
.HasDefaultValue(0);
|
||||
|
||||
builder.Property(x => x.LinkUrl)
|
||||
.HasMaxLength(500);
|
||||
|
||||
builder.Property(x => x.LinkText)
|
||||
.HasMaxLength(100);
|
||||
|
||||
// Indexes
|
||||
builder.HasIndex(x => x.IsActive)
|
||||
.HasDatabaseName("IX_PublicMessages_IsActive");
|
||||
|
||||
builder.HasIndex(x => x.Type)
|
||||
.HasDatabaseName("IX_PublicMessages_Type");
|
||||
|
||||
builder.HasIndex(x => x.Priority)
|
||||
.HasDatabaseName("IX_PublicMessages_Priority");
|
||||
|
||||
builder.HasIndex(x => x.StartsAt)
|
||||
.HasDatabaseName("IX_PublicMessages_StartsAt");
|
||||
|
||||
builder.HasIndex(x => x.ExpiresAt)
|
||||
.HasDatabaseName("IX_PublicMessages_ExpiresAt");
|
||||
|
||||
builder.HasIndex(x => x.CreatedByUserId)
|
||||
.HasDatabaseName("IX_PublicMessages_CreatedByUserId");
|
||||
|
||||
builder.HasIndex(x => new { x.IsActive, x.ExpiresAt })
|
||||
.HasDatabaseName("IX_PublicMessages_IsActive_ExpiresAt");
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -2,10 +2,10 @@ using CMSMicroservice.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
//آدرس کاربر
|
||||
public class TransactionsConfiguration : IEntityTypeConfiguration<Transactions>
|
||||
//تراکنش
|
||||
public class TransactionConfiguration : IEntityTypeConfiguration<Transaction>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Transactions> builder)
|
||||
public void Configure(EntityTypeBuilder<Transaction> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
+1
-1
@@ -13,7 +13,7 @@ public class UserAddressConfiguration : IEntityTypeConfiguration<UserAddress>
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
builder
|
||||
.HasOne(entity => entity.User)
|
||||
.WithMany(entity => entity.UserAddresss)
|
||||
.WithMany(entity => entity.UserAddresses)
|
||||
.HasForeignKey(entity => entity.UserId)
|
||||
.IsRequired(true);
|
||||
builder.Property(entity => entity.Title).IsRequired(true);
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
//تنظیمات سبد خرید کاربر
|
||||
public class UserCartConfiguration : IEntityTypeConfiguration<UserCart>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<UserCart> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
builder.HasKey(entity => entity.Id);
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
builder
|
||||
.HasOne(entity => entity.Product)
|
||||
.WithMany(entity => entity.UserCarts)
|
||||
.HasForeignKey(entity => entity.ProductId)
|
||||
.IsRequired(true);
|
||||
builder
|
||||
.HasOne(entity => entity.User)
|
||||
.WithMany(entity => entity.UserCarts)
|
||||
.HasForeignKey(entity => entity.UserId)
|
||||
.IsRequired(true);
|
||||
builder.Property(entity => entity.Count).IsRequired(true);
|
||||
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -3,9 +3,9 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
//آدرس کاربر
|
||||
public class UserCartsConfiguration : IEntityTypeConfiguration<UserCarts>
|
||||
public class UserCartsConfiguration : IEntityTypeConfiguration<UserCart>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<UserCarts> builder)
|
||||
public void Configure(EntityTypeBuilder<UserCart> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
@@ -13,12 +13,12 @@ public class UserCartsConfiguration : IEntityTypeConfiguration<UserCarts>
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
builder
|
||||
.HasOne(entity => entity.Product)
|
||||
.WithMany(entity => entity.UserCartss)
|
||||
.WithMany(entity => entity.UserCarts)
|
||||
.HasForeignKey(entity => entity.ProductId)
|
||||
.IsRequired(true);
|
||||
builder
|
||||
.HasOne(entity => entity.User)
|
||||
.WithMany(entity => entity.UserCartss)
|
||||
.WithMany(entity => entity.UserCarts)
|
||||
.HasForeignKey(entity => entity.UserId)
|
||||
.IsRequired(true);
|
||||
builder.Property(entity => entity.Count).IsRequired(true);
|
||||
|
||||
@@ -16,11 +16,6 @@ public class UserConfiguration : IEntityTypeConfiguration<User>
|
||||
builder.Property(entity => entity.Mobile).IsRequired(true);
|
||||
builder.Property(entity => entity.NationalCode).IsRequired(false);
|
||||
builder.Property(entity => entity.AvatarPath).IsRequired(false);
|
||||
builder
|
||||
.HasOne(entity => entity.Parent)
|
||||
.WithMany(entity => entity.Users)
|
||||
.HasForeignKey(entity => entity.ParentId)
|
||||
.IsRequired(false);
|
||||
builder.Property(entity => entity.ReferralCode).IsRequired(true);
|
||||
builder.Property(entity => entity.IsMobileVerified ).IsRequired(true);
|
||||
builder.Property(entity => entity.MobileVerifiedAt).IsRequired(false);
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||
|
||||
/// <summary>
|
||||
/// خرید پکیج توسط کاربر
|
||||
/// </summary>
|
||||
public class UserPackagePurchaseConfiguration : IEntityTypeConfiguration<UserPackagePurchase>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<UserPackagePurchase> builder)
|
||||
{
|
||||
builder.HasQueryFilter(p => !p.IsDeleted);
|
||||
builder.Ignore(entity => entity.DomainEvents);
|
||||
|
||||
builder.HasKey(entity => entity.Id);
|
||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||
|
||||
builder.Property(entity => entity.UserId).IsRequired();
|
||||
builder.Property(entity => entity.PackageId).IsRequired();
|
||||
builder.Property(entity => entity.PurchaseMethod).IsRequired();
|
||||
builder.Property(entity => entity.PurchasedAt).IsRequired();
|
||||
builder.Property(entity => entity.Amount).IsRequired();
|
||||
builder.Property(entity => entity.OrderId).IsRequired(false);
|
||||
builder.Property(entity => entity.TransactionId).IsRequired(false);
|
||||
|
||||
// رابطه با User
|
||||
builder.HasOne(entity => entity.User)
|
||||
.WithMany() // User can have multiple package purchases
|
||||
.HasForeignKey(entity => entity.UserId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// رابطه با Package
|
||||
builder.HasOne(entity => entity.Package)
|
||||
.WithMany()
|
||||
.HasForeignKey(entity => entity.PackageId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// رابطه با UserOrder (اختیاری)
|
||||
builder.HasOne(entity => entity.Order)
|
||||
.WithMany()
|
||||
.HasForeignKey(entity => entity.OrderId)
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired(false);
|
||||
|
||||
// رابطه با Transaction (اختیاری)
|
||||
builder.HasOne(entity => entity.Transaction)
|
||||
.WithMany()
|
||||
.HasForeignKey(entity => entity.TransactionId)
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired(false);
|
||||
|
||||
// Index برای UserId (برای کوئری سریع)
|
||||
builder.HasIndex(e => e.UserId)
|
||||
.HasDatabaseName("IX_UserPackagePurchase_UserId");
|
||||
|
||||
// Index برای PackageId
|
||||
builder.HasIndex(e => e.PackageId)
|
||||
.HasDatabaseName("IX_UserPackagePurchase_PackageId");
|
||||
|
||||
// Index برای PurchasedAt (برای فیلتر زمانی)
|
||||
builder.HasIndex(e => e.PurchasedAt)
|
||||
.HasDatabaseName("IX_UserPackagePurchase_PurchasedAt");
|
||||
|
||||
// Composite Index برای UserId + PurchasedAt (کوئریهای متداول)
|
||||
builder.HasIndex(e => new { e.UserId, e.PurchasedAt })
|
||||
.HasDatabaseName("IX_UserPackagePurchase_UserId_PurchasedAt");
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -171,7 +171,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -813,7 +813,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -171,7 +171,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -816,7 +816,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -214,7 +214,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -905,7 +905,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -267,7 +267,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -1088,7 +1088,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -267,7 +267,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -1091,7 +1091,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -267,7 +267,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -1044,7 +1044,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -267,7 +267,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -1053,7 +1053,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -267,7 +267,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -1062,7 +1062,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -937,7 +937,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -1857,7 +1857,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -961,7 +961,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -1881,7 +1881,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -1031,7 +1031,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -1951,7 +1951,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -1042,7 +1042,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -1962,7 +1962,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
Generated
+2
-2
@@ -1042,7 +1042,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -1965,7 +1965,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -1099,7 +1099,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -2045,7 +2045,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -1111,7 +1111,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -2060,7 +2060,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2
-2
@@ -1111,7 +1111,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("Packages", "CMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
@@ -2066,7 +2066,7 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGallerys", b =>
|
||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.ProductGalleries", b =>
|
||||
{
|
||||
b.HasOne("CMSMicroservice.Domain.Entities.Products", "Product")
|
||||
.WithMany("ProductGalleryss")
|
||||
|
||||
+2373
File diff suppressed because it is too large
Load Diff
+55
@@ -0,0 +1,55 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RemoveParentIdFromUser : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Users_Users_ParentId",
|
||||
schema: "CMS",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Users_ParentId",
|
||||
schema: "CMS",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ParentId",
|
||||
schema: "CMS",
|
||||
table: "Users");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<long>(
|
||||
name: "ParentId",
|
||||
schema: "CMS",
|
||||
table: "Users",
|
||||
type: "bigint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_ParentId",
|
||||
schema: "CMS",
|
||||
table: "Users",
|
||||
column: "ParentId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Users_Users_ParentId",
|
||||
schema: "CMS",
|
||||
table: "Users",
|
||||
column: "ParentId",
|
||||
principalSchema: "CMS",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2376
File diff suppressed because it is too large
Load Diff
+31
@@ -0,0 +1,31 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddGiftValueToClubMembership : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<long>(
|
||||
name: "GiftValue",
|
||||
schema: "CMS",
|
||||
table: "ClubMemberships",
|
||||
type: "bigint",
|
||||
nullable: false,
|
||||
defaultValue: 0L);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "GiftValue",
|
||||
schema: "CMS",
|
||||
table: "ClubMemberships");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2474
File diff suppressed because it is too large
Load Diff
+112
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddUserPackagePurchase : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "UserPackagePurchases",
|
||||
schema: "CMS",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
UserId = table.Column<long>(type: "bigint", nullable: false),
|
||||
PackageId = table.Column<long>(type: "bigint", nullable: false),
|
||||
PurchaseMethod = table.Column<int>(type: "int", nullable: false),
|
||||
PurchasedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
Amount = table.Column<long>(type: "bigint", nullable: false),
|
||||
OrderId = table.Column<long>(type: "bigint", nullable: true),
|
||||
TransactionId = table.Column<long>(type: "bigint", nullable: true),
|
||||
Created = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
LastModified = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
LastModifiedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_UserPackagePurchases", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_UserPackagePurchases_Packages_PackageId",
|
||||
column: x => x.PackageId,
|
||||
principalSchema: "CMS",
|
||||
principalTable: "Packages",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_UserPackagePurchases_Transactionss_TransactionId",
|
||||
column: x => x.TransactionId,
|
||||
principalSchema: "CMS",
|
||||
principalTable: "Transactionss",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_UserPackagePurchases_UserOrders_OrderId",
|
||||
column: x => x.OrderId,
|
||||
principalSchema: "CMS",
|
||||
principalTable: "UserOrders",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_UserPackagePurchases_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalSchema: "CMS",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_UserPackagePurchase_PackageId",
|
||||
schema: "CMS",
|
||||
table: "UserPackagePurchases",
|
||||
column: "PackageId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_UserPackagePurchase_PurchasedAt",
|
||||
schema: "CMS",
|
||||
table: "UserPackagePurchases",
|
||||
column: "PurchasedAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_UserPackagePurchase_UserId",
|
||||
schema: "CMS",
|
||||
table: "UserPackagePurchases",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_UserPackagePurchase_UserId_PurchasedAt",
|
||||
schema: "CMS",
|
||||
table: "UserPackagePurchases",
|
||||
columns: new[] { "UserId", "PurchasedAt" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_UserPackagePurchases_OrderId",
|
||||
schema: "CMS",
|
||||
table: "UserPackagePurchases",
|
||||
column: "OrderId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_UserPackagePurchases_TransactionId",
|
||||
schema: "CMS",
|
||||
table: "UserPackagePurchases",
|
||||
column: "TransactionId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "UserPackagePurchases",
|
||||
schema: "CMS");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2474
File diff suppressed because it is too large
Load Diff
+42
@@ -0,0 +1,42 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddClubMembershipGiftValueConfiguration : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
// اضافه کردن تنظیمات Club.MembershipGiftValue
|
||||
migrationBuilder.Sql(@"
|
||||
INSERT INTO ""SystemConfigurations""
|
||||
(""Key"", ""Value"", ""Description"", ""Scope"", ""IsActive"", ""Created"", ""CreatedBy"")
|
||||
SELECT
|
||||
'Club.MembershipGiftValue',
|
||||
'25200000',
|
||||
'مبلغ هدیه حق عضویت باشگاه (ریال) - این مبلغ از کیف پول کم نمیشود',
|
||||
1, -- ConfigurationScope.Club = 1
|
||||
true,
|
||||
NOW(),
|
||||
'System'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM ""SystemConfigurations""
|
||||
WHERE ""Key"" = 'Club.MembershipGiftValue'
|
||||
);
|
||||
");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
// حذف تنظیمات Club.MembershipGiftValue
|
||||
migrationBuilder.Sql(@"
|
||||
DELETE FROM ""SystemConfigurations""
|
||||
WHERE ""Key"" = 'Club.MembershipGiftValue';
|
||||
");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2571
File diff suppressed because it is too large
Load Diff
+108
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddManualPaymentSystem : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ManualPayments",
|
||||
schema: "CMS",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
UserId = table.Column<long>(type: "bigint", nullable: false),
|
||||
Amount = table.Column<long>(type: "bigint", nullable: false),
|
||||
Type = table.Column<int>(type: "int", nullable: false),
|
||||
Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: false),
|
||||
ReferenceNumber = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
Status = table.Column<int>(type: "int", nullable: false),
|
||||
RequestedBy = table.Column<long>(type: "bigint", nullable: false),
|
||||
ApprovedBy = table.Column<long>(type: "bigint", nullable: true),
|
||||
ApprovedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
RejectionReason = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||
TransactionId = table.Column<long>(type: "bigint", nullable: true),
|
||||
Created = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
LastModified = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
LastModifiedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ManualPayments", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_ManualPayments_Transactionss_TransactionId",
|
||||
column: x => x.TransactionId,
|
||||
principalSchema: "CMS",
|
||||
principalTable: "Transactionss",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_ManualPayments_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalSchema: "CMS",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ManualPayments_ApprovedBy",
|
||||
schema: "CMS",
|
||||
table: "ManualPayments",
|
||||
column: "ApprovedBy");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ManualPayments_Created",
|
||||
schema: "CMS",
|
||||
table: "ManualPayments",
|
||||
column: "Created");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ManualPayments_RequestedBy",
|
||||
schema: "CMS",
|
||||
table: "ManualPayments",
|
||||
column: "RequestedBy");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ManualPayments_Status",
|
||||
schema: "CMS",
|
||||
table: "ManualPayments",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ManualPayments_TransactionId",
|
||||
schema: "CMS",
|
||||
table: "ManualPayments",
|
||||
column: "TransactionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ManualPayments_UserId",
|
||||
schema: "CMS",
|
||||
table: "ManualPayments",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ManualPayments_UserId_Status",
|
||||
schema: "CMS",
|
||||
table: "ManualPayments",
|
||||
columns: new[] { "UserId", "Status" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "ManualPayments",
|
||||
schema: "CMS");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2663
File diff suppressed because it is too large
Load Diff
+94
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddPublicMessageSystem : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PublicMessages",
|
||||
schema: "CMS",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
Title = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
||||
Content = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false),
|
||||
Type = table.Column<int>(type: "int", nullable: false),
|
||||
Priority = table.Column<int>(type: "int", nullable: false),
|
||||
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
|
||||
StartsAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
ExpiresAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
CreatedByUserId = table.Column<long>(type: "bigint", nullable: false),
|
||||
ViewCount = table.Column<int>(type: "int", nullable: false, defaultValue: 0),
|
||||
LinkUrl = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||
LinkText = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||
Created = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
LastModified = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
LastModifiedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PublicMessages", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PublicMessages_CreatedByUserId",
|
||||
schema: "CMS",
|
||||
table: "PublicMessages",
|
||||
column: "CreatedByUserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PublicMessages_ExpiresAt",
|
||||
schema: "CMS",
|
||||
table: "PublicMessages",
|
||||
column: "ExpiresAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PublicMessages_IsActive",
|
||||
schema: "CMS",
|
||||
table: "PublicMessages",
|
||||
column: "IsActive");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PublicMessages_IsActive_ExpiresAt",
|
||||
schema: "CMS",
|
||||
table: "PublicMessages",
|
||||
columns: new[] { "IsActive", "ExpiresAt" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PublicMessages_Priority",
|
||||
schema: "CMS",
|
||||
table: "PublicMessages",
|
||||
column: "Priority");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PublicMessages_StartsAt",
|
||||
schema: "CMS",
|
||||
table: "PublicMessages",
|
||||
column: "StartsAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PublicMessages_Type",
|
||||
schema: "CMS",
|
||||
table: "PublicMessages",
|
||||
column: "Type");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "PublicMessages",
|
||||
schema: "CMS");
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+2753
File diff suppressed because it is too large
Load Diff
+125
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddVATSystem : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "HasVAT",
|
||||
schema: "CMS",
|
||||
table: "UserOrders",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<long>(
|
||||
name: "OrderVATId",
|
||||
schema: "CMS",
|
||||
table: "UserOrders",
|
||||
type: "bigint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OrderVATs",
|
||||
schema: "CMS",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
OrderId = table.Column<long>(type: "bigint", nullable: false),
|
||||
VATRate = table.Column<decimal>(type: "decimal(5,4)", nullable: false),
|
||||
BaseAmount = table.Column<long>(type: "bigint", nullable: false),
|
||||
VATAmount = table.Column<long>(type: "bigint", nullable: false),
|
||||
TotalAmount = table.Column<long>(type: "bigint", nullable: false),
|
||||
IsPaid = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||
PaidAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
Note = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||
Created = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
CreatedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
LastModified = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
LastModifiedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OrderVATs", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OrderVATs_UserOrders_OrderId",
|
||||
column: x => x.OrderId,
|
||||
principalSchema: "CMS",
|
||||
principalTable: "UserOrders",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_UserOrders_OrderVATId",
|
||||
schema: "CMS",
|
||||
table: "UserOrders",
|
||||
column: "OrderVATId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OrderVATs_Created",
|
||||
schema: "CMS",
|
||||
table: "OrderVATs",
|
||||
column: "Created");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OrderVATs_IsPaid",
|
||||
schema: "CMS",
|
||||
table: "OrderVATs",
|
||||
column: "IsPaid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OrderVATs_OrderId",
|
||||
schema: "CMS",
|
||||
table: "OrderVATs",
|
||||
column: "OrderId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_UserOrders_OrderVATs_OrderVATId",
|
||||
schema: "CMS",
|
||||
table: "UserOrders",
|
||||
column: "OrderVATId",
|
||||
principalSchema: "CMS",
|
||||
principalTable: "OrderVATs",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_UserOrders_OrderVATs_OrderVATId",
|
||||
schema: "CMS",
|
||||
table: "UserOrders");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OrderVATs",
|
||||
schema: "CMS");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_UserOrders_OrderVATId",
|
||||
schema: "CMS",
|
||||
table: "UserOrders");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "HasVAT",
|
||||
schema: "CMS",
|
||||
table: "UserOrders");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "OrderVATId",
|
||||
schema: "CMS",
|
||||
table: "UserOrders");
|
||||
}
|
||||
}
|
||||
}
|
||||
+3212
File diff suppressed because it is too large
Load Diff
+1330
File diff suppressed because it is too large
Load Diff
+950
-124
File diff suppressed because it is too large
Load Diff
@@ -1,367 +0,0 @@
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSMicroservice.Infrastructure.Services.Payment;
|
||||
|
||||
/// <summary>
|
||||
/// Real Implementation برای درگاه پرداخت بانک ملت (IPG)
|
||||
/// بانک ملت از SOAP Web Service استفاده میکند
|
||||
/// برای فعالسازی: باید TerminalId, Username, Password را در appsettings.json تنظیم کنید
|
||||
/// </summary>
|
||||
public class BankMellatPaymentService : IPaymentGatewayService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger<BankMellatPaymentService> _logger;
|
||||
private readonly string _terminalId;
|
||||
private readonly string _username;
|
||||
private readonly string _password;
|
||||
private readonly string _serviceUrl;
|
||||
|
||||
public BankMellatPaymentService(
|
||||
HttpClient httpClient,
|
||||
IConfiguration configuration,
|
||||
ILogger<BankMellatPaymentService> logger)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
|
||||
// خواندن تنظیمات از appsettings.json
|
||||
_terminalId = _configuration["BankMellat:TerminalId"] ?? throw new InvalidOperationException(
|
||||
"BankMellat:TerminalId is not configured");
|
||||
_username = _configuration["BankMellat:Username"] ?? throw new InvalidOperationException(
|
||||
"BankMellat:Username is not configured");
|
||||
_password = _configuration["BankMellat:Password"] ?? throw new InvalidOperationException(
|
||||
"BankMellat:Password is not configured");
|
||||
_serviceUrl = _configuration["BankMellat:ServiceUrl"] ?? "https://bpm.shaparak.ir/pgwchannel/services/pgw";
|
||||
|
||||
_httpClient.Timeout = TimeSpan.FromSeconds(30);
|
||||
}
|
||||
|
||||
public async Task<PaymentInitiateResult> InitiatePaymentAsync(
|
||||
PaymentRequest request,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Initiating Bank Mellat payment: UserId={UserId}, Amount={Amount}",
|
||||
request.UserId, request.Amount);
|
||||
|
||||
// تبدیل مبلغ به ریال (بانک ملت ریال میخواهد)
|
||||
var amountInRials = (long)(request.Amount * 10);
|
||||
var localDate = DateTime.Now.ToString("yyyyMMdd");
|
||||
var localTime = DateTime.Now.ToString("HHmmss");
|
||||
var orderId = $"{request.UserId}_{DateTime.Now.Ticks}";
|
||||
|
||||
// ساخت SOAP Request
|
||||
var soapRequest = $@"
|
||||
<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""
|
||||
xmlns:ns=""http://interfaces.core.sw.bps.com/"">
|
||||
<soap:Body>
|
||||
<ns:bpPayRequest>
|
||||
<terminalId>{_terminalId}</terminalId>
|
||||
<userName>{_username}</userName>
|
||||
<userPassword>{_password}</userPassword>
|
||||
<orderId>{orderId}</orderId>
|
||||
<amount>{amountInRials}</amount>
|
||||
<localDate>{localDate}</localDate>
|
||||
<localTime>{localTime}</localTime>
|
||||
<additionalData>{request.Description}</additionalData>
|
||||
<callBackUrl>{request.CallbackUrl}</callBackUrl>
|
||||
<payerId>0</payerId>
|
||||
</ns:bpPayRequest>
|
||||
</soap:Body>
|
||||
</soap:Envelope>";
|
||||
|
||||
var content = new StringContent(soapRequest, Encoding.UTF8, "text/xml");
|
||||
content.Headers.Add("SOAPAction", "http://interfaces.core.sw.bps.com/IPaymentGateway/bpPayRequest");
|
||||
|
||||
var response = await _httpClient.PostAsync(_serviceUrl, content, cancellationToken);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
_logger.LogError(
|
||||
"Bank Mellat API error: StatusCode={StatusCode}",
|
||||
response.StatusCode);
|
||||
|
||||
return new PaymentInitiateResult
|
||||
{
|
||||
IsSuccess = false,
|
||||
ErrorMessage = $"خطا در ارتباط با بانک ملت: {response.StatusCode}"
|
||||
};
|
||||
}
|
||||
|
||||
var responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
var refId = ParseSoapResponse(responseContent, "return");
|
||||
|
||||
// بررسی کد خطا
|
||||
if (string.IsNullOrEmpty(refId) || !long.TryParse(refId, out var refIdNumber))
|
||||
{
|
||||
_logger.LogError("Invalid RefId from Bank Mellat: {RefId}", refId);
|
||||
return new PaymentInitiateResult
|
||||
{
|
||||
IsSuccess = false,
|
||||
ErrorMessage = "پاسخ نامعتبر از بانک ملت"
|
||||
};
|
||||
}
|
||||
|
||||
if (refIdNumber < 0)
|
||||
{
|
||||
var errorMessage = GetBankMellatErrorMessage(refIdNumber.ToString());
|
||||
_logger.LogError("Bank Mellat error code: {ErrorCode} - {Message}", refIdNumber, errorMessage);
|
||||
return new PaymentInitiateResult
|
||||
{
|
||||
IsSuccess = false,
|
||||
ErrorMessage = errorMessage
|
||||
};
|
||||
}
|
||||
|
||||
_logger.LogInformation(
|
||||
"Bank Mellat payment initiated successfully: RefId={RefId}",
|
||||
refId);
|
||||
|
||||
// URL درگاه بانک ملت
|
||||
var gatewayUrl = $"https://bpm.shaparak.ir/pgwchannel/startpay.mellat?RefId={refId}";
|
||||
|
||||
return new PaymentInitiateResult
|
||||
{
|
||||
IsSuccess = true,
|
||||
RefId = refId,
|
||||
GatewayUrl = gatewayUrl,
|
||||
ErrorMessage = null
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error in InitiatePaymentAsync");
|
||||
return new PaymentInitiateResult
|
||||
{
|
||||
IsSuccess = false,
|
||||
ErrorMessage = "خطای غیرمنتظره در برقراری ارتباط با بانک"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<PaymentVerificationResult> VerifyPaymentAsync(
|
||||
string refId,
|
||||
string verificationToken,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("Verifying Bank Mellat payment: RefId={RefId}", refId);
|
||||
|
||||
// ساخت SOAP Request برای Verify
|
||||
var soapRequest = $@"
|
||||
<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""
|
||||
xmlns:ns=""http://interfaces.core.sw.bps.com/"">
|
||||
<soap:Body>
|
||||
<ns:bpVerifyRequest>
|
||||
<terminalId>{_terminalId}</terminalId>
|
||||
<userName>{_username}</userName>
|
||||
<userPassword>{_password}</userPassword>
|
||||
<orderId>{verificationToken}</orderId>
|
||||
<saleOrderId>{verificationToken}</saleOrderId>
|
||||
<saleReferenceId>{refId}</saleReferenceId>
|
||||
</ns:bpVerifyRequest>
|
||||
</soap:Body>
|
||||
</soap:Envelope>";
|
||||
|
||||
var content = new StringContent(soapRequest, Encoding.UTF8, "text/xml");
|
||||
content.Headers.Add("SOAPAction", "http://interfaces.core.sw.bps.com/IPaymentGateway/bpVerifyRequest");
|
||||
|
||||
var response = await _httpClient.PostAsync(_serviceUrl, content, cancellationToken);
|
||||
var responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
var result = ParseSoapResponse(responseContent, "return");
|
||||
|
||||
var isSuccess = result == "0"; // 0 = موفق
|
||||
|
||||
if (isSuccess)
|
||||
{
|
||||
// اگر Verify موفق بود، باید Settle کنیم
|
||||
await SettlePaymentAsync(refId, verificationToken, cancellationToken);
|
||||
}
|
||||
|
||||
_logger.LogInformation(
|
||||
"Bank Mellat verification result: RefId={RefId}, IsSuccess={IsSuccess}",
|
||||
refId, isSuccess);
|
||||
|
||||
return new PaymentVerificationResult
|
||||
{
|
||||
IsSuccess = isSuccess,
|
||||
RefId = refId,
|
||||
TrackingCode = refId,
|
||||
Amount = 0, // مبلغ باید از Database بیاید
|
||||
Message = isSuccess ? "تراکنش موفق" : GetBankMellatErrorMessage(result)
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error in VerifyPaymentAsync");
|
||||
return new PaymentVerificationResult
|
||||
{
|
||||
IsSuccess = false,
|
||||
RefId = refId,
|
||||
Message = "خطا در تأیید پرداخت"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SettlePaymentAsync(string refId, string orderId, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var soapRequest = $@"
|
||||
<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""
|
||||
xmlns:ns=""http://interfaces.core.sw.bps.com/"">
|
||||
<soap:Body>
|
||||
<ns:bpSettleRequest>
|
||||
<terminalId>{_terminalId}</terminalId>
|
||||
<userName>{_username}</userName>
|
||||
<userPassword>{_password}</userPassword>
|
||||
<orderId>{orderId}</orderId>
|
||||
<saleOrderId>{orderId}</saleOrderId>
|
||||
<saleReferenceId>{refId}</saleReferenceId>
|
||||
</ns:bpSettleRequest>
|
||||
</soap:Body>
|
||||
</soap:Envelope>";
|
||||
|
||||
var content = new StringContent(soapRequest, Encoding.UTF8, "text/xml");
|
||||
content.Headers.Add("SOAPAction", "http://interfaces.core.sw.bps.com/IPaymentGateway/bpSettleRequest");
|
||||
|
||||
var response = await _httpClient.PostAsync(_serviceUrl, content, cancellationToken);
|
||||
var responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||
var result = ParseSoapResponse(responseContent, "return");
|
||||
|
||||
var isSuccess = result == "0";
|
||||
_logger.LogInformation(
|
||||
"Bank Mellat settle result: RefId={RefId}, IsSuccess={IsSuccess}",
|
||||
refId, isSuccess);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error in SettlePaymentAsync");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<PayoutResult> ProcessPayoutAsync(
|
||||
PayoutRequest request,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Processing Bank Mellat payout: UserId={UserId}, Amount={Amount}, IBAN={Iban}",
|
||||
request.UserId, request.Amount, request.Iban);
|
||||
|
||||
// Validation
|
||||
if (!request.Iban.StartsWith("IR") || request.Iban.Length != 26)
|
||||
{
|
||||
return new PayoutResult
|
||||
{
|
||||
IsSuccess = false,
|
||||
Message = "فرمت شماره شبا نامعتبر است",
|
||||
ProcessedAt = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
if (request.Amount < 10_000)
|
||||
{
|
||||
return new PayoutResult
|
||||
{
|
||||
IsSuccess = false,
|
||||
Message = "حداقل مبلغ برداشت 10,000 تومان است",
|
||||
ProcessedAt = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: بانک ملت ممکن است API واریز مستقیم نداشته باشد
|
||||
// در این صورت باید از Shaparak Paya (سامانه پایا) استفاده کرد
|
||||
// یا از سرویسهای واسط مانند Fanapay, IPG.ir استفاده شود
|
||||
|
||||
_logger.LogWarning(
|
||||
"Bank Mellat direct payout is not supported. Use Shaparak Paya or third-party service.");
|
||||
|
||||
return new PayoutResult
|
||||
{
|
||||
IsSuccess = false,
|
||||
Message = "واریز مستقیم از طریق بانک ملت پشتیبانی نمیشود. از سامانه پایا استفاده کنید.",
|
||||
ProcessedAt = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error in ProcessPayoutAsync");
|
||||
return new PayoutResult
|
||||
{
|
||||
IsSuccess = false,
|
||||
Message = "خطا در پردازش واریز",
|
||||
ProcessedAt = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to parse SOAP XML response
|
||||
private string ParseSoapResponse(string soapResponse, string elementName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var doc = XDocument.Parse(soapResponse);
|
||||
var ns = doc.Root?.GetDefaultNamespace();
|
||||
var element = doc.Descendants(ns + elementName).FirstOrDefault();
|
||||
return element?.Value ?? string.Empty;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
// کدهای خطای بانک ملت
|
||||
private string GetBankMellatErrorMessage(string errorCode)
|
||||
{
|
||||
return errorCode switch
|
||||
{
|
||||
"0" => "تراکنش موفق",
|
||||
"11" => "شماره کارت نامعتبر است",
|
||||
"12" => "موجودی کافی نیست",
|
||||
"13" => "رمز نادرست است",
|
||||
"14" => "تعداد دفعات وارد کردن رمز بیش از حد مجاز است",
|
||||
"15" => "کارت نامعتبر است",
|
||||
"16" => "دفعات برداشت وجه بیش از حد مجاز است",
|
||||
"17" => "کاربر از انجام تراکنش منصرف شده است",
|
||||
"18" => "تاریخ انقضای کارت گذشته است",
|
||||
"19" => "مبلغ برداشت وجه بیش از حد مجاز است",
|
||||
"21" => "پذیرنده نامعتبر است",
|
||||
"23" => "خطای امنیتی رخ داده است",
|
||||
"24" => "اطلاعات کاربری پذیرنده نامعتبر است",
|
||||
"25" => "مبلغ نامعتبر است",
|
||||
"31" => "پاسخ نامعتبر است",
|
||||
"32" => "فرمت اطلاعات وارد شده صحیح نمیباشد",
|
||||
"33" => "حساب نامعتبر است",
|
||||
"34" => "خطای سیستمی",
|
||||
"35" => "تاریخ نامعتبر است",
|
||||
"41" => "شماره درخواست تکراری است",
|
||||
"42" => "تراکنش یافت نشد",
|
||||
"43" => "قبلا درخواست Verify داده شده است",
|
||||
"44" => "درخواست Verify یافت نشد",
|
||||
"45" => "تراکنش Settle شده است",
|
||||
"46" => "تراکنش Settle نشده است",
|
||||
"47" => "تراکنش Settle یافت نشد",
|
||||
"48" => "تراکنش Reverse شده است",
|
||||
"49" => "تراکنش Refund یافت نشد",
|
||||
"51" => "تراکنش تکراری است",
|
||||
"54" => "تراکنش مرجع موجود نیست",
|
||||
"55" => "تراکنش نامعتبر است",
|
||||
"61" => "خطا در واریز",
|
||||
_ => $"خطای ناشناخته: {errorCode}"
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user