# 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**:
```sql
-- برای هر کاربر با شارژ >= 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**:
```sql
-- نسخه کامل:
SUM(uwcl.ChangeValue) >= 56000000  -- از تاریخچه

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

---

## 🔧 Technical Details

### Transaction Strategy

**قبلی (اشتباه)**:
```sql
BEGIN TRANSACTION;  -- یک transaction بزرگ
  -- 100 INSERT...
COMMIT TRANSACTION;
```
❌ با cursor سازگار نیست! → `log file overflow`

**فعلی (صحیح)**:
```sql
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**:
```sql
-- اشتباه (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

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

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

---

## 🧪 Testing Queries

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

```sql
-- نسخه کامل:
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. تأیید ویژگی‌های ثبت شده

```sql
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

```sql
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
