update
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user