Files
docs/business/BUSINESS-03-ECOMMERCE-STORES.md
T
masoodafar-web c78850f86e docs: update BUSINESS-02, BUSINESS-03, TECH-03
BUSINESS-02:
- فرمول هایبرید: حذف MIN، اضافه validation کیف‌پول اعتباری
- فلوی خرید: اضافه مرحله بررسی موجودی + UserWalletChangeLog
- نام‌گذاری جدید کیف‌پول‌ها: اصلی، اعتباری، پاداش تیمی
- جدول وضعیت: اضافه WalletChangeLog + Validation

BUSINESS-03:
- بخش ۹ جدید: ExpirePendingOrdersService (۱۵ دقیقه)
- دیاگرام Mermaid فلوی انقضا

TECH-03:
- فیکس URL پروداکشن (kbs1→kbs2) + هشدار
- ۴ کامیت جدید در بخش ۹.۲
- بخش ۹.۳ فیکس URL پروداکشن
- بخش ۹.۴ نام‌گذاری کیف‌پول‌ها
2026-02-24 00:29:03 +03:30

8.4 KiB
Raw Blame History

🛒 فروشگاه، موجودی و محصولات

منابع ادغام‌شده: discount-shop-business.md, DISCOUNT-STORE-STATUS.md, package-purchase-system.md, INVENTORY-IMPROVEMENTS.md, INVENTORY-REFACTORING-STATUS.md, PRODUCT-BUNDLE-FEATURE.md, SHOP-UNIFICATION.md
آخرین بروزرسانی: اسفند ۱۴۰۴ (بروزرسانی: ExpirePendingOrders ۱۵ دقیقه + فروشگاه اعتباری نام‌گذاری)


۱. دو فروشگاه FourSat

flowchart LR
    subgraph RS["Regular Store — /store"]
        R1["همه کاربران"]
        R2["پرداخت از Balance کیف‌پول"]
        R3["قیمت عادی"]
        R4["VAT = 10%"]
    end

    subgraph DS["Discount Store — /discount-store"]
        D1["فقط اعضای باشگاه"]
        D2["پرداخت ترکیبی تخفیف+نقد"]
        D3["تخفیف بر اساس MaxDiscountPercent"]
        D4["VAT = 10%"]
    end

    subgraph SHARED["مشترک"]
        S1["Products"]
        S2["Categories"]
        S3["Inventory"]
        S4["ProductImages 1:1"]
    end

    RS --> SHARED
    DS --> SHARED

۲. Lazy Loading محصولات

۲.۱ API

// ProductService.cs
public record ProductListResult(List<ProductDto> Products, int TotalCount);

public async Task<ProductListResult> GetProductsPagedAsync(
    int skip, int take, 
    Guid? categoryId = null, 
    string? search = null)
{
    var request = new GetProductsRequest {
        Pagination = new PaginationState { Skip = skip, Take = take },
        CategoryId = categoryId?.ToString() ?? "",
        SearchTerm = search ?? ""
    };
    // gRPC call...
}

۲.۲ پیاده‌سازی UI (هر دو فروشگاه)

flowchart TD
    A["بارگذاری اولیه: 12 محصول"] --> B["اسکرول → نمایش دکمه\nنمایش محصولات بیشتر"]
    B --> C["کلیک → LoadMore\nskip += 12"]
    C --> D["محصولات جدید append به لیست"]
    D --> E{"Products.Count >= TotalCount?"}
    E -->|خیر| B
    E -->|بله| F["مخفی‌شدن دکمه"]

۳. مدیریت موجودی (Inventory)

۳.۱ بهبودهای اخیر

بهبود توضیح وضعیت
Auto-Create ایجاد خودکار رکورد موجودی هنگام ساخت محصول
Hangfire Worker InventorySyncJob — بررسی دوره‌ای و ایجاد رکوردهای گمشده
Autocomplete جستجوی محصول در صفحه موجودی BackOffice با autocomplete
Lazy Load بارگذاری تنبل محصولات در هر دو فروشگاه

۳.۲ Entity ها

public class Inventory {
    public Guid Id { get; set; }
    public Guid ProductId { get; set; }         // FK → Product
    public int Quantity { get; set; }            // موجودی فعلی
    public int ReservedQuantity { get; set; }    // رزرو‌شده
    public int MinimumStock { get; set; }        // حداقل موجودی (هشدار)
    public bool TrackInventory { get; set; }     // آیا موجودی رصد شود؟
}

// فیلد کلیدی در Product:
public int MaxDiscountPercent { get; set; }  // 0 تا 100 — درصد تخفیف در فروشگاه اعتباری

۳.۳ فلوی سفارش و موجودی

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["نمایش: موجودی کافی نیست"]

۴. تصاویر محصول (۱:۱ مربعی)

AppImage Component (Shared):
    • ObjectFit = Cover
    • AspectRatio = 1:1 (مربع)
    • Fallback = آیکون پیش‌فرض MudBlazor
    • LazyLoading = true
    
اعمال در:
    ✅ Regular Store — ProductCard
    ✅ Discount Store — ProductCard
    ✅ BackOffice — Product List
    ✅ Product Detail Pages

۵. باندل محصولات (Product Bundle)

⚠️ وضعیت: طراحی کامل — پیاده‌سازی نشده

۵.۱ مدل داده

public class ProductBundle {
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal OriginalPrice { get; set; }    // مجموع قیمت تکی
    public decimal BundlePrice { get; set; }       // قیمت باندل
    public decimal DiscountPercentage { get; set; }
    public bool IsActive { get; set; }
    public List<BundleItem> Items { get; set; }
}

public class BundleItem {
    public Guid ProductId { get; set; }
    public int Quantity { get; set; }
}

۵.۲ فلو

flowchart TD
    A["ادمین → ساخت باندل\nانتخاب محصولات + تعیین قیمت"] --> B["نمایش در فروشگاه\nبا تگ باندل"]
    B --> C["خرید → تمام محصولات\nیکجا به سبد"]
    C --> D["پرداخت → کسر موجودی\nهر محصول جداگانه"]

۶. یکپارچه‌سازی فروشگاه‌ها (Shop Unification)

۶.۱ اجزای مشترک

کامپوننت کاربرد وضعیت
ProductCard کارت محصول (۱:۱) مشترک
AppImage نمایش تصویر مشترک
CategoryFilter فیلتر دسته‌بندی مشترک
SearchBar جستجوی محصول مشترک
LoadMoreButton Lazy loading مشترک
CartSummary خلاصه سبد جداگانه

۶.۲ مسیرهای Navigation

فروشگاه عادی:
  /store                    → لیست محصولات
  /store/product/{id}       → جزئیات محصول
  /store/cart               → سبد خرید
  /store/checkout            → پرداخت

فروشگاه اعتباری:
  /discount-store            → لیست محصولات
  /discount-store/product/{id} → جزئیات
  /discount-store/cart        → سبد (ترکیبی)
  /discount-store/checkout    → پرداخت ترکیبی

۷. دسته‌بندی‌ها (Categories)

graph TD
    ROOT["دسته‌بندی‌ها"] --> A["سلامت و زیبایی"]
    ROOT --> B["تغذیه"]
    ROOT --> C["ورزشی"]

    A --> A1["مکمل‌ها"]
    A --> A2["مراقبت پوست"]
    A --> A3["مراقبت مو"]

    B --> B1["ارگانیک"]
    B --> B2["رژیمی"]

مدل: Category (Id, Name, ParentId?, ImageUrl, IsActive, SortOrder)


۸. خلاصه وضعیت

ماژول وضعیت درصد
فروشگاه عادی کامل 100%
فروشگاه اعتباری کامل 100%
Lazy Loading کامل 100%
موجودی خودکار کامل 100%
تصاویر مربعی کامل 100%
انقضای سفارشات Pending کامل 100%
باندل محصولات طراحی 30%
مقایسه محصول ایده 0%

۹. انقضای خودکار سفارشات Pending (ExpirePendingOrdersService)

سرویس پس‌زمینه‌ای که سفارشات فروشگاه اعتباری را بعد از ۱۵ دقیقه منقضی می‌کند.

۹.۱ پارامترها

پارامتر مقدار توضیح
ExpirationTime ۱۵ دقیقه مدت زمان مجاز برای پرداخت
CheckInterval ۵ دقیقه فاصله بررسی

۹.۲ عملکرد

flowchart TD
    A["هر ۵ دقیقه\nExpirePendingOrdersService"] --> B["جستجوی DiscountOrders\nPaymentStatus=Pending\nCreated < (now - 15 min)"]
    B --> C{"سفارشی یافت شد?"}
    C -->|خیر| A
    C -->|بله| D["آزادسازی رزرو موجودی\nReleaseReservationAsync"]
    D --> E["PaymentStatus → Reject\nDeliveryStatus → Cancelled"]
    E --> F["Transaction.PaymentStatus → Reject"]
    F --> G["Log: Expired order #X"]
    G --> A

۹.۳ فایل

CMS/src/CMSMicroservice.Infrastructure/BackgroundServices/ExpirePendingOrdersService.cs

رجیستر شده در ConfigureServices.cs:

services.AddHostedService<ExpirePendingOrdersService>();