docs: convert all ASCII charts to Mermaid diagrams
Converted 40+ ASCII art diagrams across 12 files to Mermaid: - flowchart TD/LR for process flows and architecture - erDiagram for entity relationships - graph TD for tree structures (binary tree, categories) - gantt for roadmap sprints Files: BUSINESS-01 to 05, TECH-01/03/04/05, OVERVIEW-01/02/05 Directory tree structures kept as plain code blocks (Mermaid N/A)
This commit is contained in:
@@ -18,15 +18,19 @@
|
||||
|
||||
## ۲. ساختار درخت باینری
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
ROOT["Root"] --- L["Left"]
|
||||
ROOT --- R["Right"]
|
||||
L --- L1["L1"] & L2["L2"]
|
||||
R --- R1["R1"] & R2["R2"]
|
||||
L1 --- L1a["..."] & L1b["..."]
|
||||
L2 --- L2a["..."] & L2b["..."]
|
||||
R1 --- R1a["..."] & R1b["..."]
|
||||
R2 --- R2a["..."] & R2b["..."]
|
||||
```
|
||||
Root
|
||||
/ \
|
||||
Left Right
|
||||
/ \ / \
|
||||
L1 L2 R1 R2
|
||||
/ \ / \ / \ / \
|
||||
... ... ... ... ... ← بدون محدودیت عمق
|
||||
```
|
||||
|
||||
> ← بدون محدودیت عمق
|
||||
|
||||
**قوانین:**
|
||||
- هر نود حداکثر ۲ فرزند (Binary) — `MaxDirectChildrenPerLeg = 1`
|
||||
@@ -38,36 +42,24 @@
|
||||
|
||||
## ۳. فلوی عضویت و فعالسازی
|
||||
|
||||
```
|
||||
خرید پکیج طلایی (56M تومان)
|
||||
│
|
||||
▼
|
||||
نمایش مودال قرارداد (غیرقابلبستهشدن)
|
||||
│
|
||||
▼
|
||||
مشاهده متن قرارداد ← ReadContract RPC
|
||||
│
|
||||
▼
|
||||
درخواست OTP ← RequestContractOtp (Kavenegar SMS)
|
||||
│
|
||||
▼
|
||||
وارد کردن کد ← VerifyContractOtp
|
||||
│
|
||||
▼
|
||||
امضای قرارداد ← AcceptContract
|
||||
│
|
||||
├─→ شارژ ۲ کیف پول: Balance += 56M, DiscountBalance += 112M (2×)
|
||||
│ (NetworkBalance شارژ نمیشود — فقط برای کمیسیون)
|
||||
├─→ کسر هزینه فعالسازی (25.2M از Balance)
|
||||
├─→ واریز 25.2M به Pool هفتگی (ClubActivationFee)
|
||||
├─→ قرارگیری در درخت باینری
|
||||
└─→ رفرش JWT Token (claims جدید)
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["خرید پکیج طلایی — 56M"] --> B["نمایش مودال قرارداد\nغیرقابلبستهشدن"]
|
||||
B --> C["مشاهده متن قرارداد\nReadContract RPC"]
|
||||
C --> D["درخواست OTP\nRequestContractOtp — Kavenegar"]
|
||||
D --> E["وارد کردن کد\nVerifyContractOtp"]
|
||||
E --> F["امضای قرارداد\nAcceptContract"]
|
||||
|
||||
⚠️ در خرید با وام دایا:
|
||||
├─→ Balance += 56M
|
||||
└─→ DiscountBalance += 112M (دو برابر — DayaLoanAmount × 2)
|
||||
F --> G["شارژ ۲ کیفپول\nBalance += 56M\nDiscountBalance += 112M"]
|
||||
F --> H["کسر فعالسازی\n−25.2M از Balance"]
|
||||
F --> I["واریز 25.2M\nبه Pool هفتگی"]
|
||||
F --> J["قرارگیری در\nدرخت باینری"]
|
||||
F --> K["رفرش JWT Token\nclaims جدید"]
|
||||
```
|
||||
|
||||
> ⚠️ در خرید با وام دایا: Balance += 56M, DiscountBalance += 112M (DayaLoanAmount × 2)
|
||||
> NetworkBalance شارژ نمیشود — فقط برای کمیسیون
|
||||
|
||||
---
|
||||
|
||||
## ۴. الگوریتم محاسبه کمیسیون هفتگی
|
||||
@@ -103,12 +95,15 @@
|
||||
|
||||
### ۴.۳ Pool هفتگی و توزیع
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["هر فعالسازی عضو\n25.2M واریز"] --> B["Pool هفتگی"]
|
||||
B --> C["sp_CalculateWeeklyBalances"]
|
||||
C --> D["sp_CalculateWeeklyCommissionPool"]
|
||||
D --> E["توزیع بر اساس\nUserBalance / TotalBalance"]
|
||||
```
|
||||
منبع Pool: هر فعالسازی عضو → 25.2M واریز به Pool
|
||||
توزیع: بر اساس WeeklyBalance هر عضو / مجموع WeeklyBalanceها
|
||||
SP: sp_CalculateWeeklyBalances → sp_CalculateWeeklyCommissionPool
|
||||
فرمت هفته: "YYYY-Www" (شمسی، شنبهپایه)
|
||||
```
|
||||
|
||||
> فرمت هفته: `YYYY-Www` (شمسی، شنبهپایه)
|
||||
|
||||
---
|
||||
|
||||
@@ -141,24 +136,16 @@ SP: sp_CalculateWeeklyBalances → sp_CalculateWeeklyCommissionPool
|
||||
|
||||
## ۷. یکپارچهسازی وام دایا
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["Hangfire Worker\nهر ۲۰ دقیقه — */20 * * * *"] --> B["بررسی درخواستهای pending"]
|
||||
B --> C["ارسال به API دایا\nMock/Real switchable"]
|
||||
C --> D["دریافت نتیجه"]
|
||||
D --> E["Balance += 56M"]
|
||||
D --> F["DiscountBalance += 112M\nDayaLoanAmount × 2"]
|
||||
```
|
||||
Hangfire Worker (هر ۲۰ دقیقه — cron: */20 * * * *)
|
||||
│
|
||||
▼
|
||||
بررسی درخواستهای pending
|
||||
│
|
||||
▼
|
||||
ارسال به API دایا (Mock/Real switchable)
|
||||
│
|
||||
▼
|
||||
دریافت نتیجه → شارژ ۲ کیفپول
|
||||
│
|
||||
├─→ Balance += 56M (DayaLoanAmount)
|
||||
└─→ DiscountBalance += 112M (DayaLoanAmount × 2 — دو برابر)
|
||||
مجموع: 168M
|
||||
|
||||
Hangfire retry: [AutomaticRetry(Attempts = 3)]
|
||||
```
|
||||
> مجموع شارژ: 168M — Hangfire retry: `[AutomaticRetry(Attempts = 3)]`
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -7,19 +7,27 @@
|
||||
|
||||
## ۱. معماری کلی مالی
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ FourSat Payment Architecture │
|
||||
├──────────────┬──────────────┬──────────────┬─────────────────────┤
|
||||
│ ZarinPal │ Daya Loan │ Manual Pay │ Discount Wallet │
|
||||
│ (IPG) │ (API) │ (Card2Card) │ (Internal) │
|
||||
├──────────────┴──────────────┴──────────────┴─────────────────────┤
|
||||
│ PYMS (Payment Service) │
|
||||
│ gRPC ←→ CMS ←→ FrontOffice/BackOffice │
|
||||
├──────────────────────────────────────────────────────────────────┤
|
||||
│ 3 Wallet System │
|
||||
│ Balance (نقدی) │ NetworkBalance (شبکه) │ DiscountBalance │
|
||||
└──────────────────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph GATEWAYS["درگاهها"]
|
||||
ZP["ZarinPal\nIPG"]
|
||||
DL["Daya Loan\nAPI"]
|
||||
MP["Manual Pay\nCard2Card"]
|
||||
DW["Discount Wallet\nInternal"]
|
||||
end
|
||||
|
||||
ZP --> PYMS["PYMS — Payment Service\ngRPC ↔ CMS ↔ FrontOffice/BackOffice"]
|
||||
DL --> PYMS
|
||||
MP --> PYMS
|
||||
DW --> PYMS
|
||||
|
||||
PYMS --> WALLETS
|
||||
|
||||
subgraph WALLETS["3 Wallet System"]
|
||||
W1["💰 Balance\nنقدی"]
|
||||
W2["🌟 NetworkBalance\nشبکه"]
|
||||
W3["🏷️ DiscountBalance\nتخفیفی"]
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
@@ -28,23 +36,14 @@
|
||||
|
||||
### ۲.۱ فلوی پرداخت
|
||||
|
||||
```
|
||||
کاربر → انتخاب محصول → درخواست پرداخت
|
||||
│
|
||||
▼
|
||||
CMS → CreatePaymentRequest (gRPC to PYMS)
|
||||
│
|
||||
▼
|
||||
PYMS → ZarinPal API → دریافت Authority
|
||||
│
|
||||
▼
|
||||
Redirect کاربر → صفحه پرداخت ZarinPal
|
||||
│
|
||||
▼
|
||||
بازگشت با Authority → CMS VerifyPayment
|
||||
│
|
||||
├─→ موفق: ثبت سفارش + شارژ کیفپول (در صورت نیاز)
|
||||
└─→ ناموفق: نمایش پیام خطا
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["کاربر → انتخاب محصول\nدرخواست پرداخت"] --> B["CMS → CreatePaymentRequest\ngRPC to PYMS"]
|
||||
B --> C["PYMS → ZarinPal API\nدریافت Authority"]
|
||||
C --> D["Redirect کاربر\nصفحه پرداخت ZarinPal"]
|
||||
D --> E["بازگشت با Authority\nCMS VerifyPayment"]
|
||||
E -->|موفق| F["✅ ثبت سفارش\n+ شارژ کیفپول"]
|
||||
E -->|ناموفق| G["❌ نمایش پیام خطا"]
|
||||
```
|
||||
|
||||
### ۲.۲ تنظیمات ZarinPal
|
||||
@@ -62,21 +61,14 @@ Redirect کاربر → صفحه پرداخت ZarinPal
|
||||
|
||||
### ۳.۱ معماری
|
||||
|
||||
```
|
||||
Hangfire Recurring Job (هر ۲۰ دقیقه — cron: */20 * * * *)
|
||||
│
|
||||
▼
|
||||
DayaLoanProcessorJob.Execute()
|
||||
│
|
||||
▼
|
||||
بررسی LoanRequests با Status=Pending
|
||||
│
|
||||
▼
|
||||
برای هر درخواست:
|
||||
├─→ ارسال به DayaLoan API ([AutomaticRetry(Attempts=3)])
|
||||
├─→ در صورت تأیید: Balance += 56M, DiscountBalance += 112M (2×)
|
||||
├─→ ثبت Transaction + Log
|
||||
└─→ در صورت رد: Status=Rejected + ارسال SMS
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["Hangfire Recurring Job\nهر ۲۰ دقیقه — */20 * * * *"] --> B["DayaLoanProcessorJob.Execute"]
|
||||
B --> C["بررسی LoanRequests\nStatus = Pending"]
|
||||
C --> D["برای هر درخواست:"]
|
||||
D --> E["ارسال به DayaLoan API\nAutomaticRetry Attempts=3"]
|
||||
E -->|تأیید| F["✅ Balance += 56M\nDiscountBalance += 112M\n+ ثبت Transaction + Log"]
|
||||
E -->|رد| G["❌ Status = Rejected\n+ ارسال SMS"]
|
||||
```
|
||||
|
||||
### ۳.۲ Mock Mode
|
||||
@@ -108,21 +100,14 @@ DayaLoanProcessorJob.Execute()
|
||||
|
||||
> ⚠️ **وضعیت: طراحیشده — پیادهسازی نشده**
|
||||
|
||||
```
|
||||
فلوی پیشنهادی:
|
||||
کاربر → انتخاب "کارتبهکارت"
|
||||
│
|
||||
▼
|
||||
نمایش شمارهکارت مقصد + مبلغ
|
||||
│
|
||||
▼
|
||||
کاربر → واریز + آپلود تصویر رسید
|
||||
│
|
||||
▼
|
||||
ادمین BackOffice → مشاهده لیست درخواستها
|
||||
│
|
||||
▼
|
||||
تأیید/رد → شارژ خودکار کیفپول
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["کاربر → انتخاب کارتبهکارت"] --> B["نمایش شمارهکارت مقصد\n+ مبلغ"]
|
||||
B --> C["کاربر → واریز\n+ آپلود تصویر رسید"]
|
||||
C --> D["ادمین BackOffice\nمشاهده لیست درخواستها"]
|
||||
D --> E{"تأیید / رد؟"}
|
||||
E -->|تأیید| F["✅ شارژ خودکار کیفپول"]
|
||||
E -->|رد| G["❌ اطلاعرسانی به کاربر"]
|
||||
```
|
||||
|
||||
**موجودیتهای مورد نیاز:**
|
||||
@@ -149,22 +134,13 @@ MaxDiscountPercent محصول = 40% (هر محصول درصد تخفیف مخص
|
||||
|
||||
### ۵.۲ فلوی خرید فروشگاه تخفیفی
|
||||
|
||||
```
|
||||
کاربر (عضو باشگاه) → مشاهده محصول
|
||||
│
|
||||
▼
|
||||
قیمت تخفیفخورده نمایش داده میشود
|
||||
│
|
||||
▼
|
||||
افزودن به سبد → بررسی DiscountBalance
|
||||
│
|
||||
├─→ DiscountBalance کافی:
|
||||
│ سهم تخفیف از DiscountBalance کسر
|
||||
│ باقیمانده → IPG (ZarinPal)
|
||||
│
|
||||
└─→ DiscountBalance ناکافی:
|
||||
فقط به اندازه موجودی از تخفیف
|
||||
باقیمانده بیشتر → IPG
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["کاربر عضو باشگاه\nمشاهده محصول"] --> B["قیمت تخفیفخورده نمایش داده میشود"]
|
||||
B --> C["افزودن به سبد\nبررسی DiscountBalance"]
|
||||
C --> D{"موجودی کافی؟"}
|
||||
D -->|کافی| E["سهم تخفیف از DiscountBalance\nباقیمانده → IPG ZarinPal"]
|
||||
D -->|ناکافی| F["فقط به اندازه موجودی\nباقیمانده بیشتر → IPG"]
|
||||
```
|
||||
|
||||
### ۵.۳ دسترسی فروشگاه تخفیفی
|
||||
|
||||
@@ -7,21 +7,31 @@
|
||||
|
||||
## ۱. دو فروشگاه FourSat
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ FourSat Stores │
|
||||
├───────────────────────┬─────────────────────────────────┤
|
||||
│ Regular Store │ Discount Store │
|
||||
│ (/store) │ (/discount-store) │
|
||||
├───────────────────────┼─────────────────────────────────┤
|
||||
│ • همه کاربران │ • فقط اعضای باشگاه │
|
||||
│ • پرداخت 100% نقدی │ • پرداخت ترکیبی (تخفیف+نقد) │
|
||||
│ • قیمت عادی │ • تخفیف بر اساس MaxDiscountPercent │
|
||||
│ • VAT = 10% │ • VAT = 9% (در کد PlaceOrder) │
|
||||
├───────────────────────┴─────────────────────────────────┤
|
||||
│ Shared: Products, Categories, │
|
||||
│ Inventory, ProductImages (1:1 square) │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph RS["Regular Store — /store"]
|
||||
R1["همه کاربران"]
|
||||
R2["پرداخت 100% نقدی"]
|
||||
R3["قیمت عادی"]
|
||||
R4["VAT = 10%"]
|
||||
end
|
||||
|
||||
subgraph DS["Discount Store — /discount-store"]
|
||||
D1["فقط اعضای باشگاه"]
|
||||
D2["پرداخت ترکیبی تخفیف+نقد"]
|
||||
D3["تخفیف بر اساس MaxDiscountPercent"]
|
||||
D4["VAT = 9%"]
|
||||
end
|
||||
|
||||
subgraph SHARED["مشترک"]
|
||||
S1["Products"]
|
||||
S2["Categories"]
|
||||
S3["Inventory"]
|
||||
S4["ProductImages 1:1"]
|
||||
end
|
||||
|
||||
RS --> SHARED
|
||||
DS --> SHARED
|
||||
```
|
||||
|
||||
---
|
||||
@@ -50,23 +60,14 @@ public async Task<ProductListResult> GetProductsPagedAsync(
|
||||
|
||||
### ۲.۲ پیادهسازی UI (هر دو فروشگاه)
|
||||
|
||||
```
|
||||
بارگذاری اولیه: 12 محصول
|
||||
│
|
||||
▼
|
||||
اسکرول → نمایش دکمه "نمایش محصولات بیشتر"
|
||||
│
|
||||
▼
|
||||
کلیک → LoadMore() → skip += 12
|
||||
│
|
||||
▼
|
||||
محصولات جدید اضافه به لیست (append)
|
||||
│
|
||||
▼
|
||||
تکرار تا Products.Count >= TotalCount
|
||||
│
|
||||
▼
|
||||
مخفیشدن دکمه
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["بارگذاری اولیه: 12 محصول"] --> B["اسکرول → نمایش دکمه\nنمایش محصولات بیشتر"]
|
||||
B --> C["کلیک → LoadMore\nskip += 12"]
|
||||
C --> D["محصولات جدید append به لیست"]
|
||||
D --> E{"Products.Count >= TotalCount?"}
|
||||
E -->|خیر| B
|
||||
E -->|بله| F["مخفیشدن دکمه"]
|
||||
```
|
||||
|
||||
---
|
||||
@@ -100,17 +101,14 @@ public int MaxDiscountPercent { get; set; } // 0 تا 100 — درصد تخفی
|
||||
|
||||
### ۳.۳ فلوی سفارش و موجودی
|
||||
|
||||
```
|
||||
سفارش جدید
|
||||
│
|
||||
▼
|
||||
بررسی Quantity - ReservedQuantity >= OrderQuantity?
|
||||
│
|
||||
├─→ بله: ReservedQuantity += OrderQuantity
|
||||
│ پرداخت موفق → Quantity -= OrderQuantity, Reserved -= OrderQuantity
|
||||
│ پرداخت ناموفق → Reserved -= OrderQuantity (آزادسازی)
|
||||
│
|
||||
└─→ خیر: نمایش "موجودی کافی نیست"
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["سفارش جدید"] --> B{"Quantity - Reserved >= OrderQty?"}
|
||||
B -->|بله| C["Reserved += OrderQty"]
|
||||
C --> D{"پرداخت موفق؟"}
|
||||
D -->|موفق| E["✅ Quantity -= OrderQty\nReserved -= OrderQty"]
|
||||
D -->|ناموفق| F["❌ Reserved -= OrderQty\nآزادسازی"]
|
||||
B -->|خیر| G["نمایش: موجودی کافی نیست"]
|
||||
```
|
||||
|
||||
---
|
||||
@@ -159,17 +157,11 @@ public class BundleItem {
|
||||
|
||||
### ۵.۲ فلو
|
||||
|
||||
```
|
||||
ادمین → ساخت باندل → انتخاب محصولات + تعیین قیمت
|
||||
│
|
||||
▼
|
||||
نمایش در فروشگاه با تگ "باندل"
|
||||
│
|
||||
▼
|
||||
خرید → تمام محصولات باندل یکجا به سبد
|
||||
│
|
||||
▼
|
||||
پرداخت → کسر موجودی هر محصول جداگانه
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["ادمین → ساخت باندل\nانتخاب محصولات + تعیین قیمت"] --> B["نمایش در فروشگاه\nبا تگ باندل"]
|
||||
B --> C["خرید → تمام محصولات\nیکجا به سبد"]
|
||||
C --> D["پرداخت → کسر موجودی\nهر محصول جداگانه"]
|
||||
```
|
||||
|
||||
---
|
||||
@@ -207,21 +199,22 @@ public class BundleItem {
|
||||
|
||||
## ۷. دستهبندیها (Categories)
|
||||
|
||||
```
|
||||
درختی / سلسلهمراتبی
|
||||
│
|
||||
├── سلامت و زیبایی
|
||||
│ ├── مکملها
|
||||
│ ├── مراقبت پوست
|
||||
│ └── مراقبت مو
|
||||
├── تغذیه
|
||||
│ ├── ارگانیک
|
||||
│ └── رژیمی
|
||||
└── ورزشی
|
||||
```mermaid
|
||||
graph TD
|
||||
ROOT["دستهبندیها"] --> A["سلامت و زیبایی"]
|
||||
ROOT --> B["تغذیه"]
|
||||
ROOT --> C["ورزشی"]
|
||||
|
||||
مدل: Category (Id, Name, ParentId?, ImageUrl, IsActive, SortOrder)
|
||||
A --> A1["مکملها"]
|
||||
A --> A2["مراقبت پوست"]
|
||||
A --> A3["مراقبت مو"]
|
||||
|
||||
B --> B1["ارگانیک"]
|
||||
B --> B2["رژیمی"]
|
||||
```
|
||||
|
||||
> مدل: `Category (Id, Name, ParentId?, ImageUrl, IsActive, SortOrder)`
|
||||
|
||||
---
|
||||
|
||||
## ۸. خلاصه وضعیت
|
||||
|
||||
@@ -7,27 +7,19 @@
|
||||
|
||||
## ۱. فلوی کامل چرخه کاربر
|
||||
|
||||
```
|
||||
ورود به سایت
|
||||
│
|
||||
▼
|
||||
ثبتنام (موبایل + OTP)
|
||||
│
|
||||
▼
|
||||
تکمیل پروفایل
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┬────────────────────────┐
|
||||
│ مسیر عادی │ مسیر باشگاه │
|
||||
├─────────────────────┼────────────────────────┤
|
||||
│ خرید از فروشگاه │ خرید پکیج طلایی (56M) │
|
||||
│ مشاهده بلاگ │ امضای قرارداد (OTP) │
|
||||
│ استفاده از خدمات │ فعالسازی (25M) │
|
||||
│ │ عضویت در درخت باینری │
|
||||
│ │ دسترسی فروشگاه تخفیفی │
|
||||
│ │ دسترسی فیچرهای باشگاه │
|
||||
│ │ کسب کمیسیون هفتگی │
|
||||
└─────────────────────┴────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["ورود به سایت"] --> B["ثبتنام — موبایل + OTP"]
|
||||
B --> C["تکمیل پروفایل"]
|
||||
C --> D{"مسیر؟"}
|
||||
|
||||
D -->|عادی| E["🛒 خرید از فروشگاه\nمشاهده بلاگ\nاستفاده از خدمات"]
|
||||
|
||||
D -->|باشگاه| F["🏆 خرید پکیج طلایی 56M"]
|
||||
F --> G["امضای قرارداد OTP"]
|
||||
G --> H["فعالسازی 25.2M"]
|
||||
H --> I["عضویت درخت باینری"]
|
||||
I --> J["دسترسی فروشگاه تخفیفی\nفیچرهای باشگاه\nکمیسیون هفتگی"]
|
||||
```
|
||||
|
||||
---
|
||||
@@ -36,28 +28,16 @@
|
||||
|
||||
### ۲.۱ فلوی ثبتنام
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["صفحه ثبتنام"] --> B["ورود شماره موبایل"]
|
||||
B --> C["ارسال OTP\nKavenegar SMS API"]
|
||||
C --> D["تأیید کد OTP"]
|
||||
D -->|کاربر جدید| E["ساخت User\n+ JWT Token"]
|
||||
D -->|کاربر موجود| F["ورود\n+ JWT Token"]
|
||||
```
|
||||
صفحه ثبتنام
|
||||
│
|
||||
▼
|
||||
ورود شماره موبایل
|
||||
│
|
||||
▼
|
||||
ارسال OTP (Kavenegar SMS API)
|
||||
│
|
||||
▼
|
||||
تأیید کد OTP
|
||||
│
|
||||
├─→ کاربر جدید: ساخت User + JWT Token
|
||||
└─→ کاربر موجود: ورود + JWT Token
|
||||
|
||||
JWT Claims:
|
||||
• UserId
|
||||
• PhoneNumber
|
||||
• IsClubMember (bool)
|
||||
• Roles[] (Admin, Customer)
|
||||
• ReferralCode
|
||||
```
|
||||
**JWT Claims:** `UserId`, `PhoneNumber`, `IsClubMember`, `Roles[]`, `ReferralCode`
|
||||
|
||||
### ۲.۲ اصلاحات ثبتنام
|
||||
|
||||
@@ -76,16 +56,15 @@ JWT Claims:
|
||||
|
||||
### ۳.۱ مشکل قبلی
|
||||
|
||||
```
|
||||
قبل:
|
||||
Admin و Customer هر دو از یک DbContext و Identity استفاده میکردند
|
||||
یک ادمین میتوانست به صورت Customer هم ظاهر شود ← تداخل Claims
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph BEFORE["قبل — مشکل"]
|
||||
A1["Admin + Customer"] --> A2["یک DbContext\nیک Identity\nتداخل Claims"]
|
||||
end
|
||||
|
||||
بعد (اصلاحشده):
|
||||
✅ ICurrentUserService → تشخیص دقیق نقش فعلی
|
||||
✅ جداسازی Authorization Policy
|
||||
✅ Admin claims فقط در BackOffice
|
||||
✅ Customer claims فقط در FrontOffice
|
||||
subgraph AFTER["بعد — اصلاحشده ✅"]
|
||||
B1["ICurrentUserService"] --> B2["جداسازی Policy\nAdmin → BackOffice\nCustomer → FrontOffice"]
|
||||
end
|
||||
```
|
||||
|
||||
### ۳.۲ ICurrentUserService
|
||||
@@ -110,29 +89,16 @@ public interface ICurrentUserService {
|
||||
|
||||
### ۴.۱ فلوی امضای قرارداد
|
||||
|
||||
```
|
||||
خرید پکیج طلایی → Redirect به صفحه قرارداد
|
||||
│
|
||||
▼
|
||||
نمایش Modal غیرقابلبستهشدن
|
||||
│
|
||||
▼
|
||||
ReadContract RPC → نمایش متن قرارداد (Markdown/HTML)
|
||||
│
|
||||
▼
|
||||
کاربر باید تا انتهای متن اسکرول کند
|
||||
│
|
||||
▼
|
||||
فعال شدن دکمه "ارسال کد تأیید"
|
||||
│
|
||||
▼
|
||||
RequestContractOtp → ارسال SMS
|
||||
│
|
||||
▼
|
||||
ورود کد ← VerifyContractOtp
|
||||
│
|
||||
├─→ معتبر: AcceptContract → فعالسازی عضویت
|
||||
└─→ نامعتبر: پیام خطا (حداکثر ۵ تلاش)
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["خرید پکیج طلایی\nRedirect به صفحه قرارداد"] --> B["نمایش Modal\nغیرقابلبستهشدن"]
|
||||
B --> C["ReadContract RPC\nنمایش متن قرارداد"]
|
||||
C --> D["اسکرول تا انتها"]
|
||||
D --> E["فعال شدن دکمه\nارسال کد تأیید"]
|
||||
E --> F["RequestContractOtp\nارسال SMS"]
|
||||
F --> G["ورود کد\nVerifyContractOtp"]
|
||||
G -->|معتبر| H["✅ AcceptContract\nفعالسازی عضویت"]
|
||||
G -->|نامعتبر| I["❌ پیام خطا\nحداکثر ۵ تلاش"]
|
||||
```
|
||||
|
||||
### ۴.۲ ذخیرهسازی قرارداد
|
||||
@@ -206,20 +172,12 @@ else
|
||||
|
||||
## ۷. کدهای معرف (Referral)
|
||||
|
||||
```
|
||||
هر عضو باشگاه → یک ReferralCode یکتا
|
||||
لینک: https://foursat.ir/register?ref={ReferralCode}
|
||||
|
||||
ثبتنام با لینک:
|
||||
│
|
||||
▼
|
||||
ذخیره ReferrerId در پروفایل کاربر جدید
|
||||
│
|
||||
▼
|
||||
هنگام خرید پکیج → زیرمجموعه Referrer در درخت باینری
|
||||
│
|
||||
▼
|
||||
Referrer → دریافت bonus (طبق شرایط باشگاه)
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["هر عضو باشگاه\nیک ReferralCode یکتا"] --> B["لینک:\nhttps://foursat.ir/register?ref=CODE"]
|
||||
B --> C["ثبتنام با لینک\nذخیره ReferrerId"]
|
||||
C --> D["خرید پکیج\nزیرمجموعه Referrer در درخت"]
|
||||
D --> E["Referrer\nدریافت bonus"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -9,14 +9,15 @@
|
||||
|
||||
### ۱.۱ معماری سادهشده (Shopify-style)
|
||||
|
||||
```
|
||||
قبل (پیچیده):
|
||||
SitePage → SitePageSetting → SitePageContent → Template → ... (7 جدول)
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph BEFORE["قبل — پیچیده"]
|
||||
X1["SitePage"] --> X2["SitePageSetting"] --> X3["SitePageContent"] --> X4["Template\n... 7 جدول"]
|
||||
end
|
||||
|
||||
بعد (ساده):
|
||||
SitePage (PageType, JsonSettings, IsPublished)
|
||||
│
|
||||
└─→ هر PageType → یک typed editor در BackOffice
|
||||
subgraph AFTER["بعد — ساده ✅"]
|
||||
Y1["SitePage\nPageType + JsonSettings"] --> Y2["هر PageType\nیک typed editor"]
|
||||
end
|
||||
```
|
||||
|
||||
### ۱.۲ انواع صفحات
|
||||
@@ -97,21 +98,14 @@ message GetBlogPostsRequest {
|
||||
|
||||
### ۳.۱ معماری
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["آپلود فایل\nتصویر / سند"] --> B["FileManagementService"]
|
||||
B --> C["ذخیره در فایلسیستم\n+ ثبت در DB"]
|
||||
C --> D["مسیر: /app/uploads/year/month/guid.ext\nURL: /api/files/guid"]
|
||||
```
|
||||
آپلود فایل (تصویر/سند)
|
||||
│
|
||||
▼
|
||||
FileManagementService → ذخیره در فایلسیستم + ثبت در DB
|
||||
│
|
||||
▼
|
||||
مسیر فیزیکی: /app/uploads/{year}/{month}/{guid}.{ext}
|
||||
مسیر URL: /api/files/{guid}
|
||||
|
||||
محدودیتها:
|
||||
• حداکثر حجم: 10MB (configurable)
|
||||
• فرمتهای مجاز: jpg, png, webp, pdf, doc, docx
|
||||
• تصاویر: resize خودکار به 800×800 (محصولات)
|
||||
```
|
||||
> محدودیت: حداکثر 10MB • jpg, png, webp, pdf, doc, docx • Resize: 800×800 (محصولات)
|
||||
|
||||
### ۳.۲ Storage Strategy
|
||||
|
||||
@@ -198,20 +192,12 @@ CREATE TABLE SystemConfigurations (
|
||||
|
||||
### ۶.۱ معماری
|
||||
|
||||
```
|
||||
Hangfire Recurring Job (هر ۵ دقیقه)
|
||||
│
|
||||
▼
|
||||
ChatikaJob → بررسی پیامهای جدید کاربران
|
||||
│
|
||||
▼
|
||||
ارسال به Chatika API (با Polly retry ×3)
|
||||
│
|
||||
▼
|
||||
دریافت پاسخ → ذخیره در ChatMessages
|
||||
│
|
||||
▼
|
||||
نمایش در UI باشگاه (real-time via SignalR planned)
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["Hangfire Recurring Job\nهر ۵ دقیقه"] --> B["ChatikaJob\nبررسی پیامهای جدید"]
|
||||
B --> C["ارسال به Chatika API\nPolly retry ×3"]
|
||||
C --> D["دریافت پاسخ\nذخیره در ChatMessages"]
|
||||
D --> E["نمایش در UI باشگاه\nSignalR planned"]
|
||||
```
|
||||
|
||||
### ۶.۲ فعلی vs آینده
|
||||
@@ -228,20 +214,12 @@ ChatikaJob → بررسی پیامهای جدید کاربران
|
||||
|
||||
### ۷.۱ ساختار
|
||||
|
||||
```
|
||||
Hero Section (انیمیشن fade-in)
|
||||
│
|
||||
▼
|
||||
ویژگیها (Features Grid — 3 ستونه)
|
||||
│
|
||||
▼
|
||||
محصولات ویژه (Carousel)
|
||||
│
|
||||
▼
|
||||
آمار (Counter animation — اصلاحشده)
|
||||
│
|
||||
▼
|
||||
CTA — Call to Action (ثبتنام / ورود)
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["🎨 Hero Section\nانیمیشن fade-in"] --> B["✨ ویژگیها\nFeatures Grid — 3 ستونه"]
|
||||
B --> C["📦 محصولات ویژه\nCarousel"]
|
||||
C --> D["📊 آمار\nCounter animation\nlinear interpolation"]
|
||||
D --> E["🚀 CTA\nثبتنام / ورود"]
|
||||
```
|
||||
|
||||
### ۷.۲ اصلاح انیمیشن Counter
|
||||
|
||||
+170
-241
@@ -7,283 +7,212 @@
|
||||
|
||||
## ۱. فلوی کلان کاربر (User Journey)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ FourSat — User Journey │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ [ورود به سایت] │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ◆ آیا ثبتنام کرده؟ ◆──── خیر ───→ [Landing Page] │
|
||||
│ │ │ │
|
||||
│ بله [ثبتنام] │
|
||||
│ │ موبایل + OTP │
|
||||
│ ▼ │ │
|
||||
│ [Login + JWT] ▼ │
|
||||
│ │ [پروفایل] │
|
||||
│ ▼ │ │
|
||||
│ ◆ عضو باشگاه؟ ◆ ▼ │
|
||||
│ │ │ ┌───────────────┐ │
|
||||
│ بله خیر │ Regular Store │ │
|
||||
│ │ │ │ خرید عادی │ │
|
||||
│ │ └──────────────→│ IPG پرداخت │ │
|
||||
│ │ └───────────────┘ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────────────────────────────────────┐ │
|
||||
│ │ Club Member Dashboard │ │
|
||||
│ ├──────────┬──────────┬──────────┬─────────────┤ │
|
||||
│ │ فروشگاه │ درخت شبکه │ کمیسیون │ Chatika AI │ │
|
||||
│ │ تخفیفی │ باینری │ هفتگی │ │ │
|
||||
│ │ (per-product) │ │ │ │ │
|
||||
│ └──────────┴──────────┴──────────┴─────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["🌐 ورود به سایت"] --> B{"آیا ثبتنام کرده؟"}
|
||||
B -->|خیر| C["Landing Page"]
|
||||
C --> D["ثبتنام\nموبایل + OTP"]
|
||||
D --> E["پروفایل"]
|
||||
E --> F
|
||||
|
||||
B -->|بله| G["Login + JWT"]
|
||||
G --> H{"عضو باشگاه؟"}
|
||||
H -->|خیر| F["🛒 Regular Store\nخرید عادی — IPG پرداخت"]
|
||||
H -->|بله| I["🏆 Club Member Dashboard"]
|
||||
|
||||
I --> J["فروشگاه تخفیفی\nper-product MaxDiscount%"]
|
||||
I --> K["درخت شبکه\nباینری"]
|
||||
I --> L["کمیسیون\nهفتگی"]
|
||||
I --> M["Chatika AI"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۲. فلوی مالی (Financial Flow)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ FourSat — Financial Flow │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ═══════════════════ ورودی پول ═══════════════════ │
|
||||
│ │
|
||||
│ [ZarinPal IPG] ──→ ┐ │
|
||||
│ [Daya Loan] ──→ ├──→ [PYMS Service] ──→ [DB Transaction] │
|
||||
│ [Manual Pay] ──→ ┘ │ │
|
||||
│ ▼ │
|
||||
│ ═══════════ توزیع به کیفپولها ═══════════ │
|
||||
│ │
|
||||
│ ┌────────────────┐ ┌─────────────────┐ ┌──────────────────┐ │
|
||||
│ │ 💰 Balance │ │ 🌟 NetworkBal │ │ 🏷️ DiscountBal │ │
|
||||
│ │ (نقدی) │ │ (طلایی/کمیسیون)│ │ (تخفیفی) │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ • IPG: +56M │ │ • شارژ نمیشود │ │ • IPG: +112M │ │
|
||||
│ │ • Daya: +56M │ │ • فقط برای │ │ • Daya: +112M │ │
|
||||
│ │ • فعالسازی │ │ محاسبه │ │ (دو برابر) │ │
|
||||
│ │ -25.2M │ │ کمیسیون │ │ • per-product │ │
|
||||
│ │ • خرید فروشگاه │ │ • سقف 300/هفته │ │ MaxDiscount% │ │
|
||||
│ └───────┬────────┘ └────────┬────────┘ └────────┬─────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ═══════════════════ خروجی پول ═══════════════════ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ Weekly Commission Pool │ │
|
||||
│ │ │ │
|
||||
│ │ Source: هر فعالسازی → 25.2M واریز │ │
|
||||
│ │ Calculate: sp_CalculateWeeklyBalances │ │
|
||||
│ │ Distribute: sp_CalculateWeeklyCommissionPool │ │
|
||||
│ │ Formula: UserShare = UserBalance / TotalBalance │ │
|
||||
│ │ Cap: MAX 300 per leg per week │ │
|
||||
│ │ Carryover: به هفته بعد (max 300, else flush) │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─ Member A: Balance=150 → Share=150/600 → 25% ─┐ │ │
|
||||
│ │ │ Member B: Balance=200 → Share=200/600 → 33% │ │ │
|
||||
│ │ │ Member C: Balance=250 → Share=250/600 → 42% │ │ │
|
||||
│ │ └─ Total: 600 ─┘ │ │
|
||||
│ └──────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph INPUT["═══ ورودی پول ═══"]
|
||||
Z1["ZarinPal IPG"]
|
||||
Z2["Daya Loan"]
|
||||
Z3["Manual Pay"]
|
||||
end
|
||||
|
||||
Z1 --> PYMS["PYMS Service"]
|
||||
Z2 --> PYMS
|
||||
Z3 --> PYMS
|
||||
PYMS --> TX[("DB Transaction")]
|
||||
|
||||
TX --> W1 & W2 & W3
|
||||
|
||||
subgraph WALLETS["═══ توزیع به کیفپولها ═══"]
|
||||
W1["💰 Balance — نقدی\n• IPG: +56M\n• Daya: +56M\n• فعالسازی: −25.2M\n• خرید فروشگاه"]
|
||||
W2["🌟 NetworkBalance — طلایی\n• شارژ نمیشود\n• فقط محاسبه کمیسیون\n• سقف 300/هفته"]
|
||||
W3["🏷️ DiscountBalance — تخفیفی\n• IPG: +112M\n• Daya: +112M\n• per-product MaxDiscount%"]
|
||||
end
|
||||
|
||||
W1 & W2 --> POOL
|
||||
|
||||
subgraph POOL["═══ Weekly Commission Pool ═══"]
|
||||
P1["هر فعالسازی → 25.2M واریز به Pool"]
|
||||
P2["sp_CalculateWeeklyBalances"]
|
||||
P3["sp_CalculateWeeklyCommissionPool"]
|
||||
P4["UserShare = UserBalance / TotalBalance"]
|
||||
P5["Cap: MAX 300 per leg per week"]
|
||||
P1 --> P2 --> P3 --> P4 --> P5
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۳. فلوی داده (Data Flow)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ FourSat — Data Flow │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ [Browser/Client] │
|
||||
│ │ │
|
||||
│ │ HTTPS │
|
||||
│ ▼ │
|
||||
│ [nginx / K8s Ingress] │
|
||||
│ │ │
|
||||
│ ├──→ / ──────────→ [FrontOffice :5003] (Blazor Server) │
|
||||
│ │ │ │
|
||||
│ ├──→ /admin ─────→ [BackOffice :5002] (Blazor WASM) │
|
||||
│ │ │ │
|
||||
│ └──→ /hangfire ──→ [CMS :5001] (Dashboard) │
|
||||
│ │ │
|
||||
│ ┌─────────────────────────────┘ │
|
||||
│ │ gRPC (Protobuf v3, HTTP/2) │
|
||||
│ ▼ │
|
||||
│ [CMS Microservice :5001] │
|
||||
│ │ │
|
||||
│ ├──→ [MediatR] ──→ Commands/Queries ──→ Handlers │
|
||||
│ │ │ │
|
||||
│ ├──→ [Hangfire] ──→ Background Jobs │ │
|
||||
│ │ • DayaLoan (15min) │ │
|
||||
│ │ • Commission (weekly) │ │
|
||||
│ │ • Chatika (5min) │ │
|
||||
│ │ • InventorySync (hourly) │ │
|
||||
│ │ │ │
|
||||
│ └──→ [External Services] │ │
|
||||
│ • ZarinPal API │ │
|
||||
│ • Kavenegar API ▼ │
|
||||
│ • DayaLoan API [EF Core 9] │
|
||||
│ • Chatika API │ │
|
||||
│ ▼ │
|
||||
│ [SQL Server 2022] │
|
||||
│ Schema: [CMS] │
|
||||
│ ~15 main tables │
|
||||
│ + 3 Stored Procs │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
CLIENT["🌐 Browser / Client"] -->|HTTPS| NGINX["nginx / K8s Ingress"]
|
||||
|
||||
NGINX -->|"/"| FO["FrontOffice :5003\nBlazor Server"]
|
||||
NGINX -->|"/admin"| BO["BackOffice :5002\nBlazor WASM"]
|
||||
NGINX -->|"/hangfire"| CMS
|
||||
|
||||
FO -->|gRPC| CMS["CMS Microservice :5001"]
|
||||
BO -->|gRPC| CMS
|
||||
|
||||
CMS --> MEDIATR["MediatR\nCommands / Queries → Handlers"]
|
||||
CMS --> HF["Hangfire\n• DayaLoan — */20 min\n• Commission — Sunday 00:05\n• Chatika — */5 min"]
|
||||
CMS --> EXT["External Services\n• ZarinPal API\n• Kavenegar API\n• DayaLoan API\n• Chatika API"]
|
||||
|
||||
MEDIATR --> EF["EF Core 9"]
|
||||
HF --> EF
|
||||
EF --> DB[("SQL Server 2022\nSchema: CMS\n~15 tables + 3 SPs")]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۴. درخت باینری شبکه (Network Tree)
|
||||
|
||||
```
|
||||
┌─────────┐
|
||||
│ Root │
|
||||
│ (Admin) │
|
||||
└────┬────┘
|
||||
┌─────────┴─────────┐
|
||||
┌────▼────┐ ┌────▼────┐
|
||||
│ User A │ │ User B │
|
||||
│ L=120 │ │ L=0 │
|
||||
│ R=80 │ │ R=150 │
|
||||
└────┬────┘ └────┬────┘
|
||||
┌───────┴───────┐ ┌──────┴──────┐
|
||||
┌────▼──┐ ┌────▼──┐ ┌──▼───┐ ┌───▼──┐
|
||||
│User C │ │User D │ │User E│ │User F│
|
||||
│Active │ │Active │ │Pend. │ │Active│
|
||||
└───────┘ └───────┘ └──────┘ └──────┘
|
||||
```mermaid
|
||||
graph TD
|
||||
ROOT["🔵 Root — Admin"]
|
||||
ROOT --- A["👤 User A\nL=120 | R=80"]
|
||||
ROOT --- B["👤 User B\nL=0 | R=150"]
|
||||
|
||||
Legend:
|
||||
L = Left leg sales this week
|
||||
R = Right leg sales this week
|
||||
Active = فعال (contract signed)
|
||||
Pend. = در انتظار فعالسازی
|
||||
شبکه روی entity User مدل شده (NetworkParentId, LegPosition)
|
||||
محاسبه کمیسیون تا عمق 15 سطح — درخت بدون محدودیت عمق
|
||||
A --- C["✅ User C\nActive"]
|
||||
A --- D["✅ User D\nActive"]
|
||||
B --- E["⏳ User E\nPending"]
|
||||
B --- F["✅ User F\nActive"]
|
||||
|
||||
style ROOT fill:#1976D2,color:#fff
|
||||
style C fill:#4CAF50,color:#fff
|
||||
style D fill:#4CAF50,color:#fff
|
||||
style E fill:#FF9800,color:#fff
|
||||
style F fill:#4CAF50,color:#fff
|
||||
```
|
||||
|
||||
> **راهنما:**
|
||||
> - `L` / `R` = فروش پای چپ / راست این هفته
|
||||
> - **Active** = فعال (قرارداد امضا شده) — **Pending** = در انتظار فعالسازی
|
||||
> - شبکه روی entity `User` مدل شده (`NetworkParentId`, `LegPosition`)
|
||||
> - محاسبه کمیسیون تا عمق ۱۵ سطح — درخت بدون محدودیت عمق
|
||||
|
||||
---
|
||||
|
||||
## ۵. فلوی خرید — Regular vs Discount Store
|
||||
|
||||
### ۵.۱ Regular Store
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A1["مشاهده محصولات"] --> B1["Lazy Load — 12 per page"]
|
||||
B1 --> C1["افزودن به سبد"]
|
||||
C1 --> D1["بررسی موجودی"]
|
||||
D1 --> E1["Checkout"]
|
||||
E1 --> F1["ZarinPal IPG\n100% نقدی"]
|
||||
F1 --> G1["ثبت سفارش"]
|
||||
G1 --> H1["کسر موجودی"]
|
||||
H1 --> I1["SMS تأیید"]
|
||||
```
|
||||
┌────────────────────────────────┬──────────────────────────────────┐
|
||||
│ Regular Store │ Discount Store │
|
||||
├────────────────────────────────┼──────────────────────────────────┤
|
||||
│ │ │
|
||||
│ [مشاهده محصولات] │ [مشاهده محصولات] ← فقط باشگاه │
|
||||
│ │ │ │ │
|
||||
│ ▼ │ ▼ │
|
||||
│ [Lazy Load — 12 per page] │ [Lazy Load — 12 per page] │
|
||||
│ │ │ │ │
|
||||
│ ▼ │ ▼ │
|
||||
│ [افزودن به سبد] │ [افزودن به سبد] │
|
||||
│ │ │ │ │
|
||||
│ ▼ │ ▼ │
|
||||
│ [بررسی موجودی] │ [بررسی موجودی] │
|
||||
│ │ │ [بررسی DiscountBalance] │
|
||||
│ ▼ │ │ │
|
||||
│ [Checkout] │ ▼ │
|
||||
│ │ │ [محاسبه سهم تخفیف (MaxDiscount%)]│
|
||||
│ ▼ │ [محاسبه سهم نقدی (باقیمانده)] │
|
||||
│ [ZarinPal IPG] │ │ │
|
||||
│ [100% نقدی] │ ▼ │
|
||||
│ │ │ [کسر از DiscountBalance] │
|
||||
│ ▼ │ [ZarinPal IPG برای باقیمانده] │
|
||||
│ [ثبت سفارش] │ │ │
|
||||
│ │ │ ▼ │
|
||||
│ ▼ │ [ثبت سفارش ترکیبی] │
|
||||
│ [کسر موجودی] │ [کسر موجودی] │
|
||||
│ │ │ │ │
|
||||
│ ▼ │ ▼ │
|
||||
│ [SMS تأیید] │ [SMS تأیید] │
|
||||
│ │ │
|
||||
└────────────────────────────────┴──────────────────────────────────┘
|
||||
|
||||
### ۵.۲ Discount Store
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A2["مشاهده محصولات\nفقط اعضای باشگاه"] --> B2["Lazy Load — 12 per page"]
|
||||
B2 --> C2["افزودن به سبد"]
|
||||
C2 --> D2["بررسی موجودی + DiscountBalance"]
|
||||
D2 --> E2["محاسبه سهم تخفیف\nMaxDiscount% هر محصول"]
|
||||
E2 --> F2["محاسبه سهم نقدی\nباقیمانده"]
|
||||
F2 --> G2["کسر از DiscountBalance"]
|
||||
G2 --> H2["ZarinPal IPG\nبرای باقیمانده نقدی"]
|
||||
H2 --> I2["ثبت سفارش ترکیبی"]
|
||||
I2 --> J2["کسر موجودی"]
|
||||
J2 --> K2["SMS تأیید"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۶. معماری Deployment
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ Production Server │
|
||||
│ 45.149.79.127 │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────┐ ┌────────────────────────────────────┐ │
|
||||
│ │ nginx │────→│ Kubernetes Cluster │ │
|
||||
│ │ :80/:443│ │ │ │
|
||||
│ └─────────┘ │ ┌───────────┐ ┌───────────────┐ │ │
|
||||
│ │ │CMS ×2 │ │FrontOffice ×2 │ │ │
|
||||
│ │ │:5001 gRPC │ │:5003 Blazor │ │ │
|
||||
│ │ └─────┬─────┘ └───────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌─────▼─────┐ ┌───────────────┐ │ │
|
||||
│ │ │SQL Server │ │BackOffice ×1 │ │ │
|
||||
│ │ │:1433 │ │:5002 Static │ │ │
|
||||
│ │ └───────────┘ └───────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌───────────┐ ┌───────────────┐ │ │
|
||||
│ │ │Nexus │ │Hangfire │ │ │
|
||||
│ │ │:8081 │ │(inside CMS) │ │ │
|
||||
│ │ └───────────┘ └───────────────┘ │ │
|
||||
│ └────────────────────────────────────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph SERVER["🖥️ Production Server — 45.149.79.127"]
|
||||
NGINX["nginx\n:80 / :443"]
|
||||
subgraph K8S["☸ Kubernetes Cluster"]
|
||||
CMS["CMS ×2\n:5001 gRPC"]
|
||||
FO["FrontOffice ×2\n:5003 Blazor Server"]
|
||||
BO["BackOffice ×1\n:5002 Static"]
|
||||
DB[("SQL Server\n:1433")]
|
||||
NEXUS["Nexus\n:8081"]
|
||||
HF["Hangfire\ninside CMS"]
|
||||
end
|
||||
end
|
||||
|
||||
NGINX --> CMS
|
||||
NGINX --> FO
|
||||
NGINX --> BO
|
||||
CMS --> DB
|
||||
CMS --> HF
|
||||
|
||||
style SERVER fill:#f5f5f5,stroke:#333
|
||||
style K8S fill:#e3f2fd,stroke:#1976D2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۷. Entity Relationship (سادهشده)
|
||||
|
||||
```
|
||||
┌──────────┐ ┌──────────────┐
|
||||
│ User │────→│ ClubMembership│
|
||||
│ +Network │ │ │
|
||||
│ ParentId│ └──────────────┘
|
||||
│ +LegPos │
|
||||
└────┬─────┘
|
||||
│
|
||||
├────→ ┌──────────┐ ┌──────────┐
|
||||
│ │ Order │────→│ OrderItem│────→ [Product]
|
||||
│ └──────────┘ └──────────┘
|
||||
│
|
||||
├────→ ┌──────────────┐
|
||||
│ │ Transaction │
|
||||
│ └──────────────┘
|
||||
│
|
||||
├────→ ┌──────────────┐
|
||||
│ │ UserWallet │────→ Balance + NetworkBalance + DiscountBalance
|
||||
│ └──────────────┘
|
||||
│
|
||||
├────→ ┌──────────────┐
|
||||
│ │ UserContract │
|
||||
│ └──────────────┘
|
||||
│
|
||||
└────→ ┌──────────────┐
|
||||
│ ChatMessage │
|
||||
└──────────────┘
|
||||
|
||||
┌──────────┐ ┌───────────┐
|
||||
│ Product │────→│ Inventory │
|
||||
│ │────→│ Category │
|
||||
│ │────→│ Images │
|
||||
└──────────┘
|
||||
|
||||
┌──────────┐ ┌──────────────────────┐
|
||||
│ SitePage │ │ SystemConfiguration │
|
||||
│ (typed) │ │ (key-value) │
|
||||
└──────────┘ └──────────────────────┘
|
||||
|
||||
┌──────────┐
|
||||
│ BlogPost │────→ [Tags, Category, Author]
|
||||
└──────────┘
|
||||
```mermaid
|
||||
erDiagram
|
||||
User ||--o{ ClubMembership : has
|
||||
User ||--o| UserWallet : has
|
||||
User ||--o{ UserContract : signs
|
||||
User ||--o{ UserOrder : places
|
||||
User ||--o{ ChatMessage : sends
|
||||
User }o--o| User : "NetworkParentId"
|
||||
|
||||
UserOrder ||--|{ OrderItem : contains
|
||||
OrderItem }o--|| Product : references
|
||||
UserOrder ||--o{ Transaction : has
|
||||
|
||||
Product ||--o| Inventory : has
|
||||
Product }o--|| Category : belongs_to
|
||||
Product ||--o{ ProductImage : has
|
||||
|
||||
UserWallet ||--o{ UserWalletChangeLog : logs
|
||||
|
||||
BlogPost }o--|| Category : belongs_to
|
||||
|
||||
UserWallet {
|
||||
long Balance
|
||||
long NetworkBalance
|
||||
long DiscountBalance
|
||||
}
|
||||
User {
|
||||
Guid NetworkParentId
|
||||
int LegPosition
|
||||
}
|
||||
UserContract {
|
||||
Guid SignGuid
|
||||
string SignedPdfFile
|
||||
}
|
||||
```
|
||||
|
||||
@@ -71,34 +71,25 @@ totalDoc/
|
||||
|
||||
## نقشه ارتباط فایلها
|
||||
|
||||
```
|
||||
┌──────────────┐
|
||||
│ O2: INDEX │ ← شما اینجا هستید
|
||||
└──────┬───────┘
|
||||
│
|
||||
┌─────────────────┼──────────────────┐
|
||||
│ │ │
|
||||
┌────▼────┐ ┌────▼─────┐ ┌────▼─────┐
|
||||
│Business │ │Technical │ │Overview │
|
||||
│ (B1-B5) │ │ (T1-T5) │ │ (O1-O5) │
|
||||
└────┬────┘ └────┬─────┘ └────┬─────┘
|
||||
│ │ │
|
||||
┌────┴────────────────┴──────────────────┴────┐
|
||||
│ │
|
||||
│ B1 ←→ B2 (مالی/باشگاه) │
|
||||
│ B2 ←→ B3 (پرداخت/فروشگاه) │
|
||||
│ B3 ←→ B4 (فروشگاه/کاربر) │
|
||||
│ B4 ←→ B5 (کاربر/محتوا) │
|
||||
│ B1 ←→ T1 (باشگاه/CMS) │
|
||||
│ T1 ←→ T2 (CMS/UI) │
|
||||
│ T1 ←→ T3 (CMS/Deploy) │
|
||||
│ T3 ←→ T4 (Deploy/Migration) │
|
||||
│ T1 ←→ T5 (CMS/API) │
|
||||
│ O1: دیاگرام = بصری B1-B5 + T1-T5 │
|
||||
│ O3: تاریخچه = changelog B1-B5 + T1-T5 │
|
||||
│ O5: آینده = roadmap B1-B5 + T1-T5 │
|
||||
│ │
|
||||
└──────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
graph TD
|
||||
INDEX["📋 O2: INDEX\nشما اینجا هستید"]
|
||||
INDEX --> BIZ["📁 Business\nB1-B5"]
|
||||
INDEX --> TECH["📁 Technical\nT1-T5"]
|
||||
INDEX --> OVR["📁 Overview\nO1-O5"]
|
||||
|
||||
BIZ --- B12["B1 ↔ B2\nمالی / باشگاه"]
|
||||
BIZ --- B23["B2 ↔ B3\nپرداخت / فروشگاه"]
|
||||
BIZ --- B34["B3 ↔ B4\nفروشگاه / کاربر"]
|
||||
BIZ --- B45["B4 ↔ B5\nکاربر / محتوا"]
|
||||
|
||||
BIZ --- TECH
|
||||
TECH --- T12["T1 ↔ T2 — CMS/UI"]
|
||||
TECH --- T13["T1 ↔ T3 — CMS/Deploy"]
|
||||
TECH --- T34["T3 ↔ T4 — Deploy/Migration"]
|
||||
TECH --- T15["T1 ↔ T5 — CMS/API"]
|
||||
|
||||
OVR --- OX["O1: دیاگرامها\nO3: تاریخچه\nO5: نقشه راه"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -69,40 +69,42 @@ Documentation ████████████████████
|
||||
|
||||
### Q1 1404 (فروردین-خرداد)
|
||||
|
||||
```
|
||||
Sprint 1 (فروردین):
|
||||
├── H2: Mobile Responsive
|
||||
├── H1: Product Bundle
|
||||
└── M4: SEO Meta Tags
|
||||
|
||||
Sprint 2 (اردیبهشت):
|
||||
├── M1: Manual Payment (if approved)
|
||||
├── M2: SignalR Chatika
|
||||
└── M6: Dashboard Charts
|
||||
|
||||
Sprint 3 (خرداد):
|
||||
├── M3: Dark Mode
|
||||
├── H3: Rate Limiting
|
||||
└── L1: PWA
|
||||
```mermaid
|
||||
gantt
|
||||
title Q1 1404 — فروردین تا خرداد
|
||||
dateFormat YYYY-MM-DD
|
||||
section Sprint 1 فروردین
|
||||
H2 Mobile Responsive :a1, 2025-03-21, 5d
|
||||
H1 Product Bundle :a2, after a1, 3d
|
||||
M4 SEO Meta Tags :a3, after a2, 2d
|
||||
section Sprint 2 اردیبهشت
|
||||
M1 Manual Payment :b1, 2025-04-21, 3d
|
||||
M2 SignalR Chatika :b2, after b1, 2d
|
||||
M6 Dashboard Charts :b3, after b2, 3d
|
||||
section Sprint 3 خرداد
|
||||
M3 Dark Mode :c1, 2025-05-22, 2d
|
||||
H3 Rate Limiting :c2, after c1, 2d
|
||||
L1 PWA :c3, after c2, 3d
|
||||
```
|
||||
|
||||
### Q2 1404 (تیر-شهریور)
|
||||
|
||||
```
|
||||
Sprint 4 (تیر):
|
||||
├── L3: Monitoring
|
||||
├── L4: Log Aggregation
|
||||
└── L2: API Versioning
|
||||
|
||||
Sprint 5 (مرداد):
|
||||
├── L5: Product Compare
|
||||
├── L6: Wishlist
|
||||
└── L7: Email Templates
|
||||
|
||||
Sprint 6 (شهریور):
|
||||
├── L8: Refund System
|
||||
├── Performance Optimization
|
||||
└── Security Audit
|
||||
```mermaid
|
||||
gantt
|
||||
title Q2 1404 — تیر تا شهریور
|
||||
dateFormat YYYY-MM-DD
|
||||
section Sprint 4 تیر
|
||||
L3 Monitoring :d1, 2025-06-22, 3d
|
||||
L4 Log Aggregation :d2, after d1, 3d
|
||||
L2 API Versioning :d3, after d2, 2d
|
||||
section Sprint 5 مرداد
|
||||
L5 Product Compare :e1, 2025-07-23, 2d
|
||||
L6 Wishlist :e2, after e1, 2d
|
||||
L7 Email Templates :e3, after e2, 2d
|
||||
section Sprint 6 شهریور
|
||||
L8 Refund System :f1, 2025-08-23, 5d
|
||||
Performance Optimization :f2, after f1, 3d
|
||||
Security Audit :f3, after f2, 3d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -22,30 +22,38 @@
|
||||
|
||||
## ۲. معماری لایهای CMS
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Presentation Layer │
|
||||
│ FrontOffice (Blazor Server) ←─gRPC─→ CMS │
|
||||
│ BackOffice (Blazor WASM) ←─gRPC─→ CMS │
|
||||
├──────────────────────────────────────────────────────┤
|
||||
│ Application Layer │
|
||||
│ Commands (MediatR IRequest<T>) │
|
||||
│ Queries (MediatR IRequest<T>) │
|
||||
│ Validators (FluentValidation) │
|
||||
│ Handlers (IRequestHandler<TReq, TRes>) │
|
||||
├──────────────────────────────────────────────────────┤
|
||||
│ Domain Layer │
|
||||
│ Entities, Enums, Value Objects │
|
||||
│ Domain Events, Interfaces │
|
||||
├──────────────────────────────────────────────────────┤
|
||||
│ Infrastructure Layer │
|
||||
│ EF Core DbContext (CMSDbContext) │
|
||||
│ Repositories, External Services │
|
||||
│ Hangfire Jobs, File Storage │
|
||||
├──────────────────────────────────────────────────────┤
|
||||
│ Database │
|
||||
│ SQL Server — Schema: [CMS] │
|
||||
└──────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph PRES["💻 Presentation Layer"]
|
||||
FO["FrontOffice\nBlazor Server"]
|
||||
BO["BackOffice\nBlazor WASM"]
|
||||
end
|
||||
|
||||
FO & BO -->|gRPC| APP
|
||||
|
||||
subgraph APP["⚙️ Application Layer"]
|
||||
CMD["Commands\nMediatR IRequest"]
|
||||
QRY["Queries\nMediatR IRequest"]
|
||||
VAL["Validators\nFluentValidation"]
|
||||
HND["Handlers\nIRequestHandler"]
|
||||
end
|
||||
|
||||
APP --> DOM
|
||||
|
||||
subgraph DOM["📦 Domain Layer"]
|
||||
ENT["Entities, Enums\nValue Objects\nDomain Events"]
|
||||
end
|
||||
|
||||
DOM --> INF
|
||||
|
||||
subgraph INF["🔧 Infrastructure Layer"]
|
||||
EF["EF Core DbContext"]
|
||||
SVC["External Services"]
|
||||
HF["Hangfire Jobs"]
|
||||
FS["File Storage"]
|
||||
end
|
||||
|
||||
INF --> DB[("🗄️ SQL Server\nSchema: CMS")]
|
||||
```
|
||||
|
||||
---
|
||||
@@ -191,22 +199,22 @@ Engine: MSSQL 2022-CU16, Collation=Arabic_CI_AS
|
||||
|
||||
### ۶.۱ قبل vs بعد
|
||||
|
||||
```
|
||||
قبل:
|
||||
FrontOffice → BFF (REST) → CMS (gRPC)
|
||||
BackOffice → BFF (REST) → CMS (gRPC)
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph BEFORE["قبل"]
|
||||
F1["FrontOffice"] -->|REST| BFF1["BFF"]
|
||||
B1["BackOffice"] -->|REST| BFF1
|
||||
BFF1 -->|gRPC| C1["CMS"]
|
||||
end
|
||||
|
||||
بعد (فعلی):
|
||||
FrontOffice → CMS (gRPC مستقیم)
|
||||
BackOffice → CMS (gRPC مستقیم)
|
||||
|
||||
مزایا:
|
||||
✅ حذف لایه واسط → کاهش latency
|
||||
✅ حذف maintenance اضافی
|
||||
✅ Type-safe از proto تا UI
|
||||
✅ کاهش ۱ سرویس در deployment
|
||||
subgraph AFTER["بعد — فعلی ✅"]
|
||||
F2["FrontOffice"] -->|gRPC| C2["CMS"]
|
||||
B2["BackOffice"] -->|gRPC| C2
|
||||
end
|
||||
```
|
||||
|
||||
> مزایا: حذف لایه واسط → کاهش latency • Type-safe از proto تا UI • کاهش ۱ سرویس در deployment
|
||||
|
||||
### ۶.۲ سازگاری API
|
||||
|
||||
```
|
||||
|
||||
@@ -214,21 +214,21 @@ jobs:
|
||||
|
||||
### ۵.۱ فلوی آمادهسازی
|
||||
|
||||
```
|
||||
سرور اینترنتدار:
|
||||
1. pull-base-images.sh → دانلود Docker images
|
||||
2. cache-nuget-packages.sh → دانلود NuGet packages
|
||||
3. save-images.sh → ذخیره تصاویر به tar
|
||||
4. بستهبندی همه فایلها
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph ONLINE["🌐 سرور اینترنتدار"]
|
||||
A1["pull-base-images.sh\nدانلود Docker images"] --> A2["cache-nuget-packages.sh\nدانلود NuGet packages"]
|
||||
A2 --> A3["save-images.sh\nذخیره تصاویر به tar"]
|
||||
A3 --> A4["بستهبندی"]
|
||||
end
|
||||
|
||||
انتقال فیزیکی (USB/HDD):
|
||||
tar files + nuget packages + k8s manifests
|
||||
A4 -->|"💾 انتقال فیزیکی\nUSB / HDD"| B1
|
||||
|
||||
سرور آفلاین:
|
||||
1. load-images.sh → بارگذاری تصاویر
|
||||
2. setup-nexus-complete.sh → راهاندازی Nexus (NuGet proxy)
|
||||
3. build-all-offline.sh → بیلد با Nexus محلی
|
||||
4. k8s-deploy.sh → استقرار در Kubernetes
|
||||
subgraph OFFLINE["🔒 سرور آفلاین"]
|
||||
B1["load-images.sh\nبارگذاری تصاویر"] --> B2["setup-nexus-complete.sh\nراهاندازی Nexus"]
|
||||
B2 --> B3["build-all-offline.sh\nبیلد با Nexus محلی"]
|
||||
B3 --> B4["k8s-deploy.sh\nاستقرار در K8s"]
|
||||
end
|
||||
```
|
||||
|
||||
### ۵.۲ اسکریپتهای کلیدی
|
||||
@@ -250,12 +250,12 @@ jobs:
|
||||
|
||||
### ۶.۱ نقش
|
||||
|
||||
```
|
||||
Nexus (داخلی):
|
||||
├── NuGet proxy → cache.nuget.org packages
|
||||
├── NuGet hosted → بستههای proto داخلی
|
||||
├── Docker proxy → cache Docker Hub images
|
||||
└── Docker hosted → تصاویر داخلی FourSat
|
||||
```mermaid
|
||||
graph TD
|
||||
NEXUS["Nexus داخلی"] --> NP["NuGet proxy\ncache nuget.org"]
|
||||
NEXUS --> NH["NuGet hosted\nبستههای proto داخلی"]
|
||||
NEXUS --> DP["Docker proxy\ncache Docker Hub"]
|
||||
NEXUS --> DH["Docker hosted\nتصاویر داخلی FourSat"]
|
||||
```
|
||||
|
||||
### ۶.۲ NuGet.config
|
||||
@@ -303,17 +303,11 @@ Proto packages: BaGet (internal) at http://localhost:5555
|
||||
|
||||
### ۸.۱ فلوی بستهبندی
|
||||
|
||||
```
|
||||
CMS/src/Protos/*.proto
|
||||
│
|
||||
▼
|
||||
pack-protos.sh → dotnet pack → .nupkg
|
||||
│
|
||||
▼
|
||||
push to BaGet/Nexus
|
||||
│
|
||||
▼
|
||||
BackOffice + FrontOffice → dotnet restore → مصرف proto
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["CMS/src/Protos/*.proto"] --> B["pack-protos.sh\ndotnet pack → .nupkg"]
|
||||
B --> C["Push to BaGet / Nexus"]
|
||||
C --> D["BackOffice + FrontOffice\ndotnet restore → مصرف proto"]
|
||||
```
|
||||
|
||||
### ۸.۲ نام بسته
|
||||
|
||||
@@ -23,30 +23,24 @@ Timeline:
|
||||
|
||||
### ۲.۱ قبل
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
FO1["FrontOffice"] -->|HTTP/REST| BFF["BFF"]
|
||||
BO1["BackOffice"] -->|HTTP/REST| BFF
|
||||
BFF -->|gRPC| CMS1["CMS"]
|
||||
```
|
||||
FrontOffice ──HTTP/REST──→ BFF ──gRPC──→ CMS
|
||||
BackOffice ──HTTP/REST──→ BFF ──gRPC──→ CMS
|
||||
|
||||
BFF مسئولیتها:
|
||||
• تبدیل REST↔gRPC
|
||||
• Aggregation
|
||||
• Auth proxy
|
||||
• Rate limiting
|
||||
```
|
||||
**BFF مسئولیتها:** تبدیل REST↔gRPC • Aggregation • Auth proxy • Rate limiting
|
||||
|
||||
### ۲.۲ بعد (فعلی)
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
FO2["FrontOffice"] -->|gRPC| CMS2["CMS مستقیم"]
|
||||
BO2["BackOffice"] -->|gRPC| CMS2
|
||||
```
|
||||
FrontOffice ──gRPC──→ CMS (مستقیم)
|
||||
BackOffice ──gRPC──→ CMS (مستقیم)
|
||||
|
||||
مزایا:
|
||||
✅ حذف ۱ سرویس از deployment
|
||||
✅ کاهش ~50ms latency per request
|
||||
✅ Type-safety از proto تا UI
|
||||
✅ سادهسازی debug و logging
|
||||
✅ کاهش maintenance cost
|
||||
```
|
||||
**مزایا:** ✅ حذف ۱ سرویس • کاهش ~50ms latency • Type-safety از proto تا UI • سادهسازی debug
|
||||
|
||||
### ۲.۳ مراحل مهاجرت
|
||||
|
||||
@@ -78,18 +72,22 @@ BackOffice ──gRPC──→ CMS (مستقیم)
|
||||
|
||||
### ۳.۱ قبل
|
||||
|
||||
```
|
||||
Client → nginx → Ocelot Gateway → { CMS, BFF, FileService }
|
||||
↑
|
||||
URL routing, rate limiting, auth
|
||||
```mermaid
|
||||
flowchart LR
|
||||
CL1["Client"] --> NG1["nginx"] --> OC["Ocelot Gateway"]
|
||||
OC --> CMS3["CMS"]
|
||||
OC --> BFF2["BFF"]
|
||||
OC --> FS1["FileService"]
|
||||
```
|
||||
|
||||
### ۳.۲ بعد
|
||||
|
||||
```
|
||||
Client → nginx → Ingress → { CMS, BackOffice, FrontOffice }
|
||||
↑
|
||||
Path-based routing in Ingress
|
||||
```mermaid
|
||||
flowchart LR
|
||||
CL2["Client"] --> NG2["nginx"] --> ING["K8s Ingress"]
|
||||
ING --> CMS4["CMS"]
|
||||
ING --> BO3["BackOffice"]
|
||||
ING --> FO3["FrontOffice"]
|
||||
```
|
||||
|
||||
### ۳.۳ دلایل حذف
|
||||
|
||||
@@ -294,21 +294,12 @@ public class ProductService : IProductService
|
||||
|
||||
## ۵. Proto Package Distribution
|
||||
|
||||
```
|
||||
CMS/src/Protos/*.proto
|
||||
│
|
||||
▼
|
||||
pack-protos.sh
|
||||
│
|
||||
▼
|
||||
Foursat.CMSMicroservice.Protobuf.nupkg (v1.0.x)
|
||||
│
|
||||
▼
|
||||
Push to BaGet (http://localhost:5555) or Nexus
|
||||
│
|
||||
▼
|
||||
BackOffice: <PackageReference Include="Foursat.CMSMicroservice.Protobuf" />
|
||||
FrontOffice: <PackageReference Include="Foursat.CMSMicroservice.Protobuf" />
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["CMS/src/Protos/*.proto"] --> B["pack-protos.sh"]
|
||||
B --> C["Foursat.CMSMicroservice.Protobuf.nupkg\nv1.0.x"]
|
||||
C --> D["Push to BaGet / Nexus"]
|
||||
D --> E["BackOffice + FrontOffice\nPackageReference"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user