Files
hedena_gold/docs/RIAL-WAGE-PORT.md
saeedandCursor feb5727c0e feat: order revision, rial wage from variant, product tags; drop user-app-v2
Admin order edit with category chips and timeline; customer checkout charges variant rialWage; product tags; retire the unused user-app-v2 tree.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-28 14:29:12 +03:30

194 lines
8.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# اجرت ریالی — راهنمای پورت به نسخهٔ دیگر
این سند خلاصهٔ کارهایی است که برای **اجرت ریالی** (`rial_pay` / `rialWage` / `flatRialCharge`) در این ریپو انجام شده، تا بتوان همان رفتار را روی یک branch/نسخهٔ دیگر پیاده کرد.
اجرت ریالی با **اجرت درصدی** (`wagePercent`) فرق دارد: درصد داخل فرمول وزن طلا می‌رود؛ ریالی یک مبلغ ثابت ریال روی تنوع است و جداگانه روی سفارش می‌نشیند.
---
## نگاشت نام‌ها
| لایه | نام | معنی |
|------|-----|------|
| لگاسی / API ادمین و کاتالوگ | `rial_pay` | مبلغ ثابت ریال روی تنوع |
| لگاسی جمع سفارش | `rial_input` | Σ (ریال خط × تعداد) |
| Prisma تنوع | `ProductVariant.rialWage` | همان `rial_pay` |
| Prisma سفارش / آیتم | `Order.flatRialCharge` / `OrderItem.flatRialCharge` | جمع سفارش / مبلغ واحد هر خط |
| لیست ادمین سفارش | `total_price` | alias همان `Order.flatRialCharge` |
---
## جریان انتها‌به‌انتها
```
ادمین در فرم محصول → variant.rial_pay
↓
ProductVariant.rialWage (DB)
↓
کاتالوگ / API محصول → rial_pay
↓
اپ کاربر: نمایش در سبد (اختیاری)
↓
ثبت سفارش:
• مشتری → flatRialCharge = variant.rialWage (از body خوانده نمی‌شود)
• اپراتور پنل → flatRialCharge از body / rial_input
↓
OrderItem.flatRialCharge (واحد) + Order.flatRialCharge = Σ(واحد × qty)
↓
وضعیت تحویل‌شده → Ledger بدهی RIAL = Order.flatRialCharge
```
فرمول وزن طلا (بدون ریال):
```
weight = rash × (1 + (wagePercent − discountPercent) / 100)
```
---
## چک‌لیست پورت (به ترتیب)
### ۱) دیتابیس / Prisma
- [ ] فیلد روی تنوع:
```prisma
/// Legacy rial_pay — fixed Rial making charge per variant.
rialWage Decimal? @db.Decimal(18, 0)
```
- [ ] مایگریشن (نمونه از این ریپو: `apps/api/prisma/migrations/20261025143000_variant_legacy_fields/migration.sql`):
```sql
ALTER TABLE "ProductVariant" ADD COLUMN IF NOT EXISTS "rialWage" DECIMAL(18,0);
```
- [ ] از قبل باید باشند (معمولاً در schema اولیه):
- `Order.flatRialCharge Decimal @default(0) @db.Decimal(20,2)`
- `OrderItem.flatRialCharge Decimal @default(0) @db.Decimal(20,2)`
### ۲) API — نگاشت محصول / کاتالوگ
| فایل | کار |
|------|-----|
| `apps/api/src/modules/admin-products/admin-products.service.ts` | خواندن: `rial_pay: Number(v.rialWage) \| null` — نوشتن: `rialWage` از `v.rial_pay` |
| `apps/api/src/modules/catalog/catalog.service.ts` | روی هر variant کاتالوگ: `rial_pay: v.rialWage != null ? Number(v.rialWage) : null` |
### ۳) API — ثبت سفارش (مهم‌ترین رفتار)
فایل: `apps/api/src/modules/orders/orders.service.ts`
```ts
// مسیر مشتری: فقط از DB (variant.rialWage) — body نادیده گرفته می‌شود
const flatRialCharge = quotes
? new Prisma.Decimal(variant.rialWage ?? 0)
: new Prisma.Decimal(item.flatRialCharge ?? 0);
```
جمع سفارش:
```ts
Order.flatRialCharge = Σ (item.flatRialCharge × quantity)
```
- DTO آیتم (`create-order.dto.ts`): `flatRialCharge?: number` اختیاری است.
- مسیر اپراتور ادمین (`admin-orders.service` create): `rial_input` → `flatRialCharge`.
- تست‌ها در `orders.service.spec.ts` باید با همین قانون هم‌خوان باشند (تمپر کلاینت روی ریال بی‌اثر بماند).
> **توجه تاریخی:** قبلاً (MON-08) مسیر مشتری عمداً `flatRialCharge = 0` بود. نسخهٔ فعلی از `variant.rialWage` شارژ می‌کند. روی نسخهٔ مقصد همین تصمیم را صریح نگه دارید.
### ۴) API — ویرایش سفارش (اگر آن نسخه revision دارد)
فایل: `apps/api/src/modules/orders/order-revision.service.ts`
- پیش‌فرض خط: `flatRialCharge ?? variant.rialWage ?? 0`
- جمع revision مثل create از Σ واحد × qty
### ۵) لجر / حسابداری / گزارش
| فایل | کار |
|------|-----|
| ledger (بدهی ریال هنگام تحویل) | `Order.flatRialCharge` |
| `accounting-sync.service.ts` | `flatRial: item.flatRialCharge × qty` |
| `admin-report.service.ts` | ستون اکسل «اجرت ریالی» از `item.flatRialCharge` |
### ۶) ادمین پنل — فرم محصول
فایل: `apps/admin-panel/src/views/apps/product/AddProduct.vue`
- ستون جدول تنوع: «اجرت ریالی» ← `rial_pay`
- مودال تنوع: فیلد «اجرت ریالی» (`a-input-number`) ← `variantForm.rial_pay`
- در save/load: `rial_pay` را با API رد و بدل کنید
### ۷) ادمین پنل — جزئیات / ویرایش سفارش
فایل: `apps/admin-panel/src/views/order/OrderDetailBody.vue` (+ `List.vue` / `OmdeList.vue`)
- نمایش chip وقتی `flatRialCharge > 0`
- در حالت ویرایش: `a-input-number` روی `item.flatRialCharge`
- هنگام افزودن خط از تنوع: seed با `row.rial_pay`
- payload پیشنهاد ویرایش باید `flatRialCharge` هر خط را بفرستد
### ۸) اپ کاربر
| فایل | کار |
|------|-----|
| `user-app/src/api/client.ts` | `ProductVariantSummary.rial_pay`؛ سفارش‌ها `flatRialCharge` |
| `CartItem.vue` | اگر `rial_pay > 0` → «اجرت ریالی … ریال» |
| `cartStore.ts` | `totalRial()` = Σ `rial_pay × qty` (پیش‌نمایش) |
| `OrderCard.vue` / `OrderItemCard.vue` | نمایش `flatRialCharge` وقتی > 0 |
| `CartView.vue` | معمولاً `flatRialCharge` را **نمی‌فرستد**؛ سرور از `rialWage` پر می‌کند |
### ۹) ایمپورت لگاسی (اختیاری ولی توصیه می‌شود)
- تنوع: `rial_pay` → `ProductVariant.rialWage`
- خط سفارش: `rial_pay` → `OrderItem.flatRialCharge`
- هدر سفارش: `rial_input` → `Order.flatRialCharge`
اگر اسکریپت ایمپورت هنوز می‌گوید «فیلد مقصد ندارد»، بعد از افزودن `rialWage` باید به‌روز شود.
---
## فایل‌های کلیدی این ریپو (مرجع کپی)
```
apps/api/prisma/schema.prisma # rialWage + flatRialCharge
apps/api/prisma/migrations/20261025143000_variant_legacy_fields/migration.sql
apps/api/src/modules/admin-products/admin-products.service.ts
apps/api/src/modules/catalog/catalog.service.ts
apps/api/src/modules/orders/orders.service.ts
apps/api/src/modules/orders/orders.service.spec.ts
apps/api/src/modules/orders/order-revision.service.ts # اگر ویرایش سفارش دارید
apps/api/src/modules/admin-orders/admin-orders.service.ts
apps/admin-panel/src/views/apps/product/AddProduct.vue
apps/admin-panel/src/views/order/OrderDetailBody.vue
apps/user-app/src/components/product/CartItem.vue
apps/user-app/src/stores/cartStore.ts
apps/user-app/src/components/product/OrderCard.vue
apps/user-app/src/components/product/OrderItemCard.vue
apps/user-app/src/api/client.ts
```
کامیت مرجع فیلد تنوع: `55d2715` — `feat(products): port missing variant fields from henza…`
شارژ مسیر مشتری از `rialWage` و UI سبد/سفارش ممکن است روی working tree باشد؛ هنگام پورت از وضعیت فعلی این فایل‌ها کپی بگیرید، نه فقط از آن کامیت.
---
## تست دستی سریع بعد از پورت
1. در ادمین روی یک تنوع «اجرت ریالی» مثلاً `500000` بگذارید و ذخیره کنید.
2. کاتالوگ / جزئیات محصول در اپ همان عدد را به‌صورت `rial_pay` بدهد.
3. سبد: اگر UI پورت شده، خط «اجرت ریالی» دیده شود.
4. ثبت سفارش از اپ: `OrderItem.flatRialCharge` و جمع `Order.flatRialCharge` برابر مقدار تنوع × تعداد باشد — حتی اگر کلاینت عدد دیگری فرستاده باشد.
5. ثبت/ویرایش از پنل ادمین: عدد وارد‌شدهٔ اپراتور حفظ شود.
6. بعد از وضعیت تحویل: بدهی ریال لجر با جمع سفارش هم‌خوان باشد.
---
## چیزهایی که عمداً تغییر نمی‌کنند
- فرمول وزن/اجرت درصدی (`wage-formula.ts`) ریال را داخل وزن حساب نمی‌کند.
- نام API بیرونی برای تنوع همان `rial_pay` می‌ماند؛ فقط ستون DB `rialWage` است.
- بدون مقدار روی تنوع → شارژ `0` (نه خطا).