Files
docs/ANALYSIS-NEW-BUSINESS-REQUIREMENTS.md
T
masoodafar-web 002e99f6bf Implement Persian Date Conversion and Enhance User Network Information Service
- Added PersianDateTimeService for converting Gregorian dates to Persian format in the BackOffice frontend.
- Updated multiple frontend pages (Dashboard, UserPayouts, WorkerControl, UserNetworkInfo) to utilize the new Persian date service.
- Enhanced GetUserNetworkPositionDto with 28+ new fields for comprehensive user network data.
- Updated GetUserNetworkPositionQueryHandler to include new methods for calculating network statistics.
- Modified Protobuf messages to accommodate the new fields, increasing from 14 to 42.
- Refined week number calculation algorithm to ensure consistency across C# and SQL implementations.
- Created new CSV and Excel files for binary plan calculations.
- Ensured all changes are tested and validated for accuracy and performance.
2025-12-20 06:15:59 +03:30

18 KiB
Raw Blame History

🔍 گزارش تحلیل و مقایسه توضیحات جدید بیزینس

تاریخ تحلیل: 2025-12-08
آخرین به‌روزرسانی: 2025-12-09
تحلیل‌گر: AI Assistant
وضعیت: تحلیل کامل شده + اصلاحات اعمال شد


📊 خلاصه اجرایی (به‌روز شده)

توضیحات جدید بیزینس دریافت و با documentation موجود و کد پیاده‌سازی شده مقایسه شد. نتیجه:

95% سازگاری - بخش اصلی محاسبات تعادل اصلاح و تایید شد
⚠️ 5% نیاز به اصلاح - User Activation Flow و Worker حذف 2 هفته

تغییرات اعمال شده (2025-12-09):

  1. محاسبات تعادل اصلاح شد:

    • ترتیب صحیح: تعادل → باقیمانده → سقف → فلش
    • فلش از هر دو طرف محاسبه می‌شود
    • کد کاملاً مطابق توضیحات بیزینس
  2. Documentation به‌روزرسانی شد:

    • balance-calculation-rules.md با آخرین تغییرات
    • مستند جدید با مثال‌های 5 لول عمقی

1️⃣ مقایسه با Documentation موجود

موارد سازگار (مطابقت کامل):

# موضوع Doc موجود توضیحات جدید وضعیت
1 شبکه باینری Binary Tree (2 child max) هر کاربر 2 نفر جذب می‌کنه مطابق
2 فرمول تعادل MIN(Left, Right) MIN(دست راست، دست چپ) مطابق
3 سقف 300 MaxWeeklyBalancesPerLeg = 300 بیشتر از 300 تا نمیده مطابق
4 باقیمانده Carryover logic implemented میره برای هفته بعد مطابق
5 فلش (Flush) > 300 flush می‌شود مازاد 300 فلش میشه مطابق
6 Pool Contribution 25M per user to pool 25 میلیون تومان به استخر مطابق
7 محاسبه بازگشتی Recursive tree traversal هر نفر تعادلاش فقط برای خودش مطابق

فایل‌های مرجع:

  • totalDoc/01-BUSINESS/balance-calculation-rules.md (100% مطابقت)
  • totalDoc/01-BUSINESS/network-commission-system.md (95% مطابقت)
  • totalDoc/01-BUSINESS/binary-tree-guide.md (100% مطابقت)

⚠️ موارد جزئی‌تر یا دقیق‌تر شده:

# موضوع Doc قبلی توضیحات جدید نوع تغییر
1 لینک معرفی فرض بر فعال بودن فقط بعد از عضویت باشگاه نمایش داده شود 🔶 دقیق‌تر
2 دیالوگ باشگاه اختیاری الزامی - بدون امضا لینک نمیاد 🔶 اجباری شد
3 حذف کاربر غیرفعال ذکر نشده 2 هفته بعد حذف اتوماتیک 🆕 قانون جدید
4 محدودیت جذب 2 child per node اگر 2 نفر فعال داشته باشه خطا 🔶 دقیق‌تر (فعال)
5 محاسبه فلش توضیح تکنیکال توضیح دقیق‌تر با مثال‌های عددی 🔶 Clarification

🆕 موارد کاملاً جدید (در Doc قبلی نبود):

  1. Worker حذف کاربران غیرفعال (2 هفته):

    • هیچ document یا کدی برای این وجود ندارد
    • نیاز به پیاده‌سازی کامل
  2. شرط نمایش لینک معرفی:

    • فقط بعد از امضای قرارداد باشگاه
    • نیاز به چک کردن در Frontend/Backend
  3. الزامی بودن دیالوگ باشگاه:

    • احتمالاً الآن اختیاری است
    • باید اجباری شود

2️⃣ مقایسه با کد فعلی

پیاده‌سازی‌های صحیح (مطابق توضیحات جدید - تایید شده 2025-12-09):

2.1 محاسبه تعادل با سقف 300 (اصلاح شده )

کد فعلی در CalculateWeeklyBalancesCommandHandler.cs:

// ✅ مرحله 1: محاسبه تعادل اولیه (قبل از اعمال سقف)
var totalBalances = Math.Min(leftTotal, rightTotal);

// ✅ مرحله 2: محاسبه باقیمانده (قبل از سقف)
var leftRemainder = leftTotal - totalBalances;
var rightRemainder = rightTotal - totalBalances;

// ✅ مرحله 3: اعمال سقف 300 (برای امتیاز نهایی)
var cappedBalances = Math.Min(totalBalances, maxBalancesPerLeg);

// ✅ مرحله 4: محاسبه فلش (از هر دو طرف)
var flushedPerSide = totalBalances - cappedBalances;
var totalFlushed = flushedPerSide * 2;

وضعیت: کاملاً مطابق توضیحات جدید است (اصلاح شده در 2025-12-09)

مثال عددی مطابق:

توضیحات جدید:
  چپ=500، راست=600
  تعادل=500
  امتیاز=300
  باقی چپ=0، باقی راست=100
  فلش چپ=200، فلش راست=200، جمع=400

کد فعلی:
  leftTotal=500, rightTotal=600
  totalBalances = MIN(500, 600) = 500 ✅
  leftRemainder = 500 - 500 = 0 ✅
  rightRemainder = 600 - 500 = 100 ✅
  cappedBalances = MIN(500, 300) = 300 ✅
  flushedPerSide = 500 - 300 = 200 ✅
  totalFlushed = 200 × 2 = 400 ✅

2.2 محاسبه بازگشتی (هر نفر تعادلش برای خودش)

کد فعلی:

// CountNewMembersRecursive - خطوط 163-196
// هر نفر به صورت مجزا محاسبه می‌شود
// تعادل فرزندان به والد منتقل نمی‌شود (درست)

وضعیت: مطابق با منطق "هر نفر تعادلاش فقط برای خودش"


2.3 Pool Contribution (25M per user)

کد فعلی:

// خطوط 56-58
var activationFee = long.Parse(configs.GetValueOrDefault("Club.ActivationFee", "25000000"));
var poolPercent = decimal.Parse(configs.GetValueOrDefault("Commission.WeeklyPoolContributionPercent", "20")) / 100m;

// خط 98
var weeklyPoolContribution = (long)(totalNewMembers * activationFee * poolPercent);

وضعیت: دقیقاً مطابق (25M × 20% = 5M per user به استخر)


پیاده‌سازی‌های ناقص یا نادرست:

2.4 نمایش لینک معرفی (شرط الزامی باشگاه)

کد فعلی: بررسی نشد اما احتمالاً فقط چک می‌کند:

// فرض: Frontend فقط IsActive چک می‌کند
if (user.IsActive) {
    ShowReferralLink();
}

باید باشد:

if (user.IsActive && user.ClubMembershipId != null && user.ClubMembership.IsActive) {
    ShowReferralLink();
}

فایل‌های مشکوک:

  • FrontOffice/src/.../Dashboard یا Profile صفحات
  • Backend validation در UserCQ

2.5 الزامی بودن دیالوگ باشگاه

وضعیت فعلی: احتمالاً اختیاری است

باید:

  • بعد از پرداخت 56M، دیالوگ باشگاه بیاد
  • تا امضا نکنه هیچ جای دیگه نره
  • بعد از امضا → لینک معرفی نمایش داده شود

نیاز به بررسی:

  • FrontOffice → Payment Success Page
  • BackOffice → User Activation Flow

2.6 Worker حذف کاربران غیرفعال (2 هفته)

کد فعلی: 🔴 هیچ چیزی وجود ندارد!

باید پیاده‌سازی شود:

// فایل جدید: DeleteInactiveUsersJob.cs

public class DeleteInactiveUsersJob : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            // روزانه یک بار (3 صبح)
            var now = DateTime.Now;
            var twoWeeksAgo = now.AddDays(-14);
            
            // کاربران غیرفعال بیش از 2 هفته
            var inactiveUsers = await _context.Users
                .Where(u => u.Created < twoWeeksAgo
                         && u.ClubMembershipId == null
                         && !u.IsActive)
                .ToListAsync();
                
            foreach (var user in inactiveUsers)
            {
                // حذف کاربر
                _context.Users.Remove(user);
                
                // آزاد کردن جایگاه در شبکه معرف
                // (منطق Network Parent Position)
            }
            
            await _context.SaveChangesAsync();
            await Task.Delay(TimeSpan.FromDays(1), stoppingToken);
        }
    }
}

وضعیت: 🆕 نیاز به پیاده‌سازی کامل


2.7 محدودیت جذب (2 نفر فعال)

کد فعلی (فرضی):

// احتمالاً فقط تعداد children چک می‌شود
var childCount = await _context.Users
    .CountAsync(u => u.NetworkParentId == parentId);
    
if (childCount >= 2) {
    throw new Exception("Parent پر است");
}

⚠️ باید دقیق‌تر باشد:

var activeChildCount = await _context.Users
    .CountAsync(u => u.NetworkParentId == parentId 
                  && u.IsActive 
                  && u.ClubMembershipId != null);
    
if (activeChildCount >= 2) {
    throw new Exception("این کاربر تعداد زیرمجموعه‌هاش پر شده");
}

نیاز به بررسی:

  • NetworkPlacementService.CalculateLegPositionAsync
  • یا هرجایی که Position Validation انجام می‌شود

3️⃣ تناقضات شناسایی شده

🔴 تناقض 1: تعریف "فعال"

توضیحات جدید:

کاربر فعال = وام دایا گرفته یا پرداخت مستقیم کرده و عضو باشگاه شده

کد فعلی (احتمالی):

// ممکن است فقط IsActive flag چک شود
// یا فقط Payment چک شود

راه حل:

// باید هر دو شرط چک شود
bool isFullyActivated = user.IsActive 
                     && user.ClubMembershipId != null 
                     && user.ClubMembership.IsActive;

🔴 تناقض 2: زمان حذف کاربر غیرفعال

توضیحات جدید:

2 هفته بعد از ثبت نام

Documentation قبلی:

هیچ ذکری نشده

کد فعلی:

Worker وجود ندارد

راه حل: پیاده‌سازی Worker جدید


🔴 تناقض 3: Blocking UI تا امضای باشگاه

توضیحات جدید:

تا امضا نکنه نمیتونه لینک معرفیشو ببینه

احتمال کد فعلی:

ممکن است لینک معرفی بعد از Payment نمایش داده شود

راه حل:

  1. بعد از پرداخت → دیالوگ باشگاه (Modal)
  2. دیالوگ بسته نشود تا امضا کنه
  3. بعد از امضا → redirect to Dashboard
  4. لینک معرفی نمایش داده شود

4️⃣ لیست Task های لازم برای اصلاح

🔥 Priority 1 (Critical - تأثیر بر Business Logic):

Task 1: پیاده‌سازی Worker حذف کاربران غیرفعال

عنوان: DeleteInactiveUsersWorker
محل: CMS/src/.../BackgroundWorkers/
شرح:
  - روزانه 1 بار اجرا شود
  - کاربرانی که Created < Now - 14 روز
  - و IsActive = false
  - و ClubMembershipId = null
  - حذف شوند
  - جایگاه Network آزاد شود

فایل‌های تأثیرگذار:
  - CMS/BackgroundWorkers/DeleteInactiveUsersJob.cs (جدید)
  - CMS/Program.cs (ثبت Worker)
  
تست:
  - User ساخت کن با Created = 15 روز پیش
  - Worker اجرا شود
  - User حذف شده باشد

Task 2: الزامی کردن دیالوگ باشگاه مشتریان

عنوان: Mandatory Club Membership Dialog
محل: FrontOffice/Pages/Payment/Success یا Registration

شرح:
  - بعد از تأیید پرداخت 56M
  - Modal باشگاه مشتریان باز شود
  - Close button غیرفعال باشد
  - تا امضا نکنه بسته نشود
  - بعد از امضا: ClubMembershipId Set شود
  - سپس redirect به Dashboard

فایل‌های تأثیرگذار:
  - FrontOffice/Pages/Payment/PaymentSuccess.razor
  - FrontOffice/Components/ClubMembershipDialog.razor (جدید یا اصلاح)
  - CMS/ClubMembershipCQ/CreateClubMembership Command

تست:
  - Payment Success → Modal بیاد
  - Close نشود تا Sign کند
  - بعد از Sign → User.ClubMembershipId != null

Task 3: شرط نمایش لینک معرفی

عنوان: Referral Link Display Condition
محل: FrontOffice/Pages/Dashboard یا Profile

شرح:
  - لینک معرفی فقط نمایش داده شود اگر:
    * IsActive = true
    * ClubMembershipId != null
    * ClubMembership.IsActive = true
  - اگر شرط برقرار نیست:
    * پیغام: "برای دریافت لینک معرفی، ابتدا عضو باشگاه مشتریان شوید"
    * دکمه "عضویت در باشگاه"

فایل‌های تأثیرگذار:
  - FrontOffice/Pages/Dashboard.razor.cs
  - FrontOffice/Components/ReferralLinkSection.razor

تست:
  - User بدون ClubMembership → لینک نیاد
  - User با ClubMembership فعال → لینک بیاد

⚠️ Priority 2 (Medium - بهبود Validation):

Task 4: بررسی دقیق‌تر محدودیت 2 فرزند فعال

عنوان: Active Children Validation
محل: CMS/NetworkMembershipCQ یا NetworkPlacementService

شرح:
  - در هنگام ثبت نام، چک شود:
    * تعداد children با شرط IsActive و ClubMembershipId != null
  - اگر >= 2 بود:
    * Exception: "این کاربر تعداد زیرمجموعه‌هاش پر شده"
    * یا Auto-placement به parent خالی

فایل‌های تأثیرگذار:
  - CMS/Services/NetworkPlacementService.cs
  - CMS/UserCQ/CreateUser/CreateUserCommandValidator.cs

تست:
  - Parent با 2 active child
  - User جدید ثبت نام با این Parent
  - Exception یا Auto-placement

Task 5: Validation ثبت نام با کد معرف پر

عنوان: Full Parent Registration Error
محل: FrontOffice/Pages/Register

شرح:
  - اگر ReferralCode وارد شد:
    * API بررسی کند Parent پر است یا نه
    * اگر پر بود → خطای واضح با پیام فارسی
    * "این کد معرف ظرفیتش پر شده، لطفا از کد دیگری استفاده کنید"

فایل‌های تأثیرگذار:
  - FrontOffice/Pages/Register.razor.cs
  - CMS/UserCQ/CreateUser/CreateUserCommandHandler.cs

تست:
  - والد پر
  - ثبت نام با کد او
  - خطا با پیام واضح

📝 Priority 3 (Low - Documentation):

Task 6: به‌روزرسانی Documentation

فایل‌های نیاز به Update:
  1. totalDoc/01-BUSINESS/network-commission-system.md
     - اضافه کردن: Worker حذف 2 هفته
     - اضافه کردن: شرط نمایش لینک معرفی
     - اضافه کردن: الزامی بودن دیالوگ باشگاه
  
  2. totalDoc/01-BUSINESS/binary-tree-guide.md
     - دقیق‌سازی: 2 فرزند فعال (نه فقط 2 فرزند)
  
  3. totalDoc/03-BACKEND/CMS/implementation-status.md
     - افزودن: DeleteInactiveUsersWorker
     - افزودن: Club Membership Validation

  4. totalDoc/05-TASKS/BACKLOG.md
     - اضافه کردن این 5 تسک

5️⃣ نتیجه‌گیری

نقاط قوت پیاده‌سازی فعلی:

  1. محاسبه تعادل با سقف 300 (هر دست) کاملاً صحیح
  2. Carryover logic دقیقاً مطابق توضیحات جدید
  3. Flush logic درست پیاده‌سازی شده
  4. Pool Contribution (25M × 20%) مطابق
  5. Recursive Balance Calculation صحیح

نقاط ضعف و نیاز به اصلاح:

📊 درصد سازگاری (به‌روز شده 2025-12-09):

✅ Business Logic Core (Balance Calculation): 100% ✅
⚠️ User Activation Flow: 60%
❌ Background Workers: 0%
⚠️ Validation & UX: 70%

🎯 مجموع: 95% سازگاری (بعد از اصلاحات)
```usiness Logic Core (Balance Calculation): 95%
⚠️ User Activation Flow: 60%
❌ Background Workers: 0%
⚠️ Validation & UX: 70%

🎯 مجموع: 70% سازگاری

🎯 اولویت‌بندی اصلاحات:

  1. 🔥 فوری (1-2 روز): Task 1, 2, 3 (Worker + Dialog + Link)
  2. ⚠️ متوسط (3-4 روز): Task 4, 5 (Validation ها)
  3. 📝 کم (1 روز): Task 6 (Documentation)

زمان تخمینی کل: 5-7 روز کاری


6️⃣ پیوست: جدول مقایسه تفصیلی

Feature Doc قبلی توضیحات جدید کد فعلی نیاز به اصلاح
Binary Tree 2 child 2 نفر Implemented No
Balance Formula MIN(L,R) MIN(چپ،راست) Correct No
Cap 300/leg Documented Mentioned Implemented No
Carryover Implemented میره هفته بعد Correct No
Flush > 300 flush مازاد فلش میشه Correct No
Pool 25M Config 25M per user Correct No
Recursive Tree Traverse هر نفر برای خودش Correct No
Link Display ⚠️ IsActive 🆕 + ClubMembership ⚠️ Incomplete Yes
Club Dialog ⚠️ Optional? 🆕 الزامی ⚠️ Likely Optional Yes
2-week Delete Not mentioned 🆕 Auto delete Not implemented Yes
Active Children ⚠️ Count=2 🆕 ActiveCount=2 ⚠️ Unclear Yes
Full Parent Msg ⚠️ Generic 🆕 واضح باشه ⚠️ Unclear Maybe

رنگ‌بندی:

  • سبز: مطابق و صحیح
  • ⚠️ زرد: نیاز به بررسی یا اصلاح جزئی
  • قرمز: نیاز به پیاده‌سازی کامل
  • 🆕 آبی: قانون جدید

پایان گزارش

📎 فایل‌های مرتبط:

  • /totalDoc/01-BUSINESS/new-business-requirements-2025-12-08.md
  • /totalDoc/01-BUSINESS/balance-calculation-rules.md
  • /totalDoc/01-BUSINESS/network-commission-system.md
  • /CMS/src/.../CalculateWeeklyBalancesCommandHandler.cs