3c729304db
Corrections verified against actual CMS/BackOffice/FrontOffice source code: - ClubActivationFee: 25,200,000 (not 25,000,000) - Tree depth: no limit (15 is commission calculation depth only) - IPG wallet charge: Balance=56M + Discount=56M - DayaLoan wallet charge: Balance=56M + Discount=112M (2×) - Discount: per-product MaxDiscountPercent (not fixed 30%) - VAT: 10% (ShopVAT) vs 9% (discount store PlaceOrder) - Kavenegar template: 'Afrino' only (not verify-foursat) - SMS sender: 1000001110100 - DayaLoan job: every 20min (not 15min) - Commission job: Sunday 00:05 (not Saturday) - Network tree: on User entity (not separate NetworkNode table) - UserWallets entity (not UserWalletBalances) - OTP: 6 digits, 5 attempts, 2min TTL, 60s cooldown - Removed non-existent constants (ClubJoiningPercentage, ClubActivationThreshold) - Fixed Hangfire Chatika interval: every 5min - Removed InventorySync from recurring jobs list
9.0 KiB
9.0 KiB
⚙️ معماری CMS و زیرساخت فنی
منابع ادغامشده:
CMS-README.md,ICURRENTUSERSERVICE-IMPLEMENTATION.md,FILE-MANAGEMENT-ARCHITECTURE.md,FRONTOFFICE-CMS-API-COMPATIBILITY.md,BFF-REMOVAL-PLAN.md,system-constants.md
آخرین بروزرسانی: اسفند ۱۴۰۴
۱. Stack فنی
| لایه | تکنولوژی | نسخه |
|---|---|---|
| Runtime | .NET | 9.0 |
| ORM | Entity Framework Core | 9.0 |
| Communication | gRPC (Protobuf) | v3 |
| Pattern | CQRS + MediatR | — |
| Database | SQL Server (MSSQL) | 2022-CU16 |
| Job Scheduler | Hangfire | — |
| Auth | JWT Bearer + Identity | — |
| API Gateway | حذفشده (Direct gRPC) | — |
۲. معماری لایهای 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] │
└──────────────────────────────────────────────────────┘
۳. CQRS با MediatR
۳.۱ ساختار فولدرها
CMS/src/
├── CMSMicroservice/
│ ├── Features/
│ │ ├── Products/
│ │ │ ├── Commands/
│ │ │ │ ├── CreateProductCommand.cs
│ │ │ │ └── CreateProductCommandHandler.cs
│ │ │ ├── Queries/
│ │ │ │ ├── GetProductsQuery.cs
│ │ │ │ └── GetProductsQueryHandler.cs
│ │ │ └── Validators/
│ │ │ └── CreateProductCommandValidator.cs
│ │ ├── Orders/
│ │ ├── Users/
│ │ ├── Club/
│ │ ├── Payment/
│ │ └── Blog/
│ ├── Services/
│ │ ├── gRPC/ ← gRPC service implementations
│ │ ├── Background/ ← Hangfire jobs
│ │ └── External/ ← ZarinPal, Kavenegar, Daya, Chatika
│ ├── Infrastructure/
│ │ ├── Persistence/ ← DbContext, Migrations
│ │ └── Identity/ ← JWT, Claims, ICurrentUserService
│ └── Protos/ ← .proto files
۳.۲ مثال Command
// Command
public record CreateProductCommand(
string Name, string Description, decimal Price,
Guid CategoryId, string ImageUrl
) : IRequest<Guid>;
// Handler
public class CreateProductCommandHandler
: IRequestHandler<CreateProductCommand, Guid>
{
private readonly CMSDbContext _db;
public async Task<Guid> Handle(
CreateProductCommand request, CancellationToken ct)
{
var product = new Product { /* map fields */ };
_db.Products.Add(product);
// Auto-create inventory record
_db.Inventories.Add(new Inventory { ProductId = product.Id });
await _db.SaveChangesAsync(ct);
return product.Id;
}
}
۴. gRPC Services
۴.۱ لیست سرویسها
| سرویس | proto | متدهای اصلی |
|---|---|---|
ProductService |
product.proto | GetProducts, GetProduct, Create, Update, Delete |
OrderService |
order.proto | CreateOrder, GetOrders, UpdateStatus |
UserService |
user.proto | Register, Login, GetProfile, UpdateProfile |
ClubService |
club.proto | GetNetworkTree, GetBalance, AcceptContract |
PaymentService |
payment.proto | CreatePayment, VerifyPayment |
BlogService |
blog.proto | GetPosts, GetPost, Create, Update |
InventoryService |
inventory.proto | GetInventory, UpdateStock |
FileService |
file.proto | Upload, Download, Delete |
SitePageService |
sitepage.proto | GetPage, SaveSettings |
CategoryService |
category.proto | GetCategories, Create, Update |
SystemConfigService |
config.proto | GetConfig, UpdateConfig |
۴.۲ PaginationState (مشترک)
message PaginationState {
int32 skip = 1;
int32 take = 2;
}
Namespace صحیح:
using CMSMicroservice.Protobuf.Protos.PaginationState;
// ⚠️ نه: CMSMicroservice.Protobuf.Protos.PublicMessages.PaginationState
۵. Database
۵.۱ اتصال
Staging: Server=194.5.195.53; Database=FourSatCMS; Schema=CMS
Production: Server=45.149.79.127; Database=FourSatCMS; Schema=CMS
Engine: MSSQL 2022-CU16, Collation=Arabic_CI_AS
۵.۲ جداول اصلی
| جدول | توضیح | رکوردهای تقریبی |
|---|---|---|
| Users | کاربران + فیلدهای شبکه (NetworkParentId, LegPosition) | ~5K |
| Products | محصولات (+ MaxDiscountPercent) | ~200 |
| Categories | دستهبندیها | ~30 |
| Orders | سفارشات | ~2K |
| Inventories | موجودی | ~200 |
| BlogPosts | پستهای بلاگ | ~50 |
| SitePages | صفحات سایت | ~10 |
| UserClubMemberships | عضویت باشگاه | ~500 |
| UserContracts | قراردادها (SignGuid, SignedPdfFile) | ~500 |
| UserWallets | کیفپول (Balance, NetworkBalance, DiscountBalance) | ~5K |
| Transactions | تراکنشها | ~5K |
| SystemConfigurations | تنظیمات | ~30 |
| ChatMessages | پیامهای چاتیکا | ~1K |
۵.۳ Stored Procedures
| SP | کاربرد |
|---|---|
SP_GetNetworkTree |
بازگشتی — استخراج درخت باینری |
sp_CalculateWeeklyBalances |
محاسبه بالانس هفتگی هر عضو |
sp_CalculateWeeklyCommissionPool |
توزیع Pool هفتگی |
۶. حذف BFF / Gateway
۶.۱ قبل vs بعد
قبل:
FrontOffice → BFF (REST) → CMS (gRPC)
BackOffice → BFF (REST) → CMS (gRPC)
بعد (فعلی):
FrontOffice → CMS (gRPC مستقیم)
BackOffice → CMS (gRPC مستقیم)
مزایا:
✅ حذف لایه واسط → کاهش latency
✅ حذف maintenance اضافی
✅ Type-safe از proto تا UI
✅ کاهش ۱ سرویس در deployment
۶.۲ سازگاری API
FrontOffice Service Layer:
• ProductService.cs → gRPC client wrapper
• OrderService.cs → gRPC client wrapper
• UserService.cs → gRPC client wrapper
هر Service:
• Constructor: inject GrpcChannel
• Methods: wrap gRPC calls + map to DTOs
• Error handling: try/catch RpcException
۷. Hangfire Jobs
| Job | فرکانس (cron) | کاربرد |
|---|---|---|
WeeklyCommissionCalculation |
5 0 * * 0 (یکشنبه ۰۰:۰۵) |
محاسبه و توزیع کمیسیون |
DayaLoanProcessorJob |
*/20 * * * * (هر ۲۰ دقیقه) |
پردازش درخواستهای وام |
ChatikaAccountActivation |
*/5 * * * * (هر ۵ دقیقه) |
فعالسازی حساب چاتیکا |
۸. پیکربندی
۸.۱ appsettings.json ساختار
{
"ConnectionStrings": {
"DefaultConnection": "Server=...;Database=FourSatCMS"
},
"Jwt": {
"Secret": "***",
"Issuer": "FourSat",
"ExpiryMinutes": 1440
},
"Grpc": {
"CmsUrl": "https://localhost:5001"
},
"Hangfire": {
"DashboardPath": "/hangfire",
"WorkerCount": 4
},
"Kavenegar": { "ApiKey": "***" },
"ZarinPal": { "MerchantId": "***" },
"DayaLoan": { "UseMock": true }
}