Compare commits

...

2 Commits

Author SHA1 Message Date
masoodafar-web 8080b75f05 fix(k8s): change imagePullPolicy to IfNotPresent in frontoffice-deployment.yaml
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 19m56s
Updated the imagePullPolicy for the frontoffice container to IfNotPresent to optimize image pulling behavior, ensuring that images are only pulled when not already present on the node.
2026-06-14 00:08:23 +03:30
masoodafar-web 34c5c508e0 feat: update package version and enhance network membership DTOs
- Updated the version of the Foursat.CMSMicroservice.Protobuf package from 0.0.197 to 0.0.199.
- Added a new property `PackageName` to `NetworkNodeDto` and `FlatNetworkNodeDto` for better representation of membership packages.
- Updated mapping in `NetworkMembershipService` to include the new `PackageName` property.
- Enhanced the org chart display by adding a badge for the package name in the UI.

These changes improve the clarity and functionality of the network membership features.
2026-06-11 23:33:40 +03:30
7 changed files with 299 additions and 4 deletions
+260
View File
@@ -0,0 +1,260 @@
# سرویس‌های FrontOffice (سمت مشتری)
این سند تمام سرویس‌هایی را که **FrontOffice** (فرانت مشتری) به **CMS** از طریق gRPC Gateway (`GW_URL`) فراخوانی می‌کند، به ترتیب **Use Case** فهرست می‌کند.
- **مسیر کد سرویس‌ها:** `FrontOffice/src/FrontOffice.Main/Utilities/`
- **ثبت gRPC:** `FrontOffice/src/FrontOffice.Main/ConfigureServices.cs`
- **تاریخ:** ۱۴۰۵/۰۳/۱۷
---
## ۱. احراز هویت و ثبت‌نام
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 1.1 | `AuthService``RefreshTokenAsync` | `UserContract.RefreshToken` | `/profile` (`Profile/Index`) | تمدید JWT پس از بازگشت از درگاه پرداخت |
| 1.2 | `AuthService``InitUserAuthInfo` / claims | — (local JWT parse) | سراسری | خواندن UserId، نام، کدملی، وضعیت قرارداد/پکیج/باشگاه از توکن |
| 1.3 | `UserContract.CreateNewOtpToken` | `UserContract` | `Shared/AuthDialog` | ارسال OTP ورود/ثبت‌نام با موبایل |
| 1.4 | `UserContract.VerifyOtpToken` | `UserContract` | `Shared/AuthDialog` | تأیید OTP و دریافت JWT |
| 1.5 | `UserContract.CreateNewOtpToken` (Purpose=`signContract`) | `UserContract` | `/register` (`RegisterWizard`) | ارسال OTP برای امضای قرارداد اصلی |
| 1.6 | `UserContract.AcceptContract` | `UserContract` | `/register` (`RegisterWizard`) | ثبت امضای قرارداد اصلی + دریافت توکن به‌روز |
| 1.7 | `UserContract.GetUserForCustomer` | `UserContract` | `/register`, `/profile`, `/profile/personal`, `/profile/settings` | بارگذاری پروفایل موجود کاربر |
| 1.8 | `UserContract.UpdateCustomerProfile` | `UserContract` | `/register`, `/profile`, `/profile/personal` | ذخیره نام، نام‌خانوادگی، کدملی و… |
| 1.9 | `AuthDialogService.ShowAuthDialogAsync` | — (UI) | فروشگاه، سبد، checkout | نمایش دیالوگ ورود برای مهمان |
| 1.10 | `GuestActionGate` | — (wrapper روی Auth) | `/`, `/products`, `/product/{id}`, Discount Store | جلوگیری از افزودن به سبد بدون لاگین |
---
## ۲. پروفایل و آدرس
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 2.1 | `UserContract.GetUserForCustomer` | `UserContract` | `/profile`, `/profile/personal`, `/profile/settings` | نمایش و ویرایش اطلاعات شخصی |
| 2.2 | `UserContract.GetUser` | `UserContract` | `/profile/hub`, `Club/ActivationSection` | اطلاعات کامل کاربر (هاب پروفایل / پس از فعال‌سازی باشگاه) |
| 2.3 | `UserContract.UpdateUser` | `UserContract` | `/profile/settings` | به‌روزرسانی تنظیمات حساب |
| 2.4 | `UserAddressContract.GetCustomerAddresses` | `UserAddressContract` | `/profile`, `/profile/addresses`, `/checkout`, Store/Discount checkout | لیست آدرس‌های تحویل |
| 2.5 | `UserAddressContract.CreateCustomerAddress` | `UserAddressContract` | `Profile/Components/AddAddressDialog` | ثبت آدرس جدید |
| 2.6 | `UserAddressContract.UpdateCustomerAddress` | `UserAddressContract` | `Profile/Components/EditAddressDialog` | ویرایش آدرس |
| 2.7 | `UserAddressContract.DeleteCustomerAddress` / `DeleteUserAddress` | `UserAddressContract` | `/profile/addresses`, `/profile` | حذف آدرس |
| 2.8 | `UserAddressContract.SetCustomerDefaultAddress` / `SetAddressAsDefault` | `UserAddressContract` | `/profile/addresses`, `/profile`, `/checkout` | تنظیم آدرس پیش‌فرض |
| 2.9 | `CityContract.GetAllCitiesByFilter` | `CityContract` | `AddAddressDialog`, `EditAddressDialog` | جستجو و انتخاب شهر/استان |
---
## ۳. پکیج و خرید عضویت
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 3.1 | `PackageService.GetAllPackagesAsync` | `PackageContract.GetCustomerPackages` | `/packages`, `/my-packages`, `/`, `/checkout`, `PackagePurchaseDialog`, `ClubMembershipContractDialog`, Commission pages | لیست پکیج‌های قابل خرید |
| 3.2 | `PackageService.GetPackageByIdAsync` | `PackageContract.GetCustomerPackageDetails` | (از طریق wrapper؛ صفحه جزئیات مستقیم RPC دارد) | جزئیات یک پکیج |
| 3.3 | `PackageContract.GetCustomerPackageDetails` | `PackageContract` | `/package/{id}` (`PackageDetail`) | جزئیات، ویژگی‌ها و مشخصات پکیج |
| 3.4 | `PackageService.GetUserPackageStatusAsync` | `PackageContract.GetUserPackageStatus` | `/packages`, `/my-packages`, `/profile` | وضعیت خرید پکیج، باشگاه، موجودی کیف پول |
| 3.5 | `PackageContract.CustomerPurchasePackage` | `PackageContract` | `/profile` (`ProcessDirectPayment`), `/checkout` | شروع پرداخت درگاهی (Zarinpal) برای خرید پکیج |
| 3.6 | `PackageContract.CustomerVerifyPackagePurchase` | `PackageContract` | `/profile/payment-callback?type=package` | تأیید پرداخت پکیج پس از بازگشت از درگاه |
| 3.7 | `PackagePurchaseDialog` | — (UI + `PackageService`) | `/profile`, `/my-packages` | انتخاب پکیج و روش پرداخت (درگاه / Daya) |
| 3.8 | Daya Loan (external URL) | — | `/profile` | هدایت به `dayadiamond.ir` برای خرید اقساطی (بدون RPC) |
---
## ۴. کیف پول، شارژ و برداشت
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 4.1 | `WalletService.GetBalancesAsync` | `UserWalletContract.GetCustomerWallet` | `/profile`, `/profile/wallet`, Store checkout, PaymentCallback | موجودی اصلی، تخفیفی و شبکه |
| 4.2 | `WalletService.GetTransactionsAsync` | `UserWalletContract.GetCustomerWalletHistory` | `/profile/wallet` | تاریخچه تراکنش‌های کیف پول |
| 4.3 | `WalletService.GetMagicWalletStatusAsync` | `UserWalletContract.GetMagicWalletStatus` | `/profile`, `/profile/magic-wallet`, `/my-packages` | وضعیت کیف پول جادویی (Magic) |
| 4.4 | `WalletService.InitiateMagicChargeAsync` | `UserWalletContract.InitiateMagicCharge` | `/profile/magic-wallet` | شروع شارژ کیف پول جادویی → درگاه |
| 4.5 | `WalletService.VerifyMagicChargeAsync` | `UserWalletContract.VerifyMagicCharge` | `/profile/payment-callback?type=magic-wallet` | تأیید شارژ Magic پس از درگاه |
| 4.6 | `WalletService.InitiateDiscountChargeAsync` | `UserWalletContract.InitiateDiscountCharge` | `/profile/charge-discount-wallet` | شروع شارژ کیف پول تخفیفی → درگاه |
| 4.7 | `WalletService.VerifyDiscountChargeAsync` | `UserWalletContract.VerifyDiscountCharge` | `/profile/payment-callback?type=discount-wallet` | تأیید شارژ کیف تخفیفی |
| 4.8 | `WalletService.GetWithdrawalsAsync` | `UserWalletContract.GetCustomerWithdrawals` | `/profile/withdrawal-requests` | لیست درخواست‌های برداشت |
| 4.9 | `WalletService.GetWithdrawalSettingsAsync` | `UserWalletContract.GetCustomerWithdrawalSettings` | `/profile/withdrawal-requests` | حداقل مبلغ برداشت |
| 4.10 | `WalletService.RequestWithdrawalAsync` | `UserWalletContract.CustomerWithdrawBalance` | `/profile/withdrawal-requests` | ثبت درخواست برداشت پاداش (با payoutId کمیسیون) |
| 4.11 | `CommissionService.GetWithdrawablePayoutsAsync` | `CommissionContract.GetMyCommissionPayouts` | `/profile/withdrawal-requests` | پاداش‌های قابل برداشت برای انتخاب |
---
## ۵. Callback پرداخت (مشترک)
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 5.1 | `PackageContract.CustomerVerifyPackagePurchase` | `PackageContract` | `/profile/payment-callback` (type=package) | تأیید خرید پکیج |
| 5.2 | `WalletService.VerifyMagicChargeAsync` | `UserWalletContract` | `/profile/payment-callback` (type=magic-wallet) | تأیید شارژ Magic |
| 5.3 | `WalletService.VerifyDiscountChargeAsync` | `UserWalletContract` | `/profile/payment-callback` (type=discount-wallet) | تأیید شارژ تخفیفی |
| 5.4 | `DiscountOrderService.VerifyDiscountOrderPaymentAsync` | `DiscountOrderContract.CustomerVerifyDiscountOrderPayment` | `/profile/payment-callback` (type=discount-order) | تأیید پرداخت سفارش فروشگاه تخفیفی |
| 5.5 | `UserContract.GetUserForCustomer` + `AuthService.InitUserAuthInfo` | `UserContract` | `/profile/payment-callback` | به‌روزرسانی claims کاربر پس از پرداخت موفق |
---
## ۶. فروشگاه اصلی (Store)
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 6.1 | `ProductService.GetProductsPagedAsync` | `ProductsContract.GetProductsForCustomer` | `/products` | لیست محصولات با فیلتر/صفحه‌بندی |
| 6.2 | `ProductService.GetTopSellingAsync` | `ProductsContract` | `/` (صفحه اصلی) | پرفروش‌ترین محصولات |
| 6.3 | `ProductService.GetByIdAsync` | `ProductsContract.GetProductByIdForCustomer` | `/product/{id}` | جزئیات محصول + گالری |
| 6.4 | `CategoryService.GetAllAsync` / `GetByIdAsync` | `CategoryContract.GetAllCategoriesForCustomer` | `/categories`, `/products` | درخت دسته‌بندی محصولات |
| 6.5 | `CartService` — Add/Update/Remove/Get | `UserCartsContract.*ForCustomer` | `/`, `/products`, `/product/{id}`, `/cart` | مدیریت سبد خرید (AddNew, Update, Remove, GetCustomerCart) |
| 6.6 | `UserOrderContract.SubmitShopBuyOrder` | `UserOrderContract` | `/checkout-summary` | ثبت سفارش و پرداخت از کیف پول |
| 6.7 | `OrderService.GetOrdersAsync` | `UserOrderContract.GetCustomerOrders` | `/orders` | لیست سفارش‌های کاربر |
| 6.8 | `OrderService.GetOrderAsync` | `UserOrderContract.GetCustomerOrder` | `/order/{id}`, `/order-tracking/{id}` | جزئیات یک سفارش |
| 6.9 | `OrderService.CalculateOrderPVAsync` | `UserOrderContract.CalculateOrderPV` | `/order/{id}` | محاسبه PV سفارش |
| 6.10 | `VATService.GetRateAsync` | `UserOrderContract` (via scope) | Store/Discount صفحات قیمت | نرخ مالیات بر ارزش افزوده (کش روزانه) |
| 6.11 | `WalletService.GetBalancesAsync` | `UserWalletContract` | `/checkout-summary` | بررسی موجودی برای پرداخت سفارش |
---
## ۷. فروشگاه تخفیفی (Discount Store)
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 7.1 | `DiscountProductService.GetProductsAsync` | `DiscountProductContract.GetDiscountProducts` | `/discount-store` | لیست محصولات تخفیفی |
| 7.2 | `DiscountProductService.GetTopSellingAsync` | `DiscountProductContract` | `/` | پرفروش‌های فروشگاه تخفیفی |
| 7.3 | `DiscountProductService.GetByIdAsync` | `DiscountProductContract.GetDiscountProductById` + Images | `/discount-store/product/{id}` | جزئیات محصول تخفیفی |
| 7.4 | `DiscountProductService.GetCategoriesAsync` | `DiscountCategoryContract.GetDiscountCategories` | `/discount-store` | دسته‌بندی‌های فروشگاه تخفیفی |
| 7.5 | `DiscountCartService` — Add/Update/Remove/Get | `DiscountShoppingCartContract.*` | `/discount-store`, `/discount-store/cart` | سبد خرید تخفیفی |
| 7.6 | `DiscountOrderService.PlaceOrderAsync` | `DiscountOrderContract.PlaceOrder` | `/discount-store/checkout` | ثبت سفارش (کیف تخفیفی + درگاه) |
| 7.7 | `DiscountOrderService.GetUserOrdersAsync` | `DiscountOrderContract.GetUserOrders` | `/discount-store/orders` | لیست سفارش‌های تخفیفی |
| 7.8 | `DiscountOrderService.GetOrderByIdAsync` | `DiscountOrderContract.GetOrderById` | `/discount-store/order/{id}` | جزئیات سفارش تخفیفی |
| 7.9 | `UserAddressContract.GetCustomerAddresses` | `UserAddressContract` | `/discount-store/checkout` | انتخاب آدرس تحویل |
---
## ۸. باشگاه مشتریان (Club)
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 8.1 | `ClubMembershipService.GetMyMembershipAsync` | `ClubMembershipContract.GetClubMembership` | `/club/membership` | وضعیت عضویت باشگاه |
| 8.2 | `ClubConfigurationService.GetClubConfigurationAsync` | `ConfigurationContract.GetClubConfiguration` | `/club/membership` | هزینه فعال‌سازی و هدیه عضویت |
| 8.3 | `ClubConfigurationService.GetClubFeaturesAsync` | `ConfigurationContract.GetClubFeatures` | `/club/features` | لیست امکانات باشگاه |
| 8.4 | `ClubMembershipService.ActivateMembershipAsync` | `ClubMembershipContract.ActivateClubMembership` | `Club/ActivationSection` | فعال‌سازی/تمدید عضویت باشگاه |
| 8.5 | `OtpTokenContract.CreateNewOtpToken` | `OtpTokenContract` | `ClubMembershipContractDialog` | OTP برای امضای قرارداد باشگاه |
| 8.6 | `ClubMembershipContract.AcceptClubMembershipContract` | `ClubMembershipContract` | `ClubMembershipContractDialog` | ثبت امضای قرارداد باشگاه |
---
## ۹. شبکه فروش (Network / MLM)
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 9.1 | `NetworkMembershipService.GetMyNetworkTreeAsync` | `NetworkMembershipContract.GetMyNetworkTree` | `/profile/tree` (`OrganizationChart`) | درخت سازمان فروش کاربر |
| 9.2 | `NetworkMembershipService.GetSubordinateTreeAsync` | `NetworkMembershipContract.GetSubordinateTree` | `/profile/tree` | drill-down به زیرمجموعه |
| 9.3 | `NetworkMembershipService.GetMyNetworkStatisticsAsync` | `NetworkMembershipContract.GetMyNetworkStatistics` | `/profile/tree`, `/network/statistics` | آمار پا چپ/راست، تعداد اعضا |
---
## ۱۰. کمیسیون و پاداش
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 10.1 | `CommissionService.GetWeekDefinitionsAsync` | `CommissionContract.GetWeekDefinitions` | `Shared/WeekSelector`, Commission pages | لیست هفته‌های محاسبه پاداش |
| 10.2 | `CommissionService.GetMyCommissionPayoutsAsync` | `CommissionContract.GetMyCommissionPayouts` | `/commission/dashboard` | تاریخچه پرداخت پاداش‌ها |
| 10.3 | `CommissionService.GetMyWeeklyBalanceAsync` | `CommissionContract.GetMyWeeklyBalances` | `/commission/weekly-balance` | جزئیات بالانس هفتگی (چپ/راست) |
| 10.4 | `PackageService.GetAllPackagesAsync` | `PackageContract` | Commission pages | فیلتر پاداش بر اساس پکیج |
---
## ۱۱. محتوای سایت، بلاگ و صفحات ثابت
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 11.1 | `SitePageSettingsService.GetPageAsync` | `SitePageSettingsContract.GetPageSettings` | `/` (landing), `/about`, `/contact`, `/licenses` | محتوای داینامیک صفحات (hero، تصاویر، JSON تنظیمات) |
| 11.2 | `BlogPostService.GetFeaturedPostsAsync` | `BlogPostContract.GetFeaturedBlogPosts` | `/`, `/profile` | پست‌های ویژه |
| 11.3 | `BlogPostService.GetPublishedPostsAsync` | `BlogPostContract.GetPublishedBlogPosts` | `/`, `/blog` | لیست پست‌های منتشرشده |
| 11.4 | `BlogPostService.GetBySlugAsync` | `BlogPostContract.GetBlogPostBySlug` | `/blog/{slug}` | محتوای کامل یک پست |
| 11.5 | `BlogPostService.IncrementViewCountAsync` | `BlogPostContract.IncrementViewCount` | `/blog/{slug}` | افزایش شمارنده بازدید |
| 11.6 | `BlogCategoryService.GetActiveCategoriesAsync` | `BlogCategoryContract` | `/blog` | فیلتر دسته‌بندی بلاگ |
| 11.7 | FAQ | — (hardcoded) | `/faq` | سوالات متداول — **بدون فراخوانی API** |
---
## ۱۲. زیرساخت مشترک (Infrastructure)
| # | سرویس / متد | gRPC Contract | صفحه / کامپوننت | کاربرد |
|---|-------------|---------------|-----------------|--------|
| 12.1 | `ImageCacheService.ResolveAsync` | `ImageResolverContract` | `Shared/AppImage` (سراسری) | resolve مسیر تصویر CMS به data-URI |
| 12.2 | `AppVersionService.CheckVersionAsync` | `AppVersionContract` | `App.razor`, `MainLayout` | بررسی نسخه جدید اپ |
| 12.3 | `AppVersionService.ApplyUpdateAsync` / `SkipVersionAsync` | — (localStorage + reload) | `App.razor`, `MainLayout` | اعمال یا رد آپدیت |
| 12.4 | `MainService.OnChangeHandler` | — (in-memory) | `/`, `AuthDialog` | اطلاع‌رسانی تغییر state سراسری (مثلاً پس از login) |
| 12.5 | `IChromiumPdfService` | — (local endpoint `/contract/generate`) | `/register` | تولید PDF قرارداد (Chromium headless) |
---
## ۱۳. Gateway / انتخاب‌گر
| صفحه | سرویس | کاربرد |
|------|--------|--------|
| `/stores` | — | انتخاب بین فروشگاه اصلی و تخفیفی |
| `/my-orders` | — | انتخاب لیست سفارش‌ها |
| `/my-cart` | — | انتخاب سبد خرید |
این صفحات فقط مسیریابی UI هستند و مستقیماً gRPC صدا نمی‌زنند.
---
## ۱۴. سرویس‌های ثبت‌شده ولی بدون استفاده در UI
| سرویس / Contract | وضعیت |
|------------------|--------|
| `SitePageService` (`SitePageContract`) | ثبت در DI؛ **هیچ صفحه‌ای inject نمی‌کند** (جایگزین: `SitePageSettingsService`) |
| `TransactionsContract` | ثبت در DI؛ **استفاده نشده** |
| `UserWalletHistoryContract` | ثبت در DI؛ **استفاده نشده** (تاریخچه از `UserWalletContract.GetCustomerWalletHistory` می‌آید) |
| `TokenNotificationService` | ثبت در DI؛ **هنوز به Layout وصل نشده** (SignalR برای invalidation توکن) |
---
## نمودار جریان پرداخت
```mermaid
flowchart LR
subgraph initiate [شروع پرداخت]
A1[Profile / Checkout]
A2[MagicWallet / ChargeDiscount]
A3[Discount Checkout]
end
subgraph gateway [Zarinpal]
G[درگاه پرداخت]
end
subgraph callback [PaymentCallback]
C1[Verify Package]
C2[Verify Magic]
C3[Verify Discount Wallet]
C4[Verify Discount Order]
end
A1 --> G
A2 --> G
A3 --> G
G --> callback
```
---
## فهرست gRPC Contractهای فعال
| Contract | Wrapper اصلی |
|----------|----------------|
| `UserContract` | `AuthService`, صفحات Profile/Register |
| `UserAddressContract` | Profile, Checkout pages |
| `CityContract` | Address dialogs |
| `PackageContract` | `PackageService`, PaymentCallback, Checkout |
| `UserWalletContract` | `WalletService` |
| `UserOrderContract` | `OrderService`, CheckoutSummary |
| `UserCartsContract` | `CartService` |
| `ProductsContract` | `ProductService` |
| `CategoryContract` | `CategoryService` |
| `DiscountProductContract` / `DiscountCategoryContract` | `DiscountProductService` |
| `DiscountShoppingCartContract` | `DiscountCartService` |
| `DiscountOrderContract` | `DiscountOrderService` |
| `ClubMembershipContract` | `ClubMembershipService`, Dialog |
| `OtpTokenContract` | Club contract dialog |
| `ConfigurationContract` | `ClubConfigurationService` |
| `NetworkMembershipContract` | `NetworkMembershipService` |
| `CommissionContract` | `CommissionService` |
| `BlogPostContract` | `BlogPostService` |
| `BlogCategoryContract` | `BlogCategoryService` |
| `SitePageSettingsContract` | `SitePageSettingsService` |
| `AppVersionContract` | `AppVersionService` |
| `ImageResolverContract` | `ImageCacheService` |
+1 -1
View File
@@ -21,7 +21,7 @@ spec:
containers: containers:
- name: frontoffice - name: frontoffice
image: 194.5.195.53:30080/admin/frontoffice:latest image: 194.5.195.53:30080/admin/frontoffice:latest
imagePullPolicy: Always imagePullPolicy: IfNotPresent
ports: ports:
- containerPort: 80 - containerPort: 80
name: http name: http
+1 -1
View File
@@ -11,7 +11,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="DateTimeConverterCL" Version="1.0.0" /> <PackageReference Include="DateTimeConverterCL" Version="1.0.0" />
<!-- Replace all FrontOffice.BFF protobuf packages with CMS protobuf --> <!-- Replace all FrontOffice.BFF protobuf packages with CMS protobuf -->
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.197" /> <PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.199" />
<!-- <ProjectReference Include="../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj" />--> <!-- <ProjectReference Include="../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj" />-->
<PackageReference Include="MudBlazor" Version="8.14.0" /> <PackageReference Include="MudBlazor" Version="8.14.0" />
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" /> <PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
@@ -21,6 +21,11 @@ public class NetworkNodeDto
/// کد معرف کاربر /// کد معرف کاربر
/// </summary> /// </summary>
public string? ReferralCode { get; set; } public string? ReferralCode { get; set; }
/// <summary>
/// نام پکیج موثر (مثلاً پکیج طلایی / نقره‌ای)
/// </summary>
public string? PackageName { get; set; }
} }
/// <summary> /// <summary>
@@ -43,6 +48,11 @@ public class FlatNetworkNodeDto
/// کد معرف کاربر - فقط برای کاربران فعال در باشگاه نمایش داده شود /// کد معرف کاربر - فقط برای کاربران فعال در باشگاه نمایش داده شود
/// </summary> /// </summary>
public string? ReferralCode { get; set; } public string? ReferralCode { get; set; }
/// <summary>
/// نام پکیج موثر (مثلاً پکیج طلایی / نقره‌ای)
/// </summary>
public string? PackageName { get; set; }
} }
/// <summary> /// <summary>
@@ -81,7 +91,8 @@ public class NetworkTreeDto
IsClubActive = node.IsClubActive, IsClubActive = node.IsClubActive,
ActivationWeekNumber = node.ActivationWeekNumber, ActivationWeekNumber = node.ActivationWeekNumber,
JoinedAt = node.JoinedAt, JoinedAt = node.JoinedAt,
ReferralCode = node.ReferralCode ReferralCode = node.ReferralCode,
PackageName = node.PackageName
}; };
result.Add(flatNode); result.Add(flatNode);
@@ -137,6 +137,7 @@ public class NetworkMembershipService
IsActive = node.IsActive, IsActive = node.IsActive,
IsClubActive = node.IsClubActive, IsClubActive = node.IsClubActive,
ReferralCode = node.ReferralCode, ReferralCode = node.ReferralCode,
PackageName = string.IsNullOrWhiteSpace(node.PackageName) ? null : node.PackageName,
ActivationWeekNumber = node.ActivationWeekDefinitionId?.ToString(), ActivationWeekNumber = node.ActivationWeekDefinitionId?.ToString(),
JoinedAt = node.JoinedAt?.ToDateTime(), JoinedAt = node.JoinedAt?.ToDateTime(),
LeftChild = MapNodeFromProto(node.LeftChild), LeftChild = MapNodeFromProto(node.LeftChild),
@@ -124,6 +124,23 @@
margin-top: 1px; margin-top: 1px;
} }
.org-node-card .package-name-badge {
display: inline-flex;
align-items: center;
height: 14px;
padding: 0 6px;
margin-top: 2px;
border-radius: 7px;
font-size: 9px;
color: #546e7a;
background: #eceff1;
border: 1px solid #b0bec5;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 120px;
}
/* Referral Code - only for club active members */ /* Referral Code - only for club active members */
.node-referral { .node-referral {
display: flex; display: flex;
+7 -1
View File
@@ -38,7 +38,7 @@ window.OrgChart = {
.container('#' + containerId) .container('#' + containerId)
.data(data) .data(data)
.nodeWidth((d) => 140) .nodeWidth((d) => 140)
.nodeHeight((d) => 70) .nodeHeight((d) => 85)
.childrenMargin((d) => 50) .childrenMargin((d) => 50)
.compactMarginBetween((d) => 15) .compactMarginBetween((d) => 15)
.compactMarginPair((d) => 15) .compactMarginPair((d) => 15)
@@ -67,6 +67,11 @@ window.OrgChart = {
// Avatar - first letter of name // Avatar - first letter of name
const firstChar = data.fullName ? data.fullName.charAt(0) : '?'; const firstChar = data.fullName ? data.fullName.charAt(0) : '?';
const packageName = data.packageName || data.PackageName || '';
const packageBadge = packageName
? `<div class="package-name-badge">${packageName}</div>`
: '';
// نمایش کد معرف فقط برای کاربران فعال در باشگاه // نمایش کد معرف فقط برای کاربران فعال در باشگاه
const referralCodeHtml = data.isClubActive && data.referralCode const referralCodeHtml = data.isClubActive && data.referralCode
? `<div class="node-referral" onclick="event.stopPropagation(); OrgChart.copyReferralCode('${data.referralCode}');" title="کپی کد معرف"> ? `<div class="node-referral" onclick="event.stopPropagation(); OrgChart.copyReferralCode('${data.referralCode}');" title="کپی کد معرف">
@@ -82,6 +87,7 @@ window.OrgChart = {
<div class="node-info"> <div class="node-info">
<div class="node-name-sm">${data.fullName || 'بدون نام'}</div> <div class="node-name-sm">${data.fullName || 'بدون نام'}</div>
<div class="node-level-sm">L${data.level || 0}${!isRoot ? ' • ' + (data.position === 'Left' ? 'چپ' : 'راست') : ''}</div> <div class="node-level-sm">L${data.level || 0}${!isRoot ? ' • ' + (data.position === 'Left' ? 'چپ' : 'راست') : ''}</div>
${packageBadge}
${referralCodeHtml} ${referralCodeHtml}
</div> </div>
</div> </div>