Phase 1.5: EF Migration + Data Seed + Backfill

MIGRATION (AddPackageBasedSystem):
- Adds 11 new columns to Packages table
- Creates PackageFeatures table (Package×ClubFeature junction)
- Adds PackageId FK to: ClubMembershipCycles, WeeklyCommissionPools,
  UserCommissionPayouts, NetworkWeeklyBalances, UserWalletChangeLogs
- Adds First/LastActivationDate, First/LastPackageId to ClubMemberships
- Drops old unique indexes, creates new composite unique indexes:
  (WeekDef,Package), (User,WeekDef,Package)

DATA MIGRATION (embedded in EF migration):
1. Seeds Golden Package (Id=1): Price=56M, ActivationFee=25.2M,
   DiscountMultiplier=2.0, MagicWalletMultiplier=2.5, MaxBalancesPerLeg=300,
   MaxNetworkLevel=15, MagicWalletMaxDeposit=1B, MagicWalletMaxCredit=2.5B
2. Backfills PackageId=1 on all existing commission/network records
3. Backfills ClubMembership First/Last fields from existing ActivatedAt

FIXES:
- ClubMembership First/Last fields now nullable (DateTime?, long?)
  for backward compat with existing records
- UserPackagePurchaseConfiguration: .WithMany() → .WithMany(p => p.Purchases)
  to prevent shadow FK PackageId1

Build: 0 errors, 73 warnings
This commit is contained in:
masoodafar-web
2026-02-25 22:49:12 +03:30
parent ae92ab8697
commit a9cd2fd67a
6 changed files with 6033 additions and 14 deletions
@@ -25,34 +25,34 @@ public class ClubMembership : BaseAuditableEntity
/// <summary>
/// اولین فعال‌سازی — فقط یک بار ست می‌شود، هیچ‌وقت overwrite نمی‌شود
/// </summary>
public DateTime FirstActivationDate { get; set; }
public DateTime? FirstActivationDate { get; set; }
/// <summary>
/// اولین پکیج خریداری‌شده — فقط یک بار ست می‌شود
/// </summary>
public long FirstPackageId { get; set; }
public long? FirstPackageId { get; set; }
/// <summary>
/// FirstPackage Navigation Property
/// </summary>
public virtual Package FirstPackage { get; set; }
public virtual Package? FirstPackage { get; set; }
/// <summary>
/// آخرین/جاری فعال‌سازی — هر خرید مجدد بروزرسانی می‌شود
/// مبنای تشخیص "فعال‌شدگان این هفته" (Q22)
/// </summary>
public DateTime LastActivationDate { get; set; }
public DateTime? LastActivationDate { get; set; }
/// <summary>
/// آخرین/جاری پکیج — هر خرید مجدد بروزرسانی می‌شود
/// مبنای carryover per-package (Q23)
/// </summary>
public long LastPackageId { get; set; }
public long? LastPackageId { get; set; }
/// <summary>
/// LastPackage Navigation Property
/// </summary>
public virtual Package LastPackage { get; set; }
public virtual Package? LastPackage { get; set; }
/// <summary>
/// [DEPRECATED] تاریخ فعال‌سازی — جایگزین با FirstActivationDate + LastActivationDate