Phase 1: Package-Based Domain Infrastructure
ENTITIES: - Package: +11 fields (SortOrder, IsActive, IsBasePackage, SupportsDaya/Direct, ActivationFee, DiscountMultiplier, MagicWalletMultiplier, MaxBalancesPerLeg, MaxNetworkLevel, MagicWalletMaxDeposit/Credit) + nav props - PackageFeature: NEW junction entity (Package × ClubFeature) for feature DIFF - ClubMembership: +4 fields (FirstActivationDate/PackageId, LastActivation/PackageId) ActivatedAt kept as [Obsolete] for backward compat - ClubMembershipCycle: +PackageId FK (tracks which package per cycle) - WeeklyCommissionPool: +PackageId FK (separate pool per package) - UserCommissionPayout: +PackageId FK (payout per package) - NetworkWeeklyBalance: +PackageId FK (balance per package) - UserWalletChangeLog: +PackageId? FK (optional package tracking) EF CONFIGS: - PackageConfiguration: 11 new field configs + indexes - PackageFeatureConfiguration: NEW (unique PackageId+ClubFeatureId) - ClubMembershipConfiguration: First/Last Package FKs + LastActivationDate index - ClubMembershipCycleConfiguration: Package FK - WeeklyCommissionPoolConfiguration: Package FK + unique(WeekDef,Package) - UserCommissionPayoutConfiguration: Package FK + unique(User,WeekDef,Package) - NetworkWeeklyBalanceConfiguration: Package FK + unique(User,WeekDef,Package) - UserWalletChangeLogConfiguration: Package FK (nullable) DBCONTEXT: - DbSet<PackageFeature> added to ApplicationDbContext + IApplicationDbContext SYSTEMCONSTANTS: - 9 constants marked [Obsolete] → moved to Package entity (ClubMembershipGiftValue, ClubActivationFee, BasePackageAmount, DayaLoanAmount, MagicWalletMultiplier, MagicWalletMaxDeposit, MagicWalletMaxCredit, CommissionMaxWeeklyBalancesPerLeg, CommissionMaxNetworkLevel) Build: 0 errors, 610 warnings (40 new = expected Obsolete CS0618)
This commit is contained in:
@@ -39,6 +39,7 @@ public interface IApplicationDbContext
|
|||||||
DbSet<ClubMembership> ClubMemberships { get; }
|
DbSet<ClubMembership> ClubMemberships { get; }
|
||||||
DbSet<ClubMembershipHistory> ClubMembershipHistories { get; }
|
DbSet<ClubMembershipHistory> ClubMembershipHistories { get; }
|
||||||
DbSet<ClubMembershipCycle> ClubMembershipCycles { get; }
|
DbSet<ClubMembershipCycle> ClubMembershipCycles { get; }
|
||||||
|
DbSet<PackageFeature> PackageFeatures { get; }
|
||||||
DbSet<ClubFeature> ClubFeatures { get; }
|
DbSet<ClubFeature> ClubFeatures { get; }
|
||||||
DbSet<UserClubFeature> UserClubFeatures { get; }
|
DbSet<UserClubFeature> UserClubFeatures { get; }
|
||||||
DbSet<NetworkWeeklyBalance> NetworkWeeklyBalances { get; }
|
DbSet<NetworkWeeklyBalance> NetworkWeeklyBalances { get; }
|
||||||
|
|||||||
@@ -24,12 +24,16 @@ public static class SystemConstants
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// مبلغ هدیه حق عضویت باشگاه (ریال) - این مبلغ از کیف پول کم نمیشود
|
/// مبلغ هدیه حق عضویت باشگاه (ریال) - این مبلغ از کیف پول کم نمیشود
|
||||||
|
/// [DEPRECATED] از Package.Price استفاده کنید
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Moved to Package entity. Use package.Price or package.ActivationFee instead.")]
|
||||||
public const long ClubMembershipGiftValue = 25_200_000;
|
public const long ClubMembershipGiftValue = 25_200_000;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// هزینه فعالسازی عضویت باشگاه (ریال)
|
/// هزینه فعالسازی عضویت باشگاه (ریال)
|
||||||
|
/// [DEPRECATED] از Package.ActivationFee استفاده کنید
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Moved to Package.ActivationFee. Read from Package entity instead.")]
|
||||||
public const long ClubActivationFee = 25_200_000;
|
public const long ClubActivationFee = 25_200_000;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -38,13 +42,16 @@ public static class SystemConstants
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// مبلغ پکیج طلایی / پایه (ریال) - 56 میلیون تومان
|
/// مبلغ پکیج طلایی / پایه (ریال) - 56 میلیون تومان
|
||||||
/// شامل: هدیه باشگاه + هزینه فعالسازی + مزایای دیگر
|
/// [DEPRECATED] از Package.Price استفاده کنید
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Moved to Package.Price. Read from Package entity instead.")]
|
||||||
public const long BasePackageAmount = 56_000_000;
|
public const long BasePackageAmount = 56_000_000;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// مبلغ وام دایا (ریال) - همان مبلغ پکیج طلایی
|
/// مبلغ وام دایا (ریال) - همان مبلغ پکیج طلایی
|
||||||
|
/// [DEPRECATED] از Package.Price استفاده کنید
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Moved to Package.Price. Read from Package entity with SupportsDayaPurchase=true.")]
|
||||||
public const long DayaLoanAmount = 56_000_000;
|
public const long DayaLoanAmount = 56_000_000;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -63,12 +70,16 @@ public static class SystemConstants
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// سقف تعادل هفتگی برای هر دست (چپ یا راست) - حداکثر کل = 600
|
/// سقف تعادل هفتگی برای هر دست (چپ یا راست) - حداکثر کل = 600
|
||||||
|
/// [DEPRECATED] از Package.MaxBalancesPerLeg استفاده کنید
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Moved to Package.MaxBalancesPerLeg. Read from Package entity instead.")]
|
||||||
public const int CommissionMaxWeeklyBalancesPerLeg = 300;
|
public const int CommissionMaxWeeklyBalancesPerLeg = 300;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// حداکثر عمق شبکه برای محاسبه کمیسیون (تعداد لول زیرمجموعه)
|
/// حداکثر عمق شبکه برای محاسبه کمیسیون (تعداد لول زیرمجموعه)
|
||||||
|
/// [DEPRECATED] از Package.MaxNetworkLevel استفاده کنید
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Moved to Package.MaxNetworkLevel. Read from Package entity instead.")]
|
||||||
public const int CommissionMaxNetworkLevel = 15;
|
public const int CommissionMaxNetworkLevel = 15;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -96,17 +107,23 @@ public static class SystemConstants
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ضریب شارژ کیفپول جادویی — واریز × 2.5 = اعتبار
|
/// ضریب شارژ کیفپول جادویی — واریز × 2.5 = اعتبار
|
||||||
|
/// [DEPRECATED] از Package.MagicWalletMultiplier استفاده کنید
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Moved to Package.MagicWalletMultiplier. Read from Package entity instead.")]
|
||||||
public const decimal MagicWalletMultiplier = 2.5m;
|
public const decimal MagicWalletMultiplier = 2.5m;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// سقف واریز در هر دور جادویی (ریال) — 100M تومان
|
/// سقف واریز در هر دور جادویی (ریال) — 100M تومان
|
||||||
|
/// [DEPRECATED] از Package.MagicWalletMaxDeposit استفاده کنید
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Moved to Package.MagicWalletMaxDeposit. Read from Package entity instead.")]
|
||||||
public const long MagicWalletMaxDeposit = 1_000_000_000;
|
public const long MagicWalletMaxDeposit = 1_000_000_000;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// سقف اعتبار در هر دور جادویی (ریال) — 250M تومان
|
/// سقف اعتبار در هر دور جادویی (ریال) — 250M تومان
|
||||||
|
/// [DEPRECATED] از Package.MagicWalletMaxCredit استفاده کنید
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Moved to Package.MagicWalletMaxCredit. Read from Package entity instead.")]
|
||||||
public const long MagicWalletMaxCredit = 2_500_000_000;
|
public const long MagicWalletMaxCredit = 2_500_000_000;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -20,9 +20,45 @@ public class ClubMembership : BaseAuditableEntity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsActive { get; set; }
|
public bool IsActive { get; set; }
|
||||||
|
|
||||||
|
// === v5: First/Last Activation Tracking (Q21) ===
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// تاریخ فعالسازی عضویت
|
/// اولین فعالسازی — فقط یک بار ست میشود، هیچوقت overwrite نمیشود
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
public DateTime FirstActivationDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// اولین پکیج خریداریشده — فقط یک بار ست میشود
|
||||||
|
/// </summary>
|
||||||
|
public long FirstPackageId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// FirstPackage Navigation Property
|
||||||
|
/// </summary>
|
||||||
|
public virtual Package FirstPackage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آخرین/جاری فعالسازی — هر خرید مجدد بروزرسانی میشود
|
||||||
|
/// مبنای تشخیص "فعالشدگان این هفته" (Q22)
|
||||||
|
/// </summary>
|
||||||
|
public DateTime LastActivationDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آخرین/جاری پکیج — هر خرید مجدد بروزرسانی میشود
|
||||||
|
/// مبنای carryover per-package (Q23)
|
||||||
|
/// </summary>
|
||||||
|
public long LastPackageId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// LastPackage Navigation Property
|
||||||
|
/// </summary>
|
||||||
|
public virtual Package LastPackage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [DEPRECATED] تاریخ فعالسازی — جایگزین با FirstActivationDate + LastActivationDate
|
||||||
|
/// حفظ موقت برای backward compatibility
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("Use FirstActivationDate / LastActivationDate instead")]
|
||||||
public DateTime? ActivatedAt { get; set; }
|
public DateTime? ActivatedAt { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -57,6 +57,16 @@ public class ClubMembershipCycle : BaseAuditableEntity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public long PackageAmount { get; set; }
|
public long PackageAmount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// شناسه پکیج خریداریشده در این دور
|
||||||
|
/// </summary>
|
||||||
|
public long PackageId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Package Navigation Property
|
||||||
|
/// </summary>
|
||||||
|
public virtual Package Package { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// آیا این دور فعلی است؟ فقط یک رکورد true میباشد
|
/// آیا این دور فعلی است؟ فقط یک رکورد true میباشد
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -36,6 +36,16 @@ public class UserCommissionPayout : BaseAuditableEntity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual WeeklyCommissionPool WeeklyPool { get; set; }
|
public virtual WeeklyCommissionPool WeeklyPool { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// شناسه پکیج (کمیسیون هر پکیج جداگانه)
|
||||||
|
/// </summary>
|
||||||
|
public long PackageId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Package Navigation Property
|
||||||
|
/// </summary>
|
||||||
|
public virtual Package Package { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// تعداد امتیازی که کاربر داشت
|
/// تعداد امتیازی که کاربر داشت
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -16,6 +16,16 @@ public class WeeklyCommissionPool : BaseAuditableEntity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual WeekDefinition WeekDefinition { get; set; }
|
public virtual WeekDefinition WeekDefinition { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// شناسه پکیج (استخر هر پکیج جداگانه)
|
||||||
|
/// </summary>
|
||||||
|
public long PackageId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Package Navigation Property
|
||||||
|
/// </summary>
|
||||||
|
public virtual Package Package { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// مجموع مبلغ جمعشده در استخر (ریال)
|
/// مجموع مبلغ جمعشده در استخر (ریال)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -25,6 +25,16 @@ public class NetworkWeeklyBalance : BaseAuditableEntity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual WeekDefinition WeekDefinition { get; set; }
|
public virtual WeekDefinition WeekDefinition { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// شناسه پکیج (تعادل هر پکیج جداگانه)
|
||||||
|
/// </summary>
|
||||||
|
public long PackageId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Package Navigation Property
|
||||||
|
/// </summary>
|
||||||
|
public virtual Package Package { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// تعداد اعضای جدید شاخه چپ در این هفته
|
/// تعداد اعضای جدید شاخه چپ در این هفته
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,15 +1,76 @@
|
|||||||
namespace CMSMicroservice.Domain.Entities;
|
namespace CMSMicroservice.Domain.Entities;
|
||||||
//پکیج
|
|
||||||
|
/// <summary>
|
||||||
|
/// پکیج — هر پکیج قیمت، ویژگیها و تنظیمات مستقل دارد
|
||||||
|
/// </summary>
|
||||||
public class Package : BaseAuditableEntity
|
public class Package : BaseAuditableEntity
|
||||||
{
|
{
|
||||||
//عنوان
|
// === فیلدهای فعلی (حفظ) ===
|
||||||
|
|
||||||
|
/// <summary>عنوان پکیج</summary>
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
//توضیحات
|
|
||||||
|
/// <summary>توضیحات</summary>
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
//آدرس تصویر
|
|
||||||
|
/// <summary>آدرس تصویر</summary>
|
||||||
public string ImagePath { get; set; }
|
public string ImagePath { get; set; }
|
||||||
//قیمت
|
|
||||||
|
/// <summary>قیمت پکیج (ریال)</summary>
|
||||||
public long Price { get; set; }
|
public long Price { get; set; }
|
||||||
//UserOrder Collection Navigation Reference
|
|
||||||
|
// === فیلدهای جدید v3 ===
|
||||||
|
|
||||||
|
/// <summary>ترتیب نمایش</summary>
|
||||||
|
public int SortOrder { get; set; }
|
||||||
|
|
||||||
|
/// <summary>فعال/غیرفعال</summary>
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>پکیج پایه؟ (فقط یکی true)</summary>
|
||||||
|
public bool IsBasePackage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>پشتیبانی از خرید دایا</summary>
|
||||||
|
public bool SupportsDayaPurchase { get; set; }
|
||||||
|
|
||||||
|
/// <summary>پشتیبانی از پرداخت مستقیم</summary>
|
||||||
|
public bool SupportsDirectPurchase { get; set; } = true;
|
||||||
|
|
||||||
|
// === محاسبات مالی ===
|
||||||
|
|
||||||
|
/// <summary>سهم Commission Pool (ریال) — معمولاً Price × 0.45</summary>
|
||||||
|
public long ActivationFee { get; set; }
|
||||||
|
|
||||||
|
/// <summary>ضریب شارژ DiscountBalance — فعلاً ×2 برای همه</summary>
|
||||||
|
public decimal DiscountMultiplier { get; set; } = 2.0m;
|
||||||
|
|
||||||
|
/// <summary>ضریب کیفپول جادویی — واریز × این مقدار = اعتبار</summary>
|
||||||
|
public decimal MagicWalletMultiplier { get; set; } = 2.5m;
|
||||||
|
|
||||||
|
// === تنظیمات پورسانت ===
|
||||||
|
|
||||||
|
/// <summary>سقف تعادل هر پا (نقرهای=۳۰، پایه=۳۰۰)</summary>
|
||||||
|
public int MaxBalancesPerLeg { get; set; } = 300;
|
||||||
|
|
||||||
|
/// <summary>عمق شبکه برای محاسبه کمیسیون</summary>
|
||||||
|
public int MaxNetworkLevel { get; set; } = 15;
|
||||||
|
|
||||||
|
// === تنظیمات کیفپول جادویی ===
|
||||||
|
|
||||||
|
/// <summary>سقف شارژ هر دور جادویی (ریال)</summary>
|
||||||
|
public long MagicWalletMaxDeposit { get; set; } = 1_000_000_000;
|
||||||
|
|
||||||
|
/// <summary>سقف اعتبار هر دور جادویی (ریال)</summary>
|
||||||
|
public long MagicWalletMaxCredit { get; set; } = 2_500_000_000;
|
||||||
|
|
||||||
|
// === Navigation Properties ===
|
||||||
|
|
||||||
|
/// <summary>فیچرهای این پکیج</summary>
|
||||||
|
public virtual ICollection<PackageFeature>? PackageFeatures { get; set; }
|
||||||
|
|
||||||
|
/// <summary>سفارشات مرتبط</summary>
|
||||||
public virtual ICollection<UserOrder> UserOrders { get; set; }
|
public virtual ICollection<UserOrder> UserOrders { get; set; }
|
||||||
|
|
||||||
|
/// <summary>خریدهای پکیج</summary>
|
||||||
|
public virtual ICollection<UserPackagePurchase>? Purchases { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using CMSMicroservice.Domain.Entities.Club;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Domain.Entities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ارتباط پکیج–فیچر — هر پکیج مجموعه فیچرهای خودش را دارد
|
||||||
|
/// </summary>
|
||||||
|
public class PackageFeature : BaseAuditableEntity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// شناسه پکیج
|
||||||
|
/// </summary>
|
||||||
|
public long PackageId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Package Navigation Property
|
||||||
|
/// </summary>
|
||||||
|
public virtual Package Package { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// شناسه فیچر باشگاه
|
||||||
|
/// </summary>
|
||||||
|
public long ClubFeatureId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ClubFeature Navigation Property
|
||||||
|
/// </summary>
|
||||||
|
public virtual ClubFeature ClubFeature { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آیا این فیچر در پکیج فعال است
|
||||||
|
/// </summary>
|
||||||
|
public bool IsIncluded { get; set; } = true;
|
||||||
|
}
|
||||||
@@ -22,4 +22,14 @@ public class UserWalletChangeLog : BaseAuditableEntity
|
|||||||
public bool IsIncrease { get; set; }
|
public bool IsIncrease { get; set; }
|
||||||
//شناسه ارجاع
|
//شناسه ارجاع
|
||||||
public long? RefrenceId { get; set; }
|
public long? RefrenceId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// شناسه پکیج مرتبط (nullable — برای تغییرات کیف پول که مرتبط با پکیج هستند)
|
||||||
|
/// </summary>
|
||||||
|
public long? PackageId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Package Navigation Property
|
||||||
|
/// </summary>
|
||||||
|
public virtual Package? Package { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ public class ApplicationDbContext : DbContext, IApplicationDbContext
|
|||||||
public DbSet<UserClubFeature> UserClubFeatures => Set<UserClubFeature>();
|
public DbSet<UserClubFeature> UserClubFeatures => Set<UserClubFeature>();
|
||||||
public DbSet<ClubMembershipHistory> ClubMembershipHistories => Set<ClubMembershipHistory>();
|
public DbSet<ClubMembershipHistory> ClubMembershipHistories => Set<ClubMembershipHistory>();
|
||||||
public DbSet<ClubMembershipCycle> ClubMembershipCycles => Set<ClubMembershipCycle>();
|
public DbSet<ClubMembershipCycle> ClubMembershipCycles => Set<ClubMembershipCycle>();
|
||||||
|
public DbSet<PackageFeature> PackageFeatures => Set<PackageFeature>();
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
public DbSet<NetworkWeeklyBalance> NetworkWeeklyBalances => Set<NetworkWeeklyBalance>();
|
public DbSet<NetworkWeeklyBalance> NetworkWeeklyBalances => Set<NetworkWeeklyBalance>();
|
||||||
|
|||||||
+24
@@ -23,12 +23,32 @@ public class ClubMembershipConfiguration : IEntityTypeConfiguration<ClubMembersh
|
|||||||
builder.Property(entity => entity.GiftValue).IsRequired();
|
builder.Property(entity => entity.GiftValue).IsRequired();
|
||||||
builder.Property(entity => entity.TotalEarned).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
|
// رابطه یکبهیک با User
|
||||||
builder.HasOne(entity => entity.User)
|
builder.HasOne(entity => entity.User)
|
||||||
.WithOne(u => u.ClubMembership)
|
.WithOne(u => u.ClubMembership)
|
||||||
.HasForeignKey<ClubMembership>(entity => entity.UserId)
|
.HasForeignKey<ClubMembership>(entity => entity.UserId)
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
.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 (یونیک برای یکبهیک)
|
// Index برای UserId (یونیک برای یکبهیک)
|
||||||
builder.HasIndex(e => e.UserId)
|
builder.HasIndex(e => e.UserId)
|
||||||
.IsUnique()
|
.IsUnique()
|
||||||
@@ -37,5 +57,9 @@ public class ClubMembershipConfiguration : IEntityTypeConfiguration<ClubMembersh
|
|||||||
// Index برای IsActive
|
// Index برای IsActive
|
||||||
builder.HasIndex(e => e.IsActive)
|
builder.HasIndex(e => e.IsActive)
|
||||||
.HasDatabaseName("IX_ClubMembership_IsActive");
|
.HasDatabaseName("IX_ClubMembership_IsActive");
|
||||||
|
|
||||||
|
// Index برای LastActivationDate (تشخیص فعالسازی هفتگی Q22)
|
||||||
|
builder.HasIndex(e => e.LastActivationDate)
|
||||||
|
.HasDatabaseName("IX_ClubMembership_LastActivationDate");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -21,6 +21,7 @@ public class ClubMembershipCycleConfiguration : IEntityTypeConfiguration<ClubMem
|
|||||||
builder.Property(entity => entity.MagicCompletedAt).IsRequired(false);
|
builder.Property(entity => entity.MagicCompletedAt).IsRequired(false);
|
||||||
builder.Property(entity => entity.PurchaseMethod).IsRequired();
|
builder.Property(entity => entity.PurchaseMethod).IsRequired();
|
||||||
builder.Property(entity => entity.PackageAmount).IsRequired();
|
builder.Property(entity => entity.PackageAmount).IsRequired();
|
||||||
|
builder.Property(entity => entity.PackageId).IsRequired();
|
||||||
builder.Property(entity => entity.IsCurrentCycle)
|
builder.Property(entity => entity.IsCurrentCycle)
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasDefaultValue(false);
|
.HasDefaultValue(false);
|
||||||
@@ -36,6 +37,11 @@ public class ClubMembershipCycleConfiguration : IEntityTypeConfiguration<ClubMem
|
|||||||
.HasForeignKey(entity => entity.ClubMembershipId)
|
.HasForeignKey(entity => entity.ClubMembershipId)
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
builder.HasOne(entity => entity.Package)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(entity => entity.PackageId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
// Indexes
|
// Indexes
|
||||||
builder.HasIndex(e => new { e.UserId, e.IsCurrentCycle })
|
builder.HasIndex(e => new { e.UserId, e.IsCurrentCycle })
|
||||||
.HasDatabaseName("IX_ClubMembershipCycle_UserId_IsCurrentCycle");
|
.HasDatabaseName("IX_ClubMembershipCycle_UserId_IsCurrentCycle");
|
||||||
|
|||||||
+10
-3
@@ -18,6 +18,7 @@ public class NetworkWeeklyBalanceConfiguration : IEntityTypeConfiguration<Networ
|
|||||||
|
|
||||||
builder.Property(entity => entity.UserId).IsRequired();
|
builder.Property(entity => entity.UserId).IsRequired();
|
||||||
builder.Property(entity => entity.WeekDefinitionId).IsRequired();
|
builder.Property(entity => entity.WeekDefinitionId).IsRequired();
|
||||||
|
builder.Property(entity => entity.PackageId).IsRequired();
|
||||||
builder.Property(entity => entity.LeftLegBalances).IsRequired();
|
builder.Property(entity => entity.LeftLegBalances).IsRequired();
|
||||||
builder.Property(entity => entity.RightLegBalances).IsRequired();
|
builder.Property(entity => entity.RightLegBalances).IsRequired();
|
||||||
builder.Property(entity => entity.TotalBalances).IsRequired();
|
builder.Property(entity => entity.TotalBalances).IsRequired();
|
||||||
@@ -37,10 +38,16 @@ public class NetworkWeeklyBalanceConfiguration : IEntityTypeConfiguration<Networ
|
|||||||
.HasForeignKey(entity => entity.WeekDefinitionId)
|
.HasForeignKey(entity => entity.WeekDefinitionId)
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
// Composite Index برای UserId و WeekDefinitionId
|
// رابطه با Package
|
||||||
builder.HasIndex(e => new { e.UserId, e.WeekDefinitionId })
|
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()
|
.IsUnique()
|
||||||
.HasDatabaseName("IX_NetworkWeeklyBalance_UserId_WeekDefinitionId");
|
.HasDatabaseName("IX_NetworkWeeklyBalance_User_WeekDef_Package");
|
||||||
|
|
||||||
// Index برای WeekDefinitionId
|
// Index برای WeekDefinitionId
|
||||||
builder.HasIndex(e => e.WeekDefinitionId)
|
builder.HasIndex(e => e.WeekDefinitionId)
|
||||||
|
|||||||
@@ -15,6 +15,28 @@ public class PackageConfiguration : IEntityTypeConfiguration<Package>
|
|||||||
builder.Property(entity => entity.Description).IsRequired(true);
|
builder.Property(entity => entity.Description).IsRequired(true);
|
||||||
builder.Property(entity => entity.ImagePath).IsRequired(true);
|
builder.Property(entity => entity.ImagePath).IsRequired(true);
|
||||||
builder.Property(entity => entity.Price).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");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
using CMSMicroservice.Domain.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// EF Configuration — ارتباط پکیج–فیچر
|
||||||
|
/// </summary>
|
||||||
|
public class PackageFeatureConfiguration : IEntityTypeConfiguration<PackageFeature>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<PackageFeature> 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-3
@@ -19,6 +19,7 @@ public class UserCommissionPayoutConfiguration : IEntityTypeConfiguration<UserCo
|
|||||||
builder.Property(entity => entity.UserId).IsRequired();
|
builder.Property(entity => entity.UserId).IsRequired();
|
||||||
builder.Property(entity => entity.WeekDefinitionId).IsRequired();
|
builder.Property(entity => entity.WeekDefinitionId).IsRequired();
|
||||||
builder.Property(entity => entity.WeeklyPoolId).IsRequired();
|
builder.Property(entity => entity.WeeklyPoolId).IsRequired();
|
||||||
|
builder.Property(entity => entity.PackageId).IsRequired();
|
||||||
builder.Property(entity => entity.BalancesEarned).IsRequired();
|
builder.Property(entity => entity.BalancesEarned).IsRequired();
|
||||||
builder.Property(entity => entity.ValuePerBalance).IsRequired();
|
builder.Property(entity => entity.ValuePerBalance).IsRequired();
|
||||||
builder.Property(entity => entity.TotalAmount).IsRequired();
|
builder.Property(entity => entity.TotalAmount).IsRequired();
|
||||||
@@ -50,10 +51,16 @@ public class UserCommissionPayoutConfiguration : IEntityTypeConfiguration<UserCo
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
// Composite Index برای UserId و WeekDefinitionId
|
// رابطه با Package
|
||||||
builder.HasIndex(e => new { e.UserId, e.WeekDefinitionId })
|
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()
|
.IsUnique()
|
||||||
.HasDatabaseName("IX_UserCommissionPayout_UserId_WeekDefinitionId");
|
.HasDatabaseName("IX_UserCommissionPayout_User_WeekDef_Package");
|
||||||
|
|
||||||
// Index برای WeeklyPoolId
|
// Index برای WeeklyPoolId
|
||||||
builder.HasIndex(e => e.WeeklyPoolId)
|
builder.HasIndex(e => e.WeeklyPoolId)
|
||||||
|
|||||||
+8
@@ -22,6 +22,14 @@ public class UserWalletChangeLogConfiguration : IEntityTypeConfiguration<UserWal
|
|||||||
builder.Property(entity => entity.ChangeNerworkValue).IsRequired(true);
|
builder.Property(entity => entity.ChangeNerworkValue).IsRequired(true);
|
||||||
builder.Property(entity => entity.IsIncrease).IsRequired(true);
|
builder.Property(entity => entity.IsIncrease).IsRequired(true);
|
||||||
builder.Property(entity => entity.RefrenceId).IsRequired(false);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -17,6 +17,7 @@ public class WeeklyCommissionPoolConfiguration : IEntityTypeConfiguration<Weekly
|
|||||||
builder.Property(entity => entity.Id).UseIdentityColumn();
|
builder.Property(entity => entity.Id).UseIdentityColumn();
|
||||||
|
|
||||||
builder.Property(entity => entity.WeekDefinitionId).IsRequired();
|
builder.Property(entity => entity.WeekDefinitionId).IsRequired();
|
||||||
|
builder.Property(entity => entity.PackageId).IsRequired();
|
||||||
builder.Property(entity => entity.TotalPoolAmount).IsRequired();
|
builder.Property(entity => entity.TotalPoolAmount).IsRequired();
|
||||||
builder.Property(entity => entity.TotalBalances).IsRequired();
|
builder.Property(entity => entity.TotalBalances).IsRequired();
|
||||||
builder.Property(entity => entity.ValuePerBalance).IsRequired();
|
builder.Property(entity => entity.ValuePerBalance).IsRequired();
|
||||||
@@ -30,10 +31,16 @@ public class WeeklyCommissionPoolConfiguration : IEntityTypeConfiguration<Weekly
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
// Index یونیک برای WeekDefinitionId
|
// رابطه با Package
|
||||||
builder.HasIndex(e => e.WeekDefinitionId)
|
builder.HasOne(entity => entity.Package)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(entity => entity.PackageId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
// Index یونیک ترکیبی: هر هفته × هر پکیج فقط یک استخر
|
||||||
|
builder.HasIndex(e => new { e.WeekDefinitionId, e.PackageId })
|
||||||
.IsUnique()
|
.IsUnique()
|
||||||
.HasDatabaseName("IX_WeeklyCommissionPool_WeekDefinitionId");
|
.HasDatabaseName("IX_WeeklyCommissionPool_WeekDef_Package");
|
||||||
|
|
||||||
// Index برای IsCalculated
|
// Index برای IsCalculated
|
||||||
builder.HasIndex(e => e.IsCalculated)
|
builder.HasIndex(e => e.IsCalculated)
|
||||||
|
|||||||
Reference in New Issue
Block a user