Files
docs/archive/03-BACKEND/CMS/club-membership-migration.md
T
masoodafar-web 5965b98728 update
2026-01-03 18:27:49 +03:30

11 KiB
Raw Blame History

Club Membership Migration Scripts

Created: 2025-12-09
Purpose: مهاجرت کاربران موجود به سیستم باشگاه مشتریان
Location: /dbbkup/


📋 Overview

این اسکریپت‌ها کاربرانی که قبل از راه‌اندازی سیستم باشگاه مشتریان، مبلغ 56 میلیون ریال شارژ کرده‌اند را به‌طور خودکار عضو باشگاه می‌کنند.


📄 Scripts

1. MigrateUsersToClubMembership.sql (نسخه کامل)

Path: /dbbkup/MigrateUsersToClubMembership.sql

Features:

  • بررسی UserWalletChangeLogs برای محاسبه مجموع شارژ‌ها
  • Fallback به Transactions اگر Logs خالی بود
  • ثبت تاریخ دقیق اولین شارژ به‌عنوان ActivatedAt
  • Skip کاربرانی که قبلاً عضو باشگاه هستند
  • Transaction-safe (هر کاربر یک transaction جداگانه)
  • گزارش کامل (موفقیت‌ها + خطاها)

What It Does:

-- برای هر کاربر با شارژ >= 56M:
1. INSERT INTO ClubMemberships (UserId, ActivatedAt=FirstChargeDate, InitialContribution=25M)
2. INSERT INTO ClubMembershipHistories (Action=0, Reason='فعال‌سازی خودکار - مهاجرت')
3. INSERT INTO UserClubFeatures (ClubFeatureId IN (1,2,3,4), Notes='اعطا شده خودکار')

Sample Output:

╔═══════════════════════════════════════════════════════════════╗
║      شروع فرآیند انتقال کاربران به باشگاه مشتریان           ║
╚═══════════════════════════════════════════════════════════════╝

تاریخ و زمان اجرا: 2025-12-09 16:30:00.0000000
مبلغ سهم استخر: 25,000,000 ریال

─────────────────────────────────────────────────────────────────
📊 تعداد کاربران کاندید: 45
─────────────────────────────────────────────────────────────────
🔄 شروع ثبت عضویت‌ها...

✓ کاربر 1001 (علی محمدی - 1234567890): عضویت با ID 501 ایجاد شد.
✓ کاربر 1002 (سارا احمدی - 0987654321): عضویت با ID 502 ایجاد شد.
...

─────────────────────────────────────────────────────────────────
╔═══════════════════════════════════════════════════════════════╗
║                    گزارش نهایی مهاجرت                        ║
╚═══════════════════════════════════════════════════════════════╝

تعداد کل کاندیدها: 45
تعداد قبلاً عضو: 0
تعداد پردازش شده: 45
تعداد خطا: 0
مجموع سهم استخر: 1,125,000,000 ریال

✓ فرآیند مهاجرت با موفقیت به پایان رسید.

2. MigrateUsersToClubMembership_Simple.sql (نسخه ساده)

Path: /dbbkup/MigrateUsersToClubMembership_Simple.sql

Features:

  • بررسی موجودی فعلی (UserWallets.Balance >= 56M)
  • سریع‌تر از نسخه کامل
  • برای سیستم‌هایی که تاریخچه شارژ ندارند
  • همان Transaction safety

Difference:

-- نسخه کامل:
SUM(uwcl.ChangeValue) >= 56000000  -- از تاریخچه

-- نسخه ساده:
uw.Balance >= 56000000             -- از موجودی فعلی

🔧 Technical Details

Transaction Strategy

قبلی (اشتباه):

BEGIN TRANSACTION;  -- یک transaction بزرگ
  -- 100 INSERT...
COMMIT TRANSACTION;

با cursor سازگار نیست! → log file overflow

فعلی (صحیح):

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRANSACTION;     -- transaction جداگانه
      INSERT ClubMemberships;
      INSERT ClubMembershipHistories;
      INSERT UserClubFeatures (4 rows);
    COMMIT TRANSACTION;    -- برای هر کاربر
END

هر کاربر مستقل → اگر یکی خطا داد، بقیه commit می‌شوند


Schema Compatibility

تغییرات از Schema واقعی:

  1. حذف User.ClubMembershipId (این ستون وجود نداره!)
  2. رابطه: ClubMemberships.UserId → Users.Id (یک‌طرفه)
  3. Action از نوع INT است (نه NVARCHAR):
    • 0 = Activated
    • 1 = Deactivated

Unicode Encoding:

-- اشتباه (encoding خراب):
N'فارسی'  -- در SELECT باز هم خراب می‌شه!

-- درست:
CAST(N'فعال‌سازی خودکار' AS NVARCHAR(500))

📊 Data Flow

┌─────────────────────────────────────────────────────────┐
│  1. Query: Users with TotalCharge >= 56M               │
│     Sources: UserWalletChangeLogs OR Transactions      │
└─────────────────────────────────────────────────────────┘
                        ↓
┌─────────────────────────────────────────────────────────┐
│  2. Filter: Skip users already in ClubMemberships      │
└─────────────────────────────────────────────────────────┘
                        ↓
┌─────────────────────────────────────────────────────────┐
│  3. For Each User (in cursor):                         │
│     BEGIN TRANSACTION                                   │
│     ├─ INSERT ClubMembership                           │
│     │    (UserId, ActivatedAt=FirstCharge,             │
│     │     InitialContribution=25M)                     │
│     ├─ INSERT ClubMembershipHistory                    │
│     │    (Action=0, Reason='مهاجرت داده‌ها')           │
│     └─ INSERT UserClubFeatures (x4)                    │
│         (ClubFeatureId IN (1,2,3,4))                   │
│     COMMIT TRANSACTION                                  │
└─────────────────────────────────────────────────────────┘
                        ↓
┌─────────────────────────────────────────────────────────┐
│  4. Report: Success count, Errors, Summary             │
└─────────────────────────────────────────────────────────┘

⚙️ Configuration Variables

DECLARE @InitialContribution BIGINT = 25000000;  -- 25M به صندوق
DECLARE @ChargeAmount BIGINT = 56000000;         -- 56M شارژ
DECLARE @CurrentDateTime DATETIME2(7) = SYSDATETIME();

Adjustable:

  • @ChargeAmount: تغییر حداقل مبلغ شارژ
  • @InitialContribution: تغییر سهم استخر

🧪 Testing Queries

1. شمارش کاربران واجد شرایط

-- نسخه کامل:
SELECT COUNT(DISTINCT u.Id)
FROM [CMS].[Users] u
INNER JOIN [CMS].[UserWallets] uw ON uw.UserId = u.Id
INNER JOIN [CMS].[UserWalletChangeLogs] uwcl ON uwcl.WalletId = uw.Id
WHERE u.IsDeleted = 0
  AND uwcl.IsIncrease = 1
  AND uwcl.ChangeValue > 0
GROUP BY u.Id
HAVING SUM(uwcl.ChangeValue) >= 56000000;

-- نسخه ساده:
SELECT COUNT(*)
FROM [CMS].[Users] u
INNER JOIN [CMS].[UserWallets] uw ON uw.UserId = u.Id
LEFT JOIN [CMS].[ClubMemberships] cm ON cm.UserId = u.Id
WHERE u.IsDeleted = 0
  AND cm.Id IS NULL
  AND uw.Balance >= 56000000;

2. تأیید ویژگی‌های ثبت شده

SELECT 
    cm.Id AS MembershipId,
    cm.UserId,
    u.FirstName + ' ' + u.LastName AS FullName,
    cm.ActivatedAt,
    COUNT(ucf.Id) AS FeaturesCount
FROM [CMS].[ClubMemberships] cm
INNER JOIN [CMS].[Users] u ON u.Id = cm.UserId
LEFT JOIN [CMS].[UserClubFeatures] ucf ON ucf.ClubMembershipId = cm.Id
WHERE cm.Created >= '2025-12-09'  -- امروز
GROUP BY cm.Id, cm.UserId, u.FirstName, u.LastName, cm.ActivatedAt
HAVING COUNT(ucf.Id) != 4;  -- باید 4 تا باشه!

3. چک کردن History

SELECT 
    h.UserId,
    u.FirstName + ' ' + u.LastName AS FullName,
    h.Action,
    h.Reason,
    h.Created
FROM [CMS].[ClubMembershipHistories] h
INNER JOIN [CMS].[Users] u ON u.Id = h.UserId
WHERE h.CreatedBy = 'MigrationScript'
ORDER BY h.Created DESC;

🚨 Error Handling

Script Behavior:

  • هر transaction جداگانه → اگر یک کاربر fail شد، بقیه commit می‌شوند
  • خطاها در @ProcessLog ذخیره می‌شوند
  • گزارش نهایی شامل لیست کامل خطاها

Common Errors:

  1. "Invalid column 'UserName'" → ستون وجود نداره (باید FirstName + LastName)
  2. "Invalid column 'ClubMembershipId'" → در جدول Users نیست
  3. "Conversion failed 'Activated'" → باید 0 باشه نه 'Activated'
  4. "Transaction cannot be committed" → نباید SET XACT_ABORT ON باشه با cursor

📝 Notes

  1. Idempotent: اجرای مجدد اسکریپت، کاربران قبلی را skip می‌کند
  2. Rollback-Safe: اگر کل script fail شد، چیزی commit نمی‌شه
  3. Performance: برای 1000+ کاربر، ممکنه 5-10 دقیقه طول بکشه
  4. Logging: تمام عملیات‌ها با CreatedBy = 'MigrationScript' قابل شناسایی هستند

🎯 Post-Migration Checklist

  • شمارش کاربران مهاجرت شده = تعداد موردانتظار
  • تمام اعضای جدید 4 ویژگی دارند (UserClubFeatures.Count = 4)
  • همه ClubMembershipHistories با Action = 0 ثبت شده‌اند
  • مجموع InitialContribution با ClubMemberships.Count × 25M برابره
  • هیچ خطایی در گزارش نهایی نیست (@ErrorCount = 0)

Last Updated: 2025-12-09
Author: Migration Script Generator
Version: 1.0