c78850f86e
BUSINESS-02: - فرمول هایبرید: حذف MIN، اضافه validation کیفپول اعتباری - فلوی خرید: اضافه مرحله بررسی موجودی + UserWalletChangeLog - نامگذاری جدید کیفپولها: اصلی، اعتباری، پاداش تیمی - جدول وضعیت: اضافه WalletChangeLog + Validation BUSINESS-03: - بخش ۹ جدید: ExpirePendingOrdersService (۱۵ دقیقه) - دیاگرام Mermaid فلوی انقضا TECH-03: - فیکس URL پروداکشن (kbs1→kbs2) + هشدار - ۴ کامیت جدید در بخش ۹.۲ - بخش ۹.۳ فیکس URL پروداکشن - بخش ۹.۴ نامگذاری کیفپولها
8.4 KiB
8.4 KiB
🛒 فروشگاه، موجودی و محصولات
منابع ادغامشده:
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>();