# Session Log - December 20, 2025 ## خلاصه Session این session شامل رفع چندین باگ در صفحات BackOffice و فعال‌سازی قابلیت‌های Products بود. --- ## 1. فیکس صفحه `/network/balances` ### مشکل ``` ValidationException هنگام لود صفحه بالانس‌های هفتگی ``` ### علت Mapster mapping برای تبدیل `GetUserWeeklyBalancesRequest` به `GetUserWeeklyBalancesQuery` وجود نداشت. ### راه‌حل اضافه کردن mapping در `CommissionProfile.cs`: ```csharp // File: BackOffice.BFF/src/BackOffice.BFF.WebApi/Common/Mappings/CommissionProfile.cs config.NewConfig() .Map(dest => dest.PaginationState, src => src.PaginationState); ``` --- ## 2. فیکس صفحه `/club/members` ### مشکل ``` صفحه لود می‌شد ولی هیچ داده‌ای نمایش نمی‌داد ``` ### علت Mapster mappings در CMS و BFF برای `GetAllClubMemberships` وجود نداشتند. ### راه‌حل ایجاد `ClubMembershipProfile.cs` در هر دو لایه: **CMS/src/CMSMicroservice.WebApi/Common/Mappings/ClubMembershipProfile.cs** (NEW): ```csharp public class ClubMembershipProfile : IRegister { void IRegister.Register(TypeAdapterConfig config) { // GetAllClubMemberships mappings config.NewConfig() .Map(dest => dest.PaginationState, src => src.PaginationState) .Map(dest => dest.Filter, src => src.Filter); config.NewConfig() .MapWith(src => new GetAllClubMembershipsResponse { MetaData = src.MetaData != null ? new CMSMicroservice.Protobuf.Common.MetaData { PageIndex = src.MetaData.PageIndex, TotalPages = src.MetaData.TotalPages, TotalCount = src.MetaData.TotalCount } : null, Models = { src.Models?.Select(...) ?? Enumerable.Empty<...>() } }); } } ``` **BackOffice.BFF/src/BackOffice.BFF.WebApi/Common/Mappings/ClubMembershipProfile.cs** (REWRITTEN): - Mapping از BFF Proto به Query - Mapping از CMS Response به BFF Proto Response - استفاده از alias imports برای disambiguation --- ## 3. فیکس صفحه `/club/statistics` ### مشکل ``` Status(StatusCode="Unimplemented", Detail="Method cms.ClubMembershipContract/GetClubStatistics is unimplemented") ``` ### علت متد `GetClubStatistics` در BFF Service override نشده بود. ### راه‌حل **1. اضافه کردن override در ClubMembershipService.cs:** ```csharp public override async Task GetClubStatistics( GetClubStatisticsRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } ``` **2. اضافه کردن mappings در CMS ClubMembershipProfile:** ```csharp config.NewConfig(); config.NewConfig() .MapWith(src => new GetClubStatisticsResponse { TotalMembers = src.TotalMembers, ActiveMembers = src.ActiveMembers, // ... سایر فیلدها PackageDistribution = { src.PackageDistribution?.Select(...) }, MonthlyTrend = { src.MonthlyTrend?.Select(...) } }); ``` **3. اضافه کردن mappings در BFF ClubMembershipProfile:** - Mapping از BFF Proto به Query - Mapping از CMS Response DTO به BFF Proto Response --- ## 4. فعال‌سازی قابلیت‌های Products ### مشکل ``` همه دکمه‌های صفحه محصولات "در حال توسعه" نشان می‌دادند ``` ### علت کدهای دیالوگ‌ها comment شده بودند با TODO markers. ### راه‌حل Uncomment کردن کدها در `ProductsMainPage.razor.cs`: **فایل: BackOffice/src/BackOffice/Pages/Products/ProductsMainPage.razor.cs** ```csharp // ✅ CreateNew() - فعال شد public async Task CreateNew() { var dialog = await DialogService.ShowAsync("افزودن محصول", new DialogParameters { { x => x.Model, new CreateNewProductsRequest() } }, new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small }); // ... } // ✅ Update() - فعال شد public async Task Update(DataModel model) { var parameters = new DialogParameters { { x => x.Model, model.Adapt() } }; var dialog = await DialogService.ShowAsync("ویرایش محصول", parameters, ...); // ... } // ✅ OpenGallery() - فعال شد public async Task OpenGallery(DataModel model) { var parameters = new DialogParameters { { x => x.ProductId, model.Id }, { x => x.ProductTitle, model.Title } }; await DialogService.ShowAsync("گالری تصاویر", parameters, ...); } // ✅ OpenTagAssignment() - فعال شد public async Task OpenTagAssignment(DataModel model) { var parameters = new DialogParameters { { x => x.ProductId, model.Id }, { x => x.ProductTitle, model.Title } }; await DialogService.ShowAsync("مدیریت تگ‌های محصول", parameters, ...); } ``` **Using statement uncomment شد:** ```csharp using BackOffice.Pages.Tag.Components; // برای AssignTagsDialog ``` --- ## 5. اضافه کردن فیلد "تعداد موجودی" به Products ### نیاز نمایش و ویرایش تعداد موجودی محصول در فرم‌ها و لیست ### تغییرات **1. فرم‌های دیالوگ (CreateDialog.razor & UpdateDialog.razor):** ```razor ``` **2. ستون جدید در لیست (ProductsMainPage.razor):** ```razor @if (context.Item.RemainingCount <= 0) { ناموجود } else if (context.Item.RemainingCount < 10) { @context.Item.RemainingCount } else { @context.Item.RemainingCount } ``` **3. اضافه کردن فیلد به BFF Commands (فیکس مهم!):** مشکل: فیلد `RemainingCount` در BFF Application Commands نبود و باعث می‌شد مقدار ارسال/دریافت نشه. **CreateNewProductsCommand.cs:** ```csharp public int Discount { get; init; } public int Rate { get; init; } public int RemainingCount { get; init; } // ← اضافه شد public ImageFileModel ImageFile { get; init; } ``` **UpdateProductsCommand.cs:** ```csharp public int Discount { get; init; } public int Rate { get; init; } public int RemainingCount { get; init; } // ← اضافه شد public string ImagePath { get; init; } ``` --- ## لیست کامل فایل‌های تغییر یافته ### BackOffice.BFF | فایل | نوع تغییر | توضیح | |------|----------|-------| | `WebApi/Common/Mappings/CommissionProfile.cs` | MODIFIED | اضافه شدن mapping برای GetUserWeeklyBalances | | `WebApi/Common/Mappings/ClubMembershipProfile.cs` | REWRITTEN | Mappings کامل برای ClubMembership | | `WebApi/Services/ClubMembershipService.cs` | MODIFIED | اضافه شدن GetClubStatistics override | | `Application/ProductsCQ/Commands/CreateNewProducts/CreateNewProductsCommand.cs` | MODIFIED | اضافه شدن RemainingCount | | `Application/ProductsCQ/Commands/UpdateProducts/UpdateProductsCommand.cs` | MODIFIED | اضافه شدن RemainingCount | ### CMS | فایل | نوع تغییر | توضیح | |------|----------|-------| | `WebApi/Common/Mappings/ClubMembershipProfile.cs` | NEW | Mappings برای ClubMembership | ### BackOffice UI | فایل | نوع تغییر | توضیح | |------|----------|-------| | `Pages/Products/ProductsMainPage.razor.cs` | MODIFIED | فعال‌سازی CreateNew, Update, OpenGallery, OpenTagAssignment | | `Pages/Products/ProductsMainPage.razor` | MODIFIED | اضافه شدن ستون موجودی | | `Pages/Products/Components/CreateDialog.razor` | MODIFIED | اضافه شدن فیلد موجودی | | `Pages/Products/Components/UpdateDialog.razor` | MODIFIED | اضافه شدن فیلد موجودی | --- ## نکات فنی مهم ### 1. Mapster با Proto Types برای proto types که immutable هستند، باید از `MapWith` استفاده کرد: ```csharp config.NewConfig() .MapWith(src => new ProtoResponse { Field1 = src.Field1, RepeatedField = { src.List?.Select(...) ?? Enumerable.Empty<...>() } }); ``` ### 2. Alias Imports برای Proto Disambiguation وقتی دو proto با اسم یکسان داریم: ```csharp using BffProtos = BackOffice.BFF.ClubMembership.Protobuf.Protos.ClubMembership; using CmsProtos = CMSMicroservice.Protobuf.Protos.ClubMembership; ``` ### 3. Null-Safe MetaData Mapping ```csharp MetaData = src.MetaData != null ? new MetaData { PageIndex = src.MetaData.PageIndex, TotalPages = src.MetaData.TotalPages, TotalCount = src.MetaData.TotalCount } : null ``` --- ## Build Status پایان Session ``` BackOffice.BFF: ✅ Build succeeded (0 errors) CMS: ✅ Build succeeded (0 errors) BackOffice UI: ✅ Build succeeded (0 errors) ```