diff --git a/src/CMSMicroservice.Application/Common/Interfaces/IApplicationDbContext.cs b/src/CMSMicroservice.Application/Common/Interfaces/IApplicationDbContext.cs index 64dcc7d..17b0b88 100644 --- a/src/CMSMicroservice.Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/CMSMicroservice.Application/Common/Interfaces/IApplicationDbContext.cs @@ -39,6 +39,7 @@ public interface IApplicationDbContext DbSet ClubMemberships { get; } DbSet ClubMembershipHistories { get; } DbSet ClubMembershipCycles { get; } + DbSet PackageFeatures { get; } DbSet ClubFeatures { get; } DbSet UserClubFeatures { get; } DbSet NetworkWeeklyBalances { get; } diff --git a/src/CMSMicroservice.Domain/Common/SystemConstants.cs b/src/CMSMicroservice.Domain/Common/SystemConstants.cs index e0b4b3d..2d02837 100644 --- a/src/CMSMicroservice.Domain/Common/SystemConstants.cs +++ b/src/CMSMicroservice.Domain/Common/SystemConstants.cs @@ -24,12 +24,16 @@ public static class SystemConstants /// /// مبلغ هدیه حق عضویت باشگاه (ریال) - این مبلغ از کیف پول کم نمی‌شود + /// [DEPRECATED] از Package.Price استفاده کنید /// + [Obsolete("Moved to Package entity. Use package.Price or package.ActivationFee instead.")] public const long ClubMembershipGiftValue = 25_200_000; /// /// هزینه فعال‌سازی عضویت باشگاه (ریال) + /// [DEPRECATED] از Package.ActivationFee استفاده کنید /// + [Obsolete("Moved to Package.ActivationFee. Read from Package entity instead.")] public const long ClubActivationFee = 25_200_000; #endregion @@ -38,13 +42,16 @@ public static class SystemConstants /// /// مبلغ پکیج طلایی / پایه (ریال) - 56 میلیون تومان - /// شامل: هدیه باشگاه + هزینه فعال‌سازی + مزایای دیگر + /// [DEPRECATED] از Package.Price استفاده کنید /// + [Obsolete("Moved to Package.Price. Read from Package entity instead.")] public const long BasePackageAmount = 56_000_000; /// /// مبلغ وام دایا (ریال) - همان مبلغ پکیج طلایی + /// [DEPRECATED] از Package.Price استفاده کنید /// + [Obsolete("Moved to Package.Price. Read from Package entity with SupportsDayaPurchase=true.")] public const long DayaLoanAmount = 56_000_000; #endregion @@ -63,12 +70,16 @@ public static class SystemConstants /// /// سقف تعادل هفتگی برای هر دست (چپ یا راست) - حداکثر کل = 600 + /// [DEPRECATED] از Package.MaxBalancesPerLeg استفاده کنید /// + [Obsolete("Moved to Package.MaxBalancesPerLeg. Read from Package entity instead.")] public const int CommissionMaxWeeklyBalancesPerLeg = 300; /// /// حداکثر عمق شبکه برای محاسبه کمیسیون (تعداد لول زیرمجموعه) + /// [DEPRECATED] از Package.MaxNetworkLevel استفاده کنید /// + [Obsolete("Moved to Package.MaxNetworkLevel. Read from Package entity instead.")] public const int CommissionMaxNetworkLevel = 15; /// @@ -96,17 +107,23 @@ public static class SystemConstants /// /// ضریب شارژ کیف‌پول جادویی — واریز × 2.5 = اعتبار + /// [DEPRECATED] از Package.MagicWalletMultiplier استفاده کنید /// + [Obsolete("Moved to Package.MagicWalletMultiplier. Read from Package entity instead.")] public const decimal MagicWalletMultiplier = 2.5m; /// /// سقف واریز در هر دور جادویی (ریال) — 100M تومان + /// [DEPRECATED] از Package.MagicWalletMaxDeposit استفاده کنید /// + [Obsolete("Moved to Package.MagicWalletMaxDeposit. Read from Package entity instead.")] public const long MagicWalletMaxDeposit = 1_000_000_000; /// /// سقف اعتبار در هر دور جادویی (ریال) — 250M تومان + /// [DEPRECATED] از Package.MagicWalletMaxCredit استفاده کنید /// + [Obsolete("Moved to Package.MagicWalletMaxCredit. Read from Package entity instead.")] public const long MagicWalletMaxCredit = 2_500_000_000; #endregion diff --git a/src/CMSMicroservice.Domain/Entities/Club/ClubMembership.cs b/src/CMSMicroservice.Domain/Entities/Club/ClubMembership.cs index 089f6bf..e67754b 100644 --- a/src/CMSMicroservice.Domain/Entities/Club/ClubMembership.cs +++ b/src/CMSMicroservice.Domain/Entities/Club/ClubMembership.cs @@ -20,9 +20,45 @@ public class ClubMembership : BaseAuditableEntity /// public bool IsActive { get; set; } + // === v5: First/Last Activation Tracking (Q21) === + /// - /// تاریخ فعال‌سازی عضویت + /// اولین فعال‌سازی — فقط یک بار ست می‌شود، هیچ‌وقت overwrite نمی‌شود /// + public DateTime FirstActivationDate { get; set; } + + /// + /// اولین پکیج خریداری‌شده — فقط یک بار ست می‌شود + /// + public long FirstPackageId { get; set; } + + /// + /// FirstPackage Navigation Property + /// + public virtual Package FirstPackage { get; set; } + + /// + /// آخرین/جاری فعال‌سازی — هر خرید مجدد بروزرسانی می‌شود + /// مبنای تشخیص "فعال‌شدگان این هفته" (Q22) + /// + public DateTime LastActivationDate { get; set; } + + /// + /// آخرین/جاری پکیج — هر خرید مجدد بروزرسانی می‌شود + /// مبنای carryover per-package (Q23) + /// + public long LastPackageId { get; set; } + + /// + /// LastPackage Navigation Property + /// + public virtual Package LastPackage { get; set; } + + /// + /// [DEPRECATED] تاریخ فعال‌سازی — جایگزین با FirstActivationDate + LastActivationDate + /// حفظ موقت برای backward compatibility + /// + [Obsolete("Use FirstActivationDate / LastActivationDate instead")] public DateTime? ActivatedAt { get; set; } /// diff --git a/src/CMSMicroservice.Domain/Entities/Club/ClubMembershipCycle.cs b/src/CMSMicroservice.Domain/Entities/Club/ClubMembershipCycle.cs index 070f713..2b1f787 100644 --- a/src/CMSMicroservice.Domain/Entities/Club/ClubMembershipCycle.cs +++ b/src/CMSMicroservice.Domain/Entities/Club/ClubMembershipCycle.cs @@ -57,6 +57,16 @@ public class ClubMembershipCycle : BaseAuditableEntity /// public long PackageAmount { get; set; } + /// + /// شناسه پکیج خریداری‌شده در این دور + /// + public long PackageId { get; set; } + + /// + /// Package Navigation Property + /// + public virtual Package Package { get; set; } + /// /// آیا این دور فعلی است؟ فقط یک رکورد true می‌باشد /// diff --git a/src/CMSMicroservice.Domain/Entities/Commission/UserCommissionPayout.cs b/src/CMSMicroservice.Domain/Entities/Commission/UserCommissionPayout.cs index 12cd658..e8c8340 100644 --- a/src/CMSMicroservice.Domain/Entities/Commission/UserCommissionPayout.cs +++ b/src/CMSMicroservice.Domain/Entities/Commission/UserCommissionPayout.cs @@ -36,6 +36,16 @@ public class UserCommissionPayout : BaseAuditableEntity /// public virtual WeeklyCommissionPool WeeklyPool { get; set; } + /// + /// شناسه پکیج (کمیسیون هر پکیج جداگانه) + /// + public long PackageId { get; set; } + + /// + /// Package Navigation Property + /// + public virtual Package Package { get; set; } + /// /// تعداد امتیازی که کاربر داشت /// diff --git a/src/CMSMicroservice.Domain/Entities/Commission/WeeklyCommissionPool.cs b/src/CMSMicroservice.Domain/Entities/Commission/WeeklyCommissionPool.cs index a5ba946..a8ca1cc 100644 --- a/src/CMSMicroservice.Domain/Entities/Commission/WeeklyCommissionPool.cs +++ b/src/CMSMicroservice.Domain/Entities/Commission/WeeklyCommissionPool.cs @@ -16,6 +16,16 @@ public class WeeklyCommissionPool : BaseAuditableEntity /// public virtual WeekDefinition WeekDefinition { get; set; } + /// + /// شناسه پکیج (استخر هر پکیج جداگانه) + /// + public long PackageId { get; set; } + + /// + /// Package Navigation Property + /// + public virtual Package Package { get; set; } + /// /// مجموع مبلغ جمع‌شده در استخر (ریال) /// diff --git a/src/CMSMicroservice.Domain/Entities/Network/NetworkWeeklyBalance.cs b/src/CMSMicroservice.Domain/Entities/Network/NetworkWeeklyBalance.cs index c60b705..65134a9 100644 --- a/src/CMSMicroservice.Domain/Entities/Network/NetworkWeeklyBalance.cs +++ b/src/CMSMicroservice.Domain/Entities/Network/NetworkWeeklyBalance.cs @@ -25,6 +25,16 @@ public class NetworkWeeklyBalance : BaseAuditableEntity /// public virtual WeekDefinition WeekDefinition { get; set; } + /// + /// شناسه پکیج (تعادل هر پکیج جداگانه) + /// + public long PackageId { get; set; } + + /// + /// Package Navigation Property + /// + public virtual Package Package { get; set; } + /// /// تعداد اعضای جدید شاخه چپ در این هفته /// diff --git a/src/CMSMicroservice.Domain/Entities/Package.cs b/src/CMSMicroservice.Domain/Entities/Package.cs index 7429c23..394e899 100644 --- a/src/CMSMicroservice.Domain/Entities/Package.cs +++ b/src/CMSMicroservice.Domain/Entities/Package.cs @@ -1,15 +1,76 @@ namespace CMSMicroservice.Domain.Entities; -//پکیج + +/// +/// پکیج — هر پکیج قیمت، ویژگی‌ها و تنظیمات مستقل دارد +/// public class Package : BaseAuditableEntity { - //عنوان + // === فیلدهای فعلی (حفظ) === + + /// عنوان پکیج public string Title { get; set; } - //توضیحات + + /// توضیحات public string Description { get; set; } - //آدرس تصویر + + /// آدرس تصویر public string ImagePath { get; set; } - //قیمت + + /// قیمت پکیج (ریال) public long Price { get; set; } - //UserOrder Collection Navigation Reference + + // === فیلدهای جدید v3 === + + /// ترتیب نمایش + public int SortOrder { get; set; } + + /// فعال/غیرفعال + public bool IsActive { get; set; } = true; + + /// پکیج پایه؟ (فقط یکی true) + public bool IsBasePackage { get; set; } + + /// پشتیبانی از خرید دایا + public bool SupportsDayaPurchase { get; set; } + + /// پشتیبانی از پرداخت مستقیم + public bool SupportsDirectPurchase { get; set; } = true; + + // === محاسبات مالی === + + /// سهم Commission Pool (ریال) — معمولاً Price × 0.45 + public long ActivationFee { get; set; } + + /// ضریب شارژ DiscountBalance — فعلاً ×2 برای همه + public decimal DiscountMultiplier { get; set; } = 2.0m; + + /// ضریب کیف‌پول جادویی — واریز × این مقدار = اعتبار + public decimal MagicWalletMultiplier { get; set; } = 2.5m; + + // === تنظیمات پورسانت === + + /// سقف تعادل هر پا (نقره‌ای=۳۰، پایه=۳۰۰) + public int MaxBalancesPerLeg { get; set; } = 300; + + /// عمق شبکه برای محاسبه کمیسیون + public int MaxNetworkLevel { get; set; } = 15; + + // === تنظیمات کیف‌پول جادویی === + + /// سقف شارژ هر دور جادویی (ریال) + public long MagicWalletMaxDeposit { get; set; } = 1_000_000_000; + + /// سقف اعتبار هر دور جادویی (ریال) + public long MagicWalletMaxCredit { get; set; } = 2_500_000_000; + + // === Navigation Properties === + + /// فیچرهای این پکیج + public virtual ICollection? PackageFeatures { get; set; } + + /// سفارشات مرتبط public virtual ICollection UserOrders { get; set; } + + /// خریدهای پکیج + public virtual ICollection? Purchases { get; set; } } diff --git a/src/CMSMicroservice.Domain/Entities/PackageFeature.cs b/src/CMSMicroservice.Domain/Entities/PackageFeature.cs new file mode 100644 index 0000000..860707d --- /dev/null +++ b/src/CMSMicroservice.Domain/Entities/PackageFeature.cs @@ -0,0 +1,34 @@ +using CMSMicroservice.Domain.Entities.Club; + +namespace CMSMicroservice.Domain.Entities; + +/// +/// ارتباط پکیج–فیچر — هر پکیج مجموعه فیچرهای خودش را دارد +/// +public class PackageFeature : BaseAuditableEntity +{ + /// + /// شناسه پکیج + /// + public long PackageId { get; set; } + + /// + /// Package Navigation Property + /// + public virtual Package Package { get; set; } + + /// + /// شناسه فیچر باشگاه + /// + public long ClubFeatureId { get; set; } + + /// + /// ClubFeature Navigation Property + /// + public virtual ClubFeature ClubFeature { get; set; } + + /// + /// آیا این فیچر در پکیج فعال است + /// + public bool IsIncluded { get; set; } = true; +} diff --git a/src/CMSMicroservice.Domain/Entities/UserWalletChangeLog.cs b/src/CMSMicroservice.Domain/Entities/UserWalletChangeLog.cs index 5a568ac..a5b6471 100644 --- a/src/CMSMicroservice.Domain/Entities/UserWalletChangeLog.cs +++ b/src/CMSMicroservice.Domain/Entities/UserWalletChangeLog.cs @@ -22,4 +22,14 @@ public class UserWalletChangeLog : BaseAuditableEntity public bool IsIncrease { get; set; } //شناسه ارجاع public long? RefrenceId { get; set; } + + /// + /// شناسه پکیج مرتبط (nullable — برای تغییرات کیف پول که مرتبط با پکیج هستند) + /// + public long? PackageId { get; set; } + + /// + /// Package Navigation Property + /// + public virtual Package? Package { get; set; } } diff --git a/src/CMSMicroservice.Infrastructure/Persistence/ApplicationDbContext.cs b/src/CMSMicroservice.Infrastructure/Persistence/ApplicationDbContext.cs index d772ffa..5d8ca45 100644 --- a/src/CMSMicroservice.Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/CMSMicroservice.Infrastructure/Persistence/ApplicationDbContext.cs @@ -110,6 +110,7 @@ public class ApplicationDbContext : DbContext, IApplicationDbContext public DbSet UserClubFeatures => Set(); public DbSet ClubMembershipHistories => Set(); public DbSet ClubMembershipCycles => Set(); + public DbSet PackageFeatures => Set(); // Network public DbSet NetworkWeeklyBalances => Set(); diff --git a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/ClubMembershipConfiguration.cs b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/ClubMembershipConfiguration.cs index 5b21622..d4fe762 100644 --- a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/ClubMembershipConfiguration.cs +++ b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/ClubMembershipConfiguration.cs @@ -23,12 +23,32 @@ public class ClubMembershipConfiguration : IEntityTypeConfiguration entity.GiftValue).IsRequired(); builder.Property(entity => entity.TotalEarned).IsRequired(); + // فیلدهای جدید First/Last Activation + builder.Property(entity => entity.FirstActivationDate).IsRequired(false); + builder.Property(entity => entity.FirstPackageId).IsRequired(false); + builder.Property(entity => entity.LastActivationDate).IsRequired(false); + builder.Property(entity => entity.LastPackageId).IsRequired(false); + // رابطه یک‌به‌یک با User builder.HasOne(entity => entity.User) .WithOne(u => u.ClubMembership) .HasForeignKey(entity => entity.UserId) .OnDelete(DeleteBehavior.Restrict); + // رابطه با Package — اولین پکیج خریداری‌شده + builder.HasOne(entity => entity.FirstPackage) + .WithMany() + .HasForeignKey(entity => entity.FirstPackageId) + .IsRequired(false) + .OnDelete(DeleteBehavior.Restrict); + + // رابطه با Package — آخرین پکیج خریداری‌شده + builder.HasOne(entity => entity.LastPackage) + .WithMany() + .HasForeignKey(entity => entity.LastPackageId) + .IsRequired(false) + .OnDelete(DeleteBehavior.Restrict); + // Index برای UserId (یونیک برای یک‌به‌یک) builder.HasIndex(e => e.UserId) .IsUnique() @@ -37,5 +57,9 @@ public class ClubMembershipConfiguration : IEntityTypeConfiguration e.IsActive) .HasDatabaseName("IX_ClubMembership_IsActive"); + + // Index برای LastActivationDate (تشخیص فعال‌سازی هفتگی Q22) + builder.HasIndex(e => e.LastActivationDate) + .HasDatabaseName("IX_ClubMembership_LastActivationDate"); } } diff --git a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/ClubMembershipCycleConfiguration.cs b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/ClubMembershipCycleConfiguration.cs index 19fb522..33fd41d 100644 --- a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/ClubMembershipCycleConfiguration.cs +++ b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/ClubMembershipCycleConfiguration.cs @@ -21,6 +21,7 @@ public class ClubMembershipCycleConfiguration : IEntityTypeConfiguration entity.MagicCompletedAt).IsRequired(false); builder.Property(entity => entity.PurchaseMethod).IsRequired(); builder.Property(entity => entity.PackageAmount).IsRequired(); + builder.Property(entity => entity.PackageId).IsRequired(); builder.Property(entity => entity.IsCurrentCycle) .IsRequired() .HasDefaultValue(false); @@ -36,6 +37,11 @@ public class ClubMembershipCycleConfiguration : IEntityTypeConfiguration entity.ClubMembershipId) .OnDelete(DeleteBehavior.Restrict); + builder.HasOne(entity => entity.Package) + .WithMany() + .HasForeignKey(entity => entity.PackageId) + .OnDelete(DeleteBehavior.Restrict); + // Indexes builder.HasIndex(e => new { e.UserId, e.IsCurrentCycle }) .HasDatabaseName("IX_ClubMembershipCycle_UserId_IsCurrentCycle"); diff --git a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/NetworkWeeklyBalanceConfiguration.cs b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/NetworkWeeklyBalanceConfiguration.cs index e176f3f..99f520b 100644 --- a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/NetworkWeeklyBalanceConfiguration.cs +++ b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/NetworkWeeklyBalanceConfiguration.cs @@ -18,6 +18,7 @@ public class NetworkWeeklyBalanceConfiguration : IEntityTypeConfiguration entity.UserId).IsRequired(); builder.Property(entity => entity.WeekDefinitionId).IsRequired(); + builder.Property(entity => entity.PackageId).IsRequired(); builder.Property(entity => entity.LeftLegBalances).IsRequired(); builder.Property(entity => entity.RightLegBalances).IsRequired(); builder.Property(entity => entity.TotalBalances).IsRequired(); @@ -37,10 +38,16 @@ public class NetworkWeeklyBalanceConfiguration : IEntityTypeConfiguration entity.WeekDefinitionId) .OnDelete(DeleteBehavior.Restrict); - // Composite Index برای UserId و WeekDefinitionId - builder.HasIndex(e => new { e.UserId, e.WeekDefinitionId }) + // رابطه با Package + builder.HasOne(entity => entity.Package) + .WithMany() + .HasForeignKey(entity => entity.PackageId) + .OnDelete(DeleteBehavior.Restrict); + + // Composite Index: هر کاربر × هر هفته × هر پکیج فقط یک رکورد + builder.HasIndex(e => new { e.UserId, e.WeekDefinitionId, e.PackageId }) .IsUnique() - .HasDatabaseName("IX_NetworkWeeklyBalance_UserId_WeekDefinitionId"); + .HasDatabaseName("IX_NetworkWeeklyBalance_User_WeekDef_Package"); // Index برای WeekDefinitionId builder.HasIndex(e => e.WeekDefinitionId) diff --git a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/PackageConfiguration.cs b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/PackageConfiguration.cs index 9cd5e28..6b6d591 100644 --- a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/PackageConfiguration.cs +++ b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/PackageConfiguration.cs @@ -15,6 +15,28 @@ public class PackageConfiguration : IEntityTypeConfiguration builder.Property(entity => entity.Description).IsRequired(true); builder.Property(entity => entity.ImagePath).IsRequired(true); builder.Property(entity => entity.Price).IsRequired(true); + + // فیلدهای جدید پکیج + builder.Property(entity => entity.SortOrder).IsRequired().HasDefaultValue(0); + builder.Property(entity => entity.IsActive).IsRequired().HasDefaultValue(true); + builder.Property(entity => entity.IsBasePackage).IsRequired().HasDefaultValue(false); + builder.Property(entity => entity.SupportsDayaPurchase).IsRequired().HasDefaultValue(false); + builder.Property(entity => entity.SupportsDirectPurchase).IsRequired().HasDefaultValue(true); + builder.Property(entity => entity.ActivationFee).IsRequired().HasDefaultValue(0L); + builder.Property(entity => entity.DiscountMultiplier).IsRequired().HasDefaultValue(2.0m) + .HasPrecision(18, 4); + builder.Property(entity => entity.MagicWalletMultiplier).IsRequired().HasDefaultValue(2.5m) + .HasPrecision(18, 4); + builder.Property(entity => entity.MaxBalancesPerLeg).IsRequired().HasDefaultValue(300); + builder.Property(entity => entity.MaxNetworkLevel).IsRequired().HasDefaultValue(15); + builder.Property(entity => entity.MagicWalletMaxDeposit).IsRequired().HasDefaultValue(1_000_000_000L); + builder.Property(entity => entity.MagicWalletMaxCredit).IsRequired().HasDefaultValue(2_500_000_000L); + + // Indexes + builder.HasIndex(e => e.IsActive) + .HasDatabaseName("IX_Package_IsActive"); + builder.HasIndex(e => e.SortOrder) + .HasDatabaseName("IX_Package_SortOrder"); } } diff --git a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/PackageFeatureConfiguration.cs b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/PackageFeatureConfiguration.cs new file mode 100644 index 0000000..2e42e1c --- /dev/null +++ b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/PackageFeatureConfiguration.cs @@ -0,0 +1,41 @@ +using CMSMicroservice.Domain.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace CMSMicroservice.Infrastructure.Persistence.Configurations; + +/// +/// EF Configuration — ارتباط پکیج–فیچر +/// +public class PackageFeatureConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder 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.PackageId).IsRequired(); + builder.Property(entity => entity.ClubFeatureId).IsRequired(); + builder.Property(entity => entity.IsIncluded).IsRequired().HasDefaultValue(true); + + // رابطه با Package + builder.HasOne(entity => entity.Package) + .WithMany(p => p.PackageFeatures) + .HasForeignKey(entity => entity.PackageId) + .OnDelete(DeleteBehavior.Cascade); + + // رابطه با ClubFeature + builder.HasOne(entity => entity.ClubFeature) + .WithMany() + .HasForeignKey(entity => entity.ClubFeatureId) + .OnDelete(DeleteBehavior.Restrict); + + // Unique: هر فیچر فقط یک بار در هر پکیج + builder.HasIndex(e => new { e.PackageId, e.ClubFeatureId }) + .IsUnique() + .HasDatabaseName("IX_PackageFeature_PackageId_ClubFeatureId"); + } +} diff --git a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/UserCommissionPayoutConfiguration.cs b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/UserCommissionPayoutConfiguration.cs index f190faa..d9632f9 100644 --- a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/UserCommissionPayoutConfiguration.cs +++ b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/UserCommissionPayoutConfiguration.cs @@ -19,6 +19,7 @@ public class UserCommissionPayoutConfiguration : IEntityTypeConfiguration entity.UserId).IsRequired(); builder.Property(entity => entity.WeekDefinitionId).IsRequired(); builder.Property(entity => entity.WeeklyPoolId).IsRequired(); + builder.Property(entity => entity.PackageId).IsRequired(); builder.Property(entity => entity.BalancesEarned).IsRequired(); builder.Property(entity => entity.ValuePerBalance).IsRequired(); builder.Property(entity => entity.TotalAmount).IsRequired(); @@ -50,10 +51,16 @@ public class UserCommissionPayoutConfiguration : IEntityTypeConfiguration new { e.UserId, e.WeekDefinitionId }) + // رابطه با Package + builder.HasOne(entity => entity.Package) + .WithMany() + .HasForeignKey(entity => entity.PackageId) + .OnDelete(DeleteBehavior.Restrict); + + // Composite Index برای UserId، WeekDefinitionId و PackageId + builder.HasIndex(e => new { e.UserId, e.WeekDefinitionId, e.PackageId }) .IsUnique() - .HasDatabaseName("IX_UserCommissionPayout_UserId_WeekDefinitionId"); + .HasDatabaseName("IX_UserCommissionPayout_User_WeekDef_Package"); // Index برای WeeklyPoolId builder.HasIndex(e => e.WeeklyPoolId) diff --git a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/UserWalletChangeLogConfiguration.cs b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/UserWalletChangeLogConfiguration.cs index 897dbec..f06d48f 100644 --- a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/UserWalletChangeLogConfiguration.cs +++ b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/UserWalletChangeLogConfiguration.cs @@ -22,6 +22,14 @@ public class UserWalletChangeLogConfiguration : IEntityTypeConfiguration entity.ChangeNerworkValue).IsRequired(true); builder.Property(entity => entity.IsIncrease).IsRequired(true); builder.Property(entity => entity.RefrenceId).IsRequired(false); + builder.Property(entity => entity.PackageId).IsRequired(false); + + // رابطه با Package (nullable) + builder.HasOne(entity => entity.Package) + .WithMany() + .HasForeignKey(entity => entity.PackageId) + .IsRequired(false) + .OnDelete(DeleteBehavior.Restrict); } } diff --git a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/WeeklyCommissionPoolConfiguration.cs b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/WeeklyCommissionPoolConfiguration.cs index 5a56c75..7789dae 100644 --- a/src/CMSMicroservice.Infrastructure/Persistence/Configurations/WeeklyCommissionPoolConfiguration.cs +++ b/src/CMSMicroservice.Infrastructure/Persistence/Configurations/WeeklyCommissionPoolConfiguration.cs @@ -17,6 +17,7 @@ public class WeeklyCommissionPoolConfiguration : IEntityTypeConfiguration entity.Id).UseIdentityColumn(); builder.Property(entity => entity.WeekDefinitionId).IsRequired(); + builder.Property(entity => entity.PackageId).IsRequired(); builder.Property(entity => entity.TotalPoolAmount).IsRequired(); builder.Property(entity => entity.TotalBalances).IsRequired(); builder.Property(entity => entity.ValuePerBalance).IsRequired(); @@ -30,10 +31,16 @@ public class WeeklyCommissionPoolConfiguration : IEntityTypeConfiguration e.WeekDefinitionId) + // رابطه با Package + builder.HasOne(entity => entity.Package) + .WithMany() + .HasForeignKey(entity => entity.PackageId) + .OnDelete(DeleteBehavior.Restrict); + + // Index یونیک ترکیبی: هر هفته × هر پکیج فقط یک استخر + builder.HasIndex(e => new { e.WeekDefinitionId, e.PackageId }) .IsUnique() - .HasDatabaseName("IX_WeeklyCommissionPool_WeekDefinitionId"); + .HasDatabaseName("IX_WeeklyCommissionPool_WeekDef_Package"); // Index برای IsCalculated builder.HasIndex(e => e.IsCalculated)