Files
docs/technical/TECH-01-CMS-ARCHITECTURE.md
T
masoodafar-web 3c729304db docs: fix all discrepancies based on comprehensive code audit
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
2026-02-18 22:58:40 +03:30

9.0 KiB
Raw Blame History

⚙️ معماری 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 }
}