update
This commit is contained in:
@@ -0,0 +1,750 @@
|
||||
# Club Discount Shop System - سیستم فروشگاه باشگاه مشتریان با تخفیف ترکیبی
|
||||
|
||||
**تاریخ ایجاد:** 2024-12-02
|
||||
**تاریخ آپدیت:** 2024-12-02
|
||||
**وضعیت:** طراحی (Phase 9)
|
||||
**اولویت:** 🔴 بالا (یکی از دو فاز باقیمانده)
|
||||
|
||||
---
|
||||
|
||||
## 📋 فهرست
|
||||
|
||||
1. [مقدمه](#مقدمه)
|
||||
2. [مفهوم اصلی: پرداخت ترکیبی](#مفهوم-اصلی-پرداخت-ترکیبی)
|
||||
3. [تفاوت با Regular Shop](#تفاوت-با-regular-shop)
|
||||
4. [معماری جداسازی](#معماری-جداسازی)
|
||||
5. [Entity Design](#entity-design)
|
||||
6. [Business Rules](#business-rules)
|
||||
7. [تسکهای پیادهسازی](#تسک-های-پیاده-سازی)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 مقدمه
|
||||
|
||||
### هدف:
|
||||
ایجاد **فروشگاه باشگاه مشتریان** که در آن کاربران میتوانند با **پرداخت ترکیبی** خرید کنند:
|
||||
|
||||
**🔑 قانون اصلی**:
|
||||
- کاربر **نمیتواند** کل محصول را فقط با `DiscountBalance` بخرد
|
||||
- کاربر میتواند **درصدی از قیمت** را با `DiscountBalance` پرداخت کند
|
||||
- **مابقی مبلغ** باید از طریق **درگاه پرداخت واقعی در Gateway/PYMS** پرداخت شود (نه در CMS)
|
||||
|
||||
### مثال عملی:
|
||||
```
|
||||
قیمت محصول: 1,000,000 تومان
|
||||
حداکثر تخفیف مجاز: 30%
|
||||
DiscountBalance کاربر: 500,000 تومان
|
||||
|
||||
محاسبه:
|
||||
- حداکثر تخفیف قابل استفاده: 1,000,000 × 30% = 300,000 تومان
|
||||
- DiscountBalance کاربر: 500,000 تومان (بیشتر از 300,000)
|
||||
- مبلغ تخفیف نهایی: 300,000 تومان (محدود به 30%)
|
||||
- مبلغ قابل پرداخت از درگاه: 1,000,000 - 300,000 = 700,000 تومان
|
||||
|
||||
نتیجه:
|
||||
✅ کسر از DiscountBalance: 300,000 تومان
|
||||
✅ پرداخت از درگاه: 700,000 تومان
|
||||
✅ DiscountBalance باقیمانده: 200,000 تومان
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 مفهوم اصلی: پرداخت ترکیبی
|
||||
|
||||
### Flow خرید:
|
||||
|
||||
```
|
||||
1. کاربر محصول را انتخاب میکند
|
||||
2. سیستم چک میکند:
|
||||
- قیمت محصول: X تومان
|
||||
- حداکثر تخفیف مجاز: Y%
|
||||
- DiscountBalance کاربر: Z تومان
|
||||
|
||||
3. محاسبه تخفیف:
|
||||
MaxDiscountAmount = X × (Y / 100)
|
||||
ActualDiscountAmount = Min(Z, MaxDiscountAmount)
|
||||
|
||||
4. محاسبه مبلغ درگاه:
|
||||
GatewayAmount = X - ActualDiscountAmount
|
||||
|
||||
5. ریدایرکت به درگاه پرداخت (GatewayAmount)
|
||||
|
||||
6. بعد از بازگشت موفق از درگاه:
|
||||
- Verify payment از درگاه
|
||||
- کسر ActualDiscountAmount از DiscountBalance
|
||||
- ثبت سفارش با دو مبلغ جدا
|
||||
- ارسال اطلاعیه به کاربر
|
||||
```
|
||||
|
||||
### مزایا:
|
||||
✅ کاربر نمیتواند کل محصول را با تخفیف بخرد (محدودیت درصد)
|
||||
✅ کاربر میتواند از موجودی تخفیف خود استفاده کند
|
||||
✅ فروشنده مطمئن است مبلغی واقعی دریافت میکند
|
||||
✅ سیستم از سوءاستفاده جلوگیری میکند
|
||||
|
||||
---
|
||||
|
||||
## 🔄 تفاوت با Regular Shop
|
||||
|
||||
| ویژگی | فروشگاه عادی (Regular) | فروشگاه تخفیفی (Club Discount) |
|
||||
|-------|------------------------|---------------------------|
|
||||
| **نوع کیف پول** | `UserWallet.Balance` | `UserWallet.DiscountBalance` + درگاه |
|
||||
| **نحوه پرداخت** | 100% از Balance یا IPG | **ترکیبی**: X% از DiscountBalance + مابقی از IPG |
|
||||
| **محدودیت تخفیف** | ندارد | **دارد** (MaxDiscountPercent per product) |
|
||||
| **نحوه شارژ** | خرید پکیج طلایی (56M) | کمیسیون برداشت Diamond |
|
||||
| **ارتباط با باشگاه** | ✅ دارد | ✅ دارد (اعضای باشگاه) |
|
||||
| **محصولات** | `Products` | `DiscountProduct` (یا flag در Products) |
|
||||
| **سفارش** | `UserOrder` | `DiscountOrder` (با دو مبلغ جدا) |
|
||||
| **پرداخت** | یک مرحلهای | **دو مرحلهای**: 1) Verify IPG، 2) Deduct DiscountBalance |
|
||||
| **TransactionType** | `DepositIpg` | `DiscountPurchase` (hybrid) |
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ معماری جداسازی
|
||||
|
||||
### اصل طراحی:
|
||||
> **"همه چیز جدا، جز درگاه پرداخت و کیف پول"**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ User │
|
||||
│ - Id │
|
||||
│ - FirstName, LastName, Mobile │
|
||||
│ - PackagePurchaseMethod │
|
||||
└────────────┬────────────────────────────────────────────────────┘
|
||||
│
|
||||
├──────────────────────────────────────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────────────────────────┐ ┌──────────────────────────┐
|
||||
│ UserWallet │ │ Transactions (مشترک) │
|
||||
│ - Balance │ │ - Type │
|
||||
│ - DiscountBalance │ │ - RefId │
|
||||
│ - NetworkBalance │ │ - Amount │
|
||||
└────────────┬───────────────┘ └──────────────────────────┘
|
||||
│
|
||||
├──────────────────────────────────────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────────────────────────┐ ┌──────────────────────────┐
|
||||
│ Regular Shop │ │ Discount Shop │
|
||||
│ - Products │ │ - DiscountProduct │
|
||||
│ - Category │ │ - DiscountCategory │
|
||||
│ - UserCarts │ │ - DiscountShoppingCart │
|
||||
│ - UserOrder │ │ - DiscountOrder │
|
||||
│ - FactorDetails │ │ - DiscountOrderDetail │
|
||||
└────────────────────────────┘ └──────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ Entity Design
|
||||
|
||||
### 1️⃣ `DiscountProduct`
|
||||
|
||||
```csharp
|
||||
namespace CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// محصول فروشگاه تخفیفی
|
||||
/// </summary>
|
||||
public class DiscountProduct : BaseAuditableEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// عنوان محصول
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// توضیحات مختصر
|
||||
/// </summary>
|
||||
public string ShortInfomation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// توضیحات کامل
|
||||
/// </summary>
|
||||
public string FullInformation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// قیمت (ریال)
|
||||
/// </summary>
|
||||
public long Price { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// درصد تخفیف
|
||||
/// </summary>
|
||||
public int DiscountPercent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// امتیاز (0 تا 5)
|
||||
/// </summary>
|
||||
public int Rate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آدرس تصویر اصلی
|
||||
/// </summary>
|
||||
public string ImagePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آدرس تصویر کوچک
|
||||
/// </summary>
|
||||
public string ThumbnailPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// تعداد فروش
|
||||
/// </summary>
|
||||
public int SaleCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// تعداد بازدید
|
||||
/// </summary>
|
||||
public int ViewCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// موجودی انبار
|
||||
/// </summary>
|
||||
public int RemainingCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// وضعیت فعال/غیرفعال
|
||||
/// </summary>
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
// Navigation Properties
|
||||
public virtual ICollection<DiscountShoppingCart> ShoppingCarts { get; set; }
|
||||
public virtual ICollection<DiscountOrderDetail> OrderDetails { get; set; }
|
||||
public virtual ICollection<DiscountProductCategory> ProductCategories { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2️⃣ `DiscountCategory`
|
||||
|
||||
```csharp
|
||||
namespace CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// دستهبندی فروشگاه تخفیفی
|
||||
/// </summary>
|
||||
public class DiscountCategory : BaseAuditableEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// نام لاتین (برای URL)
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// عنوان فارسی
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// توضیحات
|
||||
/// </summary>
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آدرس تصویر
|
||||
/// </summary>
|
||||
public string? ImagePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// شناسه والد (برای دستهبندی چند سطحی)
|
||||
/// </summary>
|
||||
public long? ParentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parent Navigation Property
|
||||
/// </summary>
|
||||
public virtual DiscountCategory? Parent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// فعال/غیرفعال
|
||||
/// </summary>
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ترتیب نمایش
|
||||
/// </summary>
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
// Navigation Properties
|
||||
public virtual ICollection<DiscountCategory> Children { get; set; }
|
||||
public virtual ICollection<DiscountProductCategory> ProductCategories { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3️⃣ `DiscountProductCategory` (Many-to-Many)
|
||||
|
||||
```csharp
|
||||
namespace CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// رابطه محصول و دستهبندی در فروشگاه تخفیفی
|
||||
/// </summary>
|
||||
public class DiscountProductCategory : BaseAuditableEntity
|
||||
{
|
||||
public long DiscountProductId { get; set; }
|
||||
public virtual DiscountProduct DiscountProduct { get; set; }
|
||||
|
||||
public long DiscountCategoryId { get; set; }
|
||||
public virtual DiscountCategory DiscountCategory { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4️⃣ `DiscountShoppingCart`
|
||||
|
||||
```csharp
|
||||
namespace CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// سبد خرید فروشگاه تخفیفی
|
||||
/// </summary>
|
||||
public class DiscountShoppingCart : BaseAuditableEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// شناسه کاربر
|
||||
/// </summary>
|
||||
public long UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User Navigation Property
|
||||
/// </summary>
|
||||
public virtual User User { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// شناسه محصول
|
||||
/// </summary>
|
||||
public long DiscountProductId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DiscountProduct Navigation Property
|
||||
/// </summary>
|
||||
public virtual DiscountProduct DiscountProduct { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// تعداد
|
||||
/// </summary>
|
||||
public int Count { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// قیمت واحد در زمان افزودن به سبد
|
||||
/// </summary>
|
||||
public long UnitPrice { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5️⃣ `DiscountOrder`
|
||||
|
||||
```csharp
|
||||
namespace CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// سفارش از فروشگاه تخفیفی
|
||||
/// </summary>
|
||||
public class DiscountOrder : BaseAuditableEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// شناسه کاربر
|
||||
/// </summary>
|
||||
public long UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User Navigation Property
|
||||
/// </summary>
|
||||
public virtual User User { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// مبلغ کل سفارش
|
||||
/// </summary>
|
||||
public long TotalAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// مبلغ تخفیف
|
||||
/// </summary>
|
||||
public long DiscountAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// مبلغ قابل پرداخت
|
||||
/// </summary>
|
||||
public long PayableAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// وضعیت پرداخت
|
||||
/// </summary>
|
||||
public PaymentStatus PaymentStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// تاریخ پرداخت
|
||||
/// </summary>
|
||||
public DateTime? PaymentDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// شناسه تراکنش (اگر پرداخت موفق باشد)
|
||||
/// </summary>
|
||||
public long? TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Transaction Navigation Property
|
||||
/// </summary>
|
||||
public virtual Transactions? Transaction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// شناسه آدرس کاربر
|
||||
/// </summary>
|
||||
public long UserAddressId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// UserAddress Navigation Property
|
||||
/// </summary>
|
||||
public virtual UserAddress UserAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// وضعیت ارسال
|
||||
/// </summary>
|
||||
public DeliveryStatus DeliveryStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// کد رهگیری مرسوله
|
||||
/// </summary>
|
||||
public string? TrackingCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// توضیحات وضعیت ارسال
|
||||
/// </summary>
|
||||
public string? DeliveryDescription { get; set; }
|
||||
|
||||
// Navigation Properties
|
||||
public virtual ICollection<DiscountOrderDetail> OrderDetails { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6️⃣ `DiscountOrderDetail`
|
||||
|
||||
```csharp
|
||||
namespace CMSMicroservice.Domain.Entities.DiscountShop;
|
||||
|
||||
/// <summary>
|
||||
/// جزئیات سفارش از فروشگاه تخفیفی
|
||||
/// </summary>
|
||||
public class DiscountOrderDetail : BaseAuditableEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// شناسه سفارش
|
||||
/// </summary>
|
||||
public long DiscountOrderId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DiscountOrder Navigation Property
|
||||
/// </summary>
|
||||
public virtual DiscountOrder DiscountOrder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// شناسه محصول
|
||||
/// </summary>
|
||||
public long DiscountProductId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DiscountProduct Navigation Property
|
||||
/// </summary>
|
||||
public virtual DiscountProduct DiscountProduct { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// تعداد
|
||||
/// </summary>
|
||||
public int Quantity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// قیمت واحد در زمان ثبت سفارش
|
||||
/// </summary>
|
||||
public long UnitPrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// درصد تخفیف در زمان ثبت سفارش
|
||||
/// </summary>
|
||||
public int DiscountPercent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// مبلغ کل این آیتم (بعد از تخفیف)
|
||||
/// </summary>
|
||||
public long TotalPrice { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📐 Business Rules
|
||||
|
||||
### قانون 1: خرید از Discount Shop فقط با DiscountBalance
|
||||
|
||||
```csharp
|
||||
// در زمان Checkout از Discount Shop:
|
||||
var wallet = await _context.UserWallets
|
||||
.FirstOrDefaultAsync(w => w.UserId == userId);
|
||||
|
||||
if (wallet.DiscountBalance < order.PayableAmount)
|
||||
{
|
||||
throw new ValidationException(
|
||||
$"موجودی کیف پول تخفیفی شما کافی نیست. " +
|
||||
$"موجودی فعلی: {wallet.DiscountBalance:N0} تومان، " +
|
||||
$"مبلغ مورد نیاز: {order.PayableAmount:N0} تومان"
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### قانون 2: خرید از Regular Shop فقط با Balance
|
||||
|
||||
```csharp
|
||||
// در زمان Checkout از Regular Shop:
|
||||
var wallet = await _context.UserWallets
|
||||
.FirstOrDefaultAsync(w => w.UserId == userId);
|
||||
|
||||
if (wallet.Balance < order.Amount)
|
||||
{
|
||||
throw new ValidationException(
|
||||
$"موجودی کیف پول اصلی شما کافی نیست. " +
|
||||
$"موجودی فعلی: {wallet.Balance:N0} تومان، " +
|
||||
$"مبلغ مورد نیاز: {order.Amount:N0} تومان"
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### قانون 3: شارژ DiscountBalance از طریق درگاه
|
||||
|
||||
```csharp
|
||||
// در VerifyDiscountWalletChargeCommand:
|
||||
wallet.DiscountBalance += amount;
|
||||
|
||||
var transaction = new Transactions
|
||||
{
|
||||
Type = TransactionType.DiscountWalletCharge,
|
||||
Amount = amount,
|
||||
RefId = verifyResult.RefId
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### قانون 4: محصولات Discount Shop جدا از Regular Shop
|
||||
|
||||
- یک محصول **نمیتواند** هم در `Products` باشد، هم در `DiscountProduct`
|
||||
- Admin باید محصولات را جداگانه مدیریت کند
|
||||
- هیچ رابطهای بین `Products` و `DiscountProduct` نیست
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Flow Diagram: خرید از Discount Shop
|
||||
|
||||
```
|
||||
کاربر → مشاهده محصولات Discount Shop
|
||||
↓
|
||||
افزودن به DiscountShoppingCart
|
||||
↓
|
||||
Checkout (بررسی DiscountBalance)
|
||||
↓
|
||||
ثبت DiscountOrder (PaymentStatus: Pending)
|
||||
↓
|
||||
کم کردن DiscountBalance از کیف پول
|
||||
↓
|
||||
ثبت Transaction (Type: Buy) ← این تراکنش برای خرید است
|
||||
↓
|
||||
ثبت DiscountOrderDetail برای هر محصول
|
||||
↓
|
||||
بهروزرسانی DiscountOrder (PaymentStatus: Success)
|
||||
↓
|
||||
خالی کردن DiscountShoppingCart
|
||||
↓
|
||||
نمایش پیام موفقیت + کد رهگیری
|
||||
```
|
||||
|
||||
**نکته:** در این فلو از درگاه استفاده **نمیشود** چون موجودی از قبل شارژ شده است.
|
||||
|
||||
---
|
||||
|
||||
## 📝 تسکهای پیادهسازی
|
||||
|
||||
### Phase 1: Entity Creation (2 روز)
|
||||
|
||||
1. **ایجاد namespace جدید**:
|
||||
- `CMSMicroservice.Domain/Entities/DiscountShop/`
|
||||
|
||||
2. **ایجاد Entityها**:
|
||||
- `DiscountProduct`
|
||||
- `DiscountCategory`
|
||||
- `DiscountProductCategory`
|
||||
- `DiscountShoppingCart`
|
||||
- `DiscountOrder`
|
||||
- `DiscountOrderDetail`
|
||||
|
||||
3. **ایجاد Configurationها**:
|
||||
- `DiscountProductConfiguration`
|
||||
- `DiscountCategoryConfiguration`
|
||||
- و غیره...
|
||||
|
||||
4. **بهروزرسانی `DbContext`**:
|
||||
```csharp
|
||||
public DbSet<DiscountProduct> DiscountProducts { get; set; }
|
||||
public DbSet<DiscountCategory> DiscountCategories { get; set; }
|
||||
// ...
|
||||
```
|
||||
|
||||
5. **ایجاد Migration**:
|
||||
```bash
|
||||
dotnet ef migrations add AddDiscountShopTables
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: Commands & Queries (3 روز)
|
||||
|
||||
#### DiscountProduct CRUD:
|
||||
- `CreateDiscountProductCommand`
|
||||
- `UpdateDiscountProductCommand`
|
||||
- `DeleteDiscountProductCommand`
|
||||
- `GetDiscountProductByIdQuery`
|
||||
- `GetDiscountProductsListQuery`
|
||||
|
||||
#### DiscountCategory CRUD:
|
||||
- `CreateDiscountCategoryCommand`
|
||||
- `UpdateDiscountCategoryCommand`
|
||||
- `DeleteDiscountCategoryCommand`
|
||||
- `GetDiscountCategoriesTreeQuery`
|
||||
|
||||
#### Shopping Cart:
|
||||
- `AddToDiscountCartCommand`
|
||||
- `RemoveFromDiscountCartCommand`
|
||||
- `GetDiscountCartQuery`
|
||||
|
||||
#### Order:
|
||||
- `CreateDiscountOrderCommand` (Checkout)
|
||||
- `GetDiscountOrderByIdQuery`
|
||||
- `GetMyDiscountOrdersQuery` (برای کاربر)
|
||||
- `UpdateDiscountOrderDeliveryCommand` (برای Admin)
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: BackOffice.BFF APIs (1 روز)
|
||||
|
||||
**Proto file**: `DiscountShopContract.proto`
|
||||
|
||||
```protobuf
|
||||
service DiscountShopContract {
|
||||
// Product
|
||||
rpc CreateDiscountProduct(CreateDiscountProductRequest) returns (CreateDiscountProductResponse);
|
||||
rpc UpdateDiscountProduct(UpdateDiscountProductRequest) returns (UpdateDiscountProductResponse);
|
||||
rpc GetDiscountProducts(GetDiscountProductsRequest) returns (GetDiscountProductsResponse);
|
||||
|
||||
// Category
|
||||
rpc CreateDiscountCategory(CreateDiscountCategoryRequest) returns (CreateDiscountCategoryResponse);
|
||||
rpc GetDiscountCategoriesTree(Empty) returns (GetDiscountCategoriesTreeResponse);
|
||||
|
||||
// Orders
|
||||
rpc GetDiscountOrders(GetDiscountOrdersRequest) returns (GetDiscountOrdersResponse);
|
||||
rpc UpdateDiscountOrderDelivery(UpdateDiscountOrderDeliveryRequest) returns (UpdateDiscountOrderDeliveryResponse);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: FrontOffice.BFF APIs (1 روز)
|
||||
|
||||
**Proto file**: `DiscountShopContract.proto` (در FrontOffice.BFF)
|
||||
|
||||
```protobuf
|
||||
service DiscountShopContract {
|
||||
// Browse
|
||||
rpc GetDiscountProducts(GetDiscountProductsRequest) returns (GetDiscountProductsResponse);
|
||||
rpc GetDiscountProductById(GetDiscountProductByIdRequest) returns (GetDiscountProductByIdResponse);
|
||||
|
||||
// Cart
|
||||
rpc AddToDiscountCart(AddToDiscountCartRequest) returns (AddToDiscountCartResponse);
|
||||
rpc GetMyDiscountCart(Empty) returns (GetMyDiscountCartResponse);
|
||||
rpc RemoveFromDiscountCart(RemoveFromDiscountCartRequest) returns (RemoveFromDiscountCartResponse);
|
||||
|
||||
// Order
|
||||
rpc CheckoutDiscountCart(CheckoutDiscountCartRequest) returns (CheckoutDiscountCartResponse);
|
||||
rpc GetMyDiscountOrders(Empty) returns (GetMyDiscountOrdersResponse);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 5: BackOffice UI (3 روز)
|
||||
|
||||
**صفحات مدیریت:**
|
||||
1. **لیست محصولات تخفیفی** + CRUD
|
||||
2. **دستهبندیها** (Tree View) + CRUD
|
||||
3. **سفارشات تخفیفی** + تغییر وضعیت ارسال
|
||||
4. **گزارش فروش** Discount Shop
|
||||
|
||||
---
|
||||
|
||||
### Phase 6: FrontOffice UI (3 روز)
|
||||
|
||||
**صفحات کاربر:**
|
||||
1. **لیست محصولات تخفیفی** (با فیلتر دستهبندی)
|
||||
2. **جزئیات محصول تخفیفی**
|
||||
3. **سبد خرید تخفیفی**
|
||||
4. **Checkout** (با نمایش `DiscountBalance`)
|
||||
5. **لیست سفارشات تخفیفی کاربر**
|
||||
|
||||
---
|
||||
|
||||
### Phase 7: Unit Tests (2 روز)
|
||||
|
||||
1. تست **CRUD محصولات تخفیفی**
|
||||
2. تست **AddToDiscountCart**
|
||||
3. تست **CheckoutDiscountCart**:
|
||||
- کاربر با موجودی کافی → موفق
|
||||
- کاربر با موجودی ناکافی → خطا
|
||||
|
||||
---
|
||||
|
||||
### Phase 8: Documentation (0.5 روز)
|
||||
|
||||
- بهروزرسانی `implementation-progress.md`
|
||||
- لینک از `REMAINING-TASKS-CONSOLIDATED.md`
|
||||
|
||||
---
|
||||
|
||||
## 📊 خلاصه Timeline
|
||||
|
||||
| Phase | عنوان | زمان |
|
||||
|-------|-------|------|
|
||||
| 1 | Entity Creation | 2 روز |
|
||||
| 2 | Commands & Queries (CMS) | 3 روز |
|
||||
| 3 | BackOffice.BFF APIs | 1 روز |
|
||||
| 4 | FrontOffice.BFF APIs | 1 روز |
|
||||
| 5 | BackOffice UI | 3 روز |
|
||||
| 6 | FrontOffice UI | 3 روز |
|
||||
| 7 | Unit Tests | 2 روز |
|
||||
| 8 | Documentation | 0.5 روز |
|
||||
| **جمع** | | **15.5 روز** (~3 هفته) |
|
||||
|
||||
---
|
||||
|
||||
## 🔗 مراجع
|
||||
|
||||
- [Package Purchase System](./package-purchase-system.md)
|
||||
- [Manual Payment System](./manual-payment-system.md)
|
||||
- [Implementation Progress](./implementation-progress.md)
|
||||
- [REMAINING-TASKS](../REMAINING-TASKS-CONSOLIDATED.md)
|
||||
|
||||
---
|
||||
|
||||
**تاریخ آخرین بهروزرسانی:** 2024-12-02
|
||||
**نویسنده:** GitHub Copilot
|
||||
**وضعیت:** ✅ تایید شده توسط کاربر
|
||||
Reference in New Issue
Block a user