diff --git a/00-INDEX.md b/00-INDEX.md index 1c1a722..f509cf2 100644 --- a/00-INDEX.md +++ b/00-INDEX.md @@ -44,6 +44,12 @@ - ✅ **Daya Loan SMS**: ارسال پیامک خودکار هنگام تأیید وام دایا - ✅ **AppVersion UI Complete**: صفحه مدیریت نسخه با قابلیت افزودن جدید - ✅ **Mapping Fixes**: رفع مشکلات Mapster (Unit→Empty, WeeklyPools) +- ✅ **Commission Status Refactor**: انتقال تبدیل Status از BFF به FrontOffice client +- ✅ **ProcessWithdrawal Fix**: رفع خطای "PayoutId invalid" در BackOffice +- ✅ **WeekDisplayName Fix**: نمایش "هفته چهلم" به جای "1404-W40" +- ✅ **Withdrawals Page Fix**: رفع مشکل لود نشدن صفحه تأیید برداشت‌ها +- ✅ **Network Balances Enhanced**: نمایش نام کاربر + Carryover breakdown با Tooltip +- ✅ **WeekDefinitionId Fix**: رفع مشکل ارسال 0 به جای مقدار صحیح (Int64Value.Value) ### دستاوردهای ۶ دی: - ✅ **App Version Management**: سیستم کامل مدیریت نسخه اپلیکیشن‌های موبایل diff --git a/03-BACKEND/MAPSTER-COMMON-ISSUES.md b/03-BACKEND/MAPSTER-COMMON-ISSUES.md new file mode 100644 index 0000000..052311a --- /dev/null +++ b/03-BACKEND/MAPSTER-COMMON-ISSUES.md @@ -0,0 +1,244 @@ +# 🔧 Mapster - مشکلات رایج و راه‌حل‌ها + +> **آخرین بروزرسانی**: ۷ دی ۱۴۰۴ +> **نسخه Mapster**: 7.4.0 + +--- + +## 📋 فهرست مشکلات + +1. [Protobuf Int64Value Mapping](#1-protobuf-int64value-mapping) +2. [MediatR Unit to Empty](#2-mediatr-unit-to-empty) +3. [Repeated Fields (List) Mapping](#3-repeated-fields-list-mapping) +4. [Property Name Mismatch](#4-property-name-mismatch) +5. [Nullable Types](#5-nullable-types) + +--- + +## 1. Protobuf Int64Value Mapping + +### مشکل +فیلدهای `google.protobuf.Int64Value` (یا `StringValue`, `BoolValue` و غیره) که wrapper types هستند، در mapping مستقیم کار نمی‌کنند. + +### نشانه‌ها +- مقدار همیشه `0` یا `null` می‌شود +- Value در client ست شده ولی در server نادرست دریافت می‌شود + +### Proto: +```protobuf +import "google/protobuf/wrappers.proto"; + +message GetMyWeeklyBalancesRequest { + google.protobuf.Int64Value week_definition_id = 3; +} +``` + +### ❌ کد اشتباه: +```csharp +config.NewConfig() + .Map(dest => dest.WeekDefinitionId, src => src.WeekDefinitionId); // WRONG! +``` + +### ✅ کد صحیح: +```csharp +config.NewConfig() + .Map(dest => dest.WeekDefinitionId, + src => src.WeekDefinitionId != null ? src.WeekDefinitionId.Value : null); +``` + +### توضیح +`Int64Value` یک class wrapper است نه primitive type. باید `.Value` را extract کنید. + +--- + +## 2. MediatR Unit to Empty + +### مشکل +`MediatR.Unit` نمی‌تواند به `google.protobuf.WellKnownTypes.Empty` map شود. + +### نشانه‌ها +- Exception: `No mapping found for MediatR.Unit` +- gRPC call با void return کار نمی‌کند + +### ❌ کد اشتباه: +```csharp +// No mapping defined - will fail at runtime +return await _mediator.Send(command).Adapt(); +``` + +### ✅ راه‌حل: +```csharp +// در GeneralMapping.cs یا هر Profile +config.NewConfig() + .MapWith(_ => new Google.Protobuf.WellKnownTypes.Empty()); +``` + +### محل فایل: +`BackOffice.BFF.WebApi/Common/Mappings/GeneralMapping.cs` + +--- + +## 3. Repeated Fields (List) Mapping + +### مشکل +فیلدهای `repeated` در protobuf به property `RepeatedField` تبدیل می‌شوند که `add-only` هستند. + +### نشانه‌ها +- لیست همیشه خالی +- Exception: `Cannot set RepeatedField` + +### Proto: +```protobuf +message GetAllAppVersionsResponse { + repeated AppVersionItem items = 1; +} +``` + +### ❌ کد اشتباه: +```csharp +config.NewConfig, GetAllAppVersionsResponse>() + .Map(dest => dest.Items, src => src); // WRONG - Items is read-only +``` + +### ✅ کد صحیح: +```csharp +config.NewConfig, GetAllAppVersionsResponse>() + .MapWith(src => CreateResponse(src)); + +private static GetAllAppVersionsResponse CreateResponse(List items) +{ + var response = new GetAllAppVersionsResponse(); + foreach (var item in items) + { + response.Items.Add(item.Adapt()); + } + return response; +} +``` + +--- + +## 4. Property Name Mismatch + +### مشکل +نام property در DTO با نام در proto message یکی نیست. + +### نشانه‌ها +- فیلد همیشه `null` یا default value +- Auto-mapping کار نمی‌کند + +### مثال: +```protobuf +message MetaData { + int32 total_page = 2; // -> TotalPage in C# +} +``` + +```csharp +public class MetaDataDto +{ + public int TotalPages { get; set; } // WRONG: should be TotalPage +} +``` + +### ✅ راه‌حل 1 - اصلاح نام: +```csharp +public class MetaDataDto +{ + public int TotalPage { get; set; } // Match proto +} +``` + +### ✅ راه‌حل 2 - Explicit mapping: +```csharp +config.NewConfig() + .Map(dest => dest.TotalPages, src => src.TotalPage); +``` + +--- + +## 5. Nullable Types + +### مشکل +Nullable types در C# نیاز به handling خاص دارند. + +### Proto با nullable: +```protobuf +google.protobuf.Int64Value nullable_id = 1; +``` + +### ✅ در DTO: +```csharp +public long? NullableId { get; set; } +``` + +### ✅ Mapping: +```csharp +.Map(dest => dest.NullableId, + src => src.NullableId != null ? (long?)src.NullableId.Value : null) +``` + +--- + +## 🎯 Best Practices + +### 1. همیشه Explicit Mapping برای Complex Types +```csharp +// بهتر است همیشه explicit باشد +config.NewConfig() + .Map(dest => dest.Prop1, src => src.Prop1) + .Map(dest => dest.Prop2, src => src.Prop2); +``` + +### 2. استفاده از MapWith برای Custom Logic +```csharp +config.NewConfig() + .MapWith(src => new Dest + { + // full control + }); +``` + +### 3. فایل Profile مجزا برای هر Domain +``` +Common/Mappings/ +├── CommissionProfile.cs +├── NetworkProfile.cs +├── ClubProfile.cs +└── GeneralMapping.cs // for common types like Unit -> Empty +``` + +### 4. تست Mapping ها +```csharp +[Fact] +public void Should_Map_Request_To_Query() +{ + // Arrange + var request = new GetMyWeeklyBalancesRequest { WeekDefinitionId = 7 }; + + // Act + var query = request.Adapt(); + + // Assert + Assert.Equal(7, query.WeekDefinitionId); +} +``` + +--- + +## 📁 فایل‌های Profile در پروژه + +| پروژه | مسیر | محتوا | +|-------|------|-------| +| CMS | `WebApi/Common/Mappings/` | CommissionProfile, AppVersionProfile | +| BackOffice.BFF | `Application/Common/Mappings/` | CommissionProfile | +| BackOffice.BFF | `WebApi/Common/Mappings/` | GeneralMapping | +| FrontOffice.BFF | `WebApi/Common/Mappings/` | CommissionProfile | + +--- + +## 🔗 منابع + +- [Mapster Documentation](https://github.com/MapsterMapper/Mapster) +- [Protobuf Well-Known Types](https://protobuf.dev/reference/csharp/api-docs/class/google/protobuf/well-known-types/) +- [CHANGELOG-2025-12-27.md](../CHANGELOG-2025-12-27.md) - جزئیات بیشتر diff --git a/CHANGELOG-2025-12-27.md b/CHANGELOG-2025-12-27.md index bc3ab59..fbae81c 100644 --- a/CHANGELOG-2025-12-27.md +++ b/CHANGELOG-2025-12-27.md @@ -1,6 +1,6 @@ # 📝 Changelog - ۷ دی ۱۴۰۴ (27 December 2025) -> **Session**: بهینه‌سازی‌های Mapping + SystemConstants + SMS Templates + AppVersion UI +> **Session**: بهینه‌سازی‌های Mapping + SystemConstants + SMS Templates + AppVersion UI + Commission System Fixes --- @@ -12,6 +12,12 @@ 3. **SMS for Daya Loan** - ارسال پیامک هنگام تأیید وام دایا 4. **AppVersion UI** - تکمیل صفحه مدیریت نسخه در BackOffice 5. **Mapping Fixes** - رفع مشکلات Mapster +6. **Commission Status Refactoring** - انتقال تبدیل Status از BFF به FrontOffice +7. **ProcessWithdrawal Fix** - رفع خطای "PayoutId invalid" در BackOffice +8. **WeekDisplayName Fix** - نمایش صحیح نام هفته به جای فرمت 1404-W40 +9. **Withdrawals Page Fix** - رفع مشکل لود نشدن صفحه تأیید برداشت‌ها +10. **Network Balances Enhancement** - افزودن نام کاربر و جزئیات Carryover به صفحه balance‌ها +11. **WeekDefinitionId Mapping Fix** - رفع مشکل ارسال WeekDefinitionId=0 در FrontOffice.BFF --- @@ -269,6 +275,272 @@ config.NewConfig() --- +### 6. 🔄 Commission Status Refactoring ✅ + +**مشکل**: تبدیل enum عددی `CommissionPayoutStatus` به متن فارسی در BFF gateway انجام می‌شد. + +**راه‌حل**: انتقال منطق به FrontOffice client برای معماری بهتر. + +#### 6.1 FrontOffice.BFF - Simplify Response + +**فایل**: `FrontOffice.BFF.Application/.../GetMyWeeklyBalancesQueryHandler.cs` + +**قبل**: +```csharp +Status = MapStatusToString(x.Status) +``` + +**بعد**: +```csharp +Status = x.Status // Return int directly +``` + +#### 6.2 FrontOffice - CommissionService + +**فایل**: `FrontOffice.Main/Utilities/CommissionService.cs` + +```csharp +public static string MapStatus(int status) => status switch +{ + 0 => "در انتظار", // Pending + 1 => "پرداخت شده", // Paid + 2 => "درخواست برداشت", // WithdrawRequested + 3 => "برداشت شده", // Withdrawn + 4 => "خطای پرداخت", // PaymentFailed + 5 => "لغو شده", // Cancelled + _ => "نامشخص" +}; + +public static string GetStatusColor(int status) => status switch +{ + 0 => "warning", // Pending - زرد + 1 => "success", // Paid - سبز + 2 => "info", // WithdrawRequested - آبی + 3 => "success", // Withdrawn - سبز + 4 => "error", // PaymentFailed - قرمز + 5 => "default", // Cancelled - خاکستری + _ => "default" +}; +``` + +**Enum مرجع** (`CommissionPayoutStatus`): +```csharp +public enum CommissionPayoutStatus +{ + Pending = 0, + Paid = 1, + WithdrawRequested = 2, + Withdrawn = 3, + PaymentFailed = 4, + Cancelled = 5 +} +``` + +--- + +### 7. 🛠️ ProcessWithdrawal Fix ✅ + +**مشکل**: خطای "PayoutId invalid" هنگام تأیید/رد برداشت در BackOffice + +**علت**: `PayoutId` در mapping از CMS request به BackOffice.BFF command map نمی‌شد. + +**فایل**: `BackOffice.BFF.Application/Common/Mappings/CommissionProfile.cs` + +**قبل**: +```csharp +config.NewConfig(); +// PayoutId ignored! +``` + +**بعد**: +```csharp +config.NewConfig() + .Map(dest => dest.PayoutId, src => src.PayoutId) + .Map(dest => dest.Approve, src => src.Approve) + .Map(dest => dest.RejectionReason, src => src.RejectionReason); +``` + +--- + +### 8. 📅 WeekDisplayName Fix ✅ + +**مشکل**: نمایش "1404-W40" به جای "هفته چهلم" در dropdown انتخاب هفته + +**علت**: استفاده از `PersianWeekNumber` به جای `DisplayName` + +**فایل**: `CMS.Application/.../GetAllWeeklyPoolsQueryHandler.cs` + +**قبل**: +```csharp +WeekDisplayName = x.WeekDefinition.PersianWeekNumber // "1404-W40" +``` + +**بعد**: +```csharp +WeekDisplayName = x.WeekDefinition.DisplayName // "هفته چهلم" +``` + +--- + +### 9. 📋 Withdrawals Page Fix ✅ + +**مشکل**: صفحه تأیید برداشت‌ها در BackOffice لود نمی‌شد + +**علت**: mismatch بین نام propertyها در CMS proto و BackOffice.BFF DTO + +**فایل**: `BackOffice.BFF.Application/.../GetWithdrawalRequestsResponseDto.cs` + +**قبل**: +```csharp +public int TotalPages { get; set; } +public int TotalCount { get; set; } +``` + +**بعد**: +```csharp +public int TotalPage { get; set; } // Match CMS proto +public int TotalCount { get; set; } +``` + +**فایل**: `BackOffice.BFF.Application/.../GetWithdrawalRequestsQueryHandler.cs` + +**قبل**: +```csharp +return response.Adapt(); +``` + +**بعد**: +```csharp +return new GetWithdrawalRequestsResponseDto +{ + TotalCount = (int)response.MetaData.TotalCount, + TotalPage = (int)response.MetaData.TotalPage, + // ... explicit mapping +}; +``` + +--- + +### 10. 👤 Network Balances Enhancement ✅ + +**نیاز**: نمایش نام کامل کاربر و جزئیات breakdown پای چپ/راست در صفحه balance‌های شبکه + +#### 10.1 CMS Proto Update + +**فایل**: `CMS/Protobufs/Protos/commission.proto` + +```protobuf +message UserWeeklyBalanceModel { + // ... existing fields + string user_full_name = 13; + int64 left_leg_new_members = 14; + int64 left_leg_carryover = 15; + int64 left_leg_total = 16; + int64 right_leg_new_members = 17; + int64 right_leg_carryover = 18; + int64 right_leg_total = 19; +} +``` + +#### 10.2 CMS Handler Update + +**فایل**: `CMS.Application/.../GetUserWeeklyBalancesQueryHandler.cs` + +```csharp +var query = _dbContext.NetworkWeeklyBalances + .Include(x => x.User) // NEW: Include User + .Include(x => x.WeekDefinition) + .Where(x => x.WeekDefinitionId == request.WeekDefinitionId); + +// In projection: +UserFullName = $"{x.User.FirstName} {x.User.LastName}".Trim(), +LeftLegNewMembers = x.LeftLegNewMembers, +LeftLegCarryover = x.LeftLegCarryover, +LeftLegTotal = x.LeftLegTotal, +RightLegNewMembers = x.RightLegNewMembers, +RightLegCarryover = x.RightLegCarryover, +RightLegTotal = x.RightLegTotal, +``` + +#### 10.3 BackOffice UI Update + +**فایل**: `BackOffice/Pages/Network/BalancesReport.razor` + +```razor +@* ستون نام کاربر *@ + + +@* ستون پای چپ با Tooltip *@ + + + + @FormatNumber(context.Item.LeftLegTotal) + + + + +@* ستون پای راست با Tooltip *@ + + + + @FormatNumber(context.Item.RightLegTotal) + + + +``` + +#### 10.4 Proto Package Update + +```bash +# Publish new proto package +cd CMS/Protobufs +# Update version in .csproj to 0.0.14 +dotnet pack +dotnet nuget push ... + +# Update BackOffice +cd BackOffice/src/BackOffice +# Update package reference in .csproj + +``` + +--- + +### 11. 🔢 WeekDefinitionId Mapping Fix ✅ + +**مشکل**: `WeekDefinitionId` همیشه `0` به BFF ارسال می‌شد، حتی اگر در client مقدار صحیح ست شده بود. + +**علت**: در protobuf، فیلد `week_definition_id` از نوع `google.protobuf.Int64Value` است که یک wrapper type هست. در mapping مستقیم assign می‌شد بدون extract کردن `.Value`. + +**فایل**: `FrontOffice.BFF/src/FrontOffice.BFF.WebApi/Common/Mappings/CommissionProfile.cs` + +**Proto Definition**: +```protobuf +message GetMyWeeklyBalancesRequest { + google.protobuf.Int64Value week_definition_id = 3; +} +``` + +**قبل**: +```csharp +config.NewConfig() + .Map(dest => dest.WeekDefinitionId, src => src.WeekDefinitionId); // BUG: assigns Int64Value object, not the value +``` + +**بعد**: +```csharp +config.NewConfig() + .Map(dest => dest.WeekDefinitionId, + src => src.WeekDefinitionId != null ? src.WeekDefinitionId.Value : null); +``` + +**توضیح**: +- `Int64Value` یک wrapper class در protobuf هست برای nullable long +- وقتی مستقیم assign کنید، implicit conversion اتفاق نمیفته +- باید explicit از `.Value` استفاده کنید + +--- + ## 📦 فایل‌های تغییر یافته ### CMS @@ -278,12 +550,20 @@ config.NewConfig() | `Domain/Common/SmsTemplates.cs` | **New** - قالب‌های پیامک | | `Application/.../ProcessDayaLoanApprovalCommandHandler.cs` | Modified - اضافه شدن SMS | | `WebApi/Common/Mappings/AppVersionProfile.cs` | **New** - Mapster profile | +| `Application/.../GetAllWeeklyPoolsQueryHandler.cs` | Modified - تغییر WeekDisplayName از PersianWeekNumber به DisplayName | +| `Application/.../GetUserWeeklyBalancesQueryHandler.cs` | Modified - اضافه شدن User include و فیلدهای جدید | +| `Application/.../GetUserWeeklyBalancesResponseDto.cs` | Modified - اضافه شدن UserFullName و breakdown fields | +| `WebApi/Common/Mappings/CommissionProfile.cs` | Modified - mapping جدید برای UserWeeklyBalanceModel | +| `Protobufs/Protos/commission.proto` | Modified - اضافه شدن فیلدهای جدید به UserWeeklyBalanceModel | ### BackOffice.BFF | فایل | نوع تغییر | |------|-----------| -| `Application/Common/Mappings/CommissionProfile.cs` | Modified - اضافه شدن GetAllWeeklyPools mapping | +| `Application/Common/Mappings/CommissionProfile.cs` | Modified - اضافه شدن GetAllWeeklyPools mapping + ProcessWithdrawal mapping | | `WebApi/Common/Mappings/GeneralMapping.cs` | Modified - اضافه شدن Unit to Empty | +| `Application/.../GetWithdrawalRequestsQueryHandler.cs` | Modified - explicit mapping به جای Adapt<> | +| `Application/.../GetWithdrawalRequestsResponseDto.cs` | Modified - تطابق با CMS proto | +| `Protobufs/Protos/commission.proto` | Modified - اضافه شدن فیلدهای جدید | ### BackOffice | فایل | نوع تغییر | @@ -291,6 +571,20 @@ config.NewConfig() | `Shared/NavMenu.razor` | Modified - اضافه شدن لینک app-versions | | `Pages/Settings/AppVersions.razor` | Modified - دکمه افزودن + OpenCreateDialog | | `Pages/Settings/Components/AppVersionEditDialog.razor` | Modified - پارامتر IsNew + Select | +| `Pages/Network/BalancesReport.razor` | Modified - ستون‌های جدید با MudTooltip | +| `BackOffice.csproj` | Modified - آپدیت proto package به v0.0.14 | + +### FrontOffice.BFF +| فایل | نوع تغییر | +|------|-----------| +| `WebApi/Common/Mappings/CommissionProfile.cs` | Modified - رفع WeekDefinitionId mapping (Int64Value.Value) | +| `Application/.../GetMyWeeklyBalancesQueryHandler.cs` | Modified - simplify status handling | + +### FrontOffice +| فایل | نوع تغییر | +|------|-----------| +| `Utilities/CommissionService.cs` | Modified - اضافه شدن GetStatusColor و MapStatus (انتقال از BFF) | +| `Pages/Commission/WeeklyBalancePage.razor.cs` | Modified - استفاده از متدهای جدید CommissionService | --- @@ -308,6 +602,14 @@ dotnet build BackOffice.BFF.WebApi/BackOffice.BFF.WebApi.csproj # BackOffice dotnet build BackOffice/BackOffice.csproj # Build succeeded. 0 Error(s) + +# FrontOffice.BFF +dotnet build FrontOffice.BFF.WebApi/FrontOffice.BFF.WebApi.csproj +# Build succeeded. 0 Error(s) + +# FrontOffice +dotnet build FrontOffice.Main/FrontOffice.Main.csproj +# Build succeeded. 0 Error(s) ``` --- @@ -317,9 +619,10 @@ dotnet build BackOffice/BackOffice.csproj | متریک | مقدار | |-------|-------| | فایل‌های جدید | 2 | -| فایل‌های تغییر یافته | 8 | -| خطوط کد اضافه شده | ~300 | -| باگ‌های Mapping رفع شده | 3 | +| فایل‌های تغییر یافته | 18 | +| خطوط کد اضافه شده | ~500 | +| باگ‌های Mapping رفع شده | 5 | +| پروژه‌های تأثیرگذار | 5 (CMS, BackOffice, BackOffice.BFF, FrontOffice, FrontOffice.BFF) | --- diff --git a/QUICK-REFERENCE.md b/QUICK-REFERENCE.md index fb70f4b..1b58ca3 100644 --- a/QUICK-REFERENCE.md +++ b/QUICK-REFERENCE.md @@ -7,12 +7,18 @@ ## 🆕 آخرین تغییرات -### ۷ دی - SystemConstants + SmsTemplates + Mapping Fixes ✨ +### ۷ دی - SystemConstants + SmsTemplates + Commission System Fixes ✨ - **SystemConstants**: انتقال مقادیر hardcode (56M) به کلاس مرکزی - **SmsTemplates**: متمرکز کردن همه قالب‌های پیامک در یک فایل - **Daya Loan SMS**: ارسال پیامک خودکار هنگام تأیید وام دایا - **AppVersion UI**: صفحه مدیریت نسخه با قابلیت افزودن جدید - **Mapping Fixes**: رفع مشکلات Mapster (Unit→Empty, WeeklyPools, AppVersion) +- **Commission Status**: انتقال تبدیل Status از BFF به FrontOffice client +- **ProcessWithdrawal**: رفع خطای "PayoutId invalid" +- **WeekDisplayName**: نمایش "هفته چهلم" به جای "1404-W40" +- **Withdrawals Page**: رفع مشکل لود نشدن صفحه +- **Network Balances**: نمایش نام کاربر + Carryover breakdown با Tooltip +- **WeekDefinitionId**: رفع مشکل ارسال 0 (Int64Value.Value extraction) **📄 جزئیات**: [CHANGELOG-2025-12-27.md](CHANGELOG-2025-12-27.md) @@ -82,18 +88,21 @@ | Component | Progress | امروز | |-----------|----------|--------| -| CMS | 98% ✅ | +1% (SmsTemplates, SystemConstants) | -| BackOffice.BFF | 100% ✅ | Mapping Fixes | -| BackOffice UI | 100% ✅ | AppVersion Complete | -| FrontOffice.BFF | 60% 🚧 | - | -| FrontOffice UI | 75% 🚧 | - | +| CMS | 98% ✅ | +1% (SmsTemplates, SystemConstants, Balance Fields) | +| BackOffice.BFF | 100% ✅ | Mapping Fixes (Withdrawals, ProcessWithdrawal) | +| BackOffice UI | 100% ✅ | AppVersion Complete + BalancesReport Enhanced | +| FrontOffice.BFF | 65% 🚧 | Status simplify + WeekDefinitionId fix | +| FrontOffice UI | 78% 🚧 | CommissionService MapStatus + GetStatusColor | ### تغییرات اخیر: -- ✅ **امروز (۷ دی)**: SystemConstants + SmsTemplates + Mapping Fixes +- ✅ **امروز (۷ دی)**: SystemConstants + SmsTemplates + Commission System Fixes - ✅ CMS: `SystemConstants.cs` و `SmsTemplates.cs` اضافه شد -- ✅ CMS: `AppVersionProfile.cs` برای Mapster -- ✅ BackOffice.BFF: اصلاح CommissionProfile و GeneralMapping -- ✅ BackOffice: صفحه app-versions تکمیل شد +- ✅ CMS: `GetUserWeeklyBalancesQueryHandler` با فیلدهای جدید (UserFullName, Carryover breakdown) +- ✅ CMS: `GetAllWeeklyPoolsQueryHandler` با WeekDisplayName صحیح +- ✅ BackOffice.BFF: اصلاح CommissionProfile (ProcessWithdrawal + Withdrawals mapping) +- ✅ BackOffice: `BalancesReport.razor` با ستون‌های جدید و MudTooltip +- ✅ FrontOffice.BFF: `CommissionProfile` رفع WeekDefinitionId mapping +- ✅ FrontOffice: `CommissionService` با MapStatus و GetStatusColor ---