150 lines
7.8 KiB
Markdown
Executable file
150 lines
7.8 KiB
Markdown
Executable file
# افزونه باشگاه مشتریان (Customer Club) — سند اجرایی تولید
|
||
|
||
این سند برای پیادهسازی **سطح تجاری و تولید (Production)** در محصول Hesabix تهیه شده است. معماری با الگوی افزونههای موجود (`product_warranty`, `repair_shop_management`) و بازار افزونه (`MarketplacePlugin` / `BusinessPlugin`) همخوان است.
|
||
|
||
---
|
||
|
||
## ۱. هدف و محدوده
|
||
|
||
### ۱.۱ هدف
|
||
|
||
- افزایش وفاداری مشتری با **امتیازدهی خودکار** بر اساس فاکتور فروش و برگشت از فروش.
|
||
- مدیریت متمرکز **قوانین امتیاز**، **ماندهٔ امتیاز** بر اساس شخص (`Person`)، و **دفتر تراکنش** قابل حسابرسی.
|
||
|
||
### ۱.۲ محدودهٔ نسخهٔ اول (همین پیادهسازی)
|
||
|
||
| قابلیت | وضعیت |
|
||
|--------|--------|
|
||
| ثبت افزونه در بازار با کد ثابت `customer_club` | بله |
|
||
| تنظیمات برنامهٔ باشگاه به ازای هر کسبوکار | بله |
|
||
| امتیاز از فاکتور **فروش** (`invoice_sales`) و کسر متناسب از **برگشت از فروش** (`invoice_sales_return`) | بله |
|
||
| بهروزرسانی امتیاز هنگام **ویرایش** فاکتور (همتراز با مبلغ جدید) | بله |
|
||
| برگشت امتیاز هنگام **حذف** فاکتور | بله |
|
||
| رد شدن فاکتور **پیشفاکتور** (`is_proforma`) | بله |
|
||
| تراکنش دستی اصلاحی (با مجوز `adjust`) | بله |
|
||
| مصرف امتیاز در بدنهٔ فاکتور فروش (تخفیف از کیف امتیاز) | **خیر** (فاز بعد؛ نیاز به تغییر payload فاکتور و UI فروش) |
|
||
|
||
---
|
||
|
||
## ۲. معماری فنی
|
||
|
||
### ۲.۱ کد افزونه و لایسنس
|
||
|
||
- **کد بازار:** `customer_club`
|
||
- فعالسازی از طریق جدول `business_plugins` و رکورد `marketplace_plugins` (اسکریپت `scripts/add_customer_club_plugin.py`).
|
||
- تمام endpointهای اختصاصی باشگاه با `require_business_access` + وابستگی پلاگین (`customer_club_plugin_dependency`) محافظت میشوند.
|
||
|
||
### ۲.۲ مجوزهای کسبوکار (JSON در `business_permissions`)
|
||
|
||
| کلید سکشن | معنی |
|
||
|-----------|------|
|
||
| `customer_club` | باشگاه مشتریان |
|
||
|
||
| اکشن | کاربرد |
|
||
|------|--------|
|
||
| `view` | مشاهدهٔ داشبورد، مانده و لیست تراکنشها (پیشنیاز سایر اکشنها در UI) |
|
||
| `manage` | تغییر تنظیمات برنامهٔ امتیاز |
|
||
| `adjust` | ثبت تراکنش دستی اصلاحی در دفتر |
|
||
|
||
مالک کسبوکار (`isOwner`) طبق منطق موجود `AuthStore` به همه دسترسی دارد.
|
||
|
||
### ۲.۳ مدل داده
|
||
|
||
1. **`customer_club_settings`** — یک ردیف به ازای هر `business_id` (تنظیمات قوانین).
|
||
2. **`customer_club_balance`** — ماندهٔ تجمیعی امتیاز به ازای هر `(business_id, person_id)` با قفل ردیفی هنگام بهروزرسانی.
|
||
3. **`customer_club_ledger`** — دفتر append-only با `delta_points`, `balance_after`, نوع تراکنش، ارجاع به سند.
|
||
4. **`customer_club_invoice_snapshot`** — آخرین امتیاز محاسبهشده برای هر `document_id` جهت **ایدمپوتنت** بودن همگامسازی با ویرایش فاکتور و حذف تمیز.
|
||
|
||
### ۲.۴ محاسبهٔ مبلغ مبنا
|
||
|
||
از `document.extra_info.totals` خوانده میشود:
|
||
|
||
- **`net`**: جمع بعد از تخفیف، قبل از مالیات (همراستا با فیلدهای متداول گزارشها).
|
||
- **`total_with_tax`**: در صورت انتخاب مبنا در تنظیمات، از `net + tax`، با تکیه بر همان شیء `totals`.
|
||
|
||
در نبود `totals`، از محاسبهٔ خطوط `InvoiceItemLine.extra_info` (همان منطق کمکی موجود در خدمات فاکتور) استفاده میشود.
|
||
|
||
### ۲.۵ دو حالت کسب امتیاز
|
||
|
||
| حالت (`earn_mode`) | فرمول |
|
||
|-------------------|--------|
|
||
| `percent_basis` | `points = basis_amount × (percent_of_basis / 100)` سپس گرد طبق `rounding` |
|
||
| `points_per_currency` | `points = (basis_amount / step_amount) × points_per_step` با گرد |
|
||
|
||
تنظیمات `rounding`: `floor` | `ceil` | `round`.
|
||
|
||
### ۲.۶ هوکهای فاکتور (`invoice_service.py`)
|
||
|
||
| رویداد | رفتار |
|
||
|--------|--------|
|
||
| ایجاد فاکتور قطعی (فروش/برگشت) بعد از `on_sales_invoice_document_finalized` | `sync_customer_club_for_invoice` در همان تراکنش commitشدهٔ بلاک سود دفتر |
|
||
| بهروزرسانی فاکتور قطعی بعد از سود دفتر | همان `sync_customer_club_for_invoice` قبل از `db.commit()` نهایی |
|
||
| حذف فاکتور قبل از `db.delete(document)` | `reverse_customer_club_on_invoice_delete` برای بازگرداندن مانده بر اساس snapshot |
|
||
|
||
خطاهای باشگاه **نباید** مانع ثبت حسابداری شوند؛ در صورت خطا فقط `warning` لاگ میشود (همسبک workflow).
|
||
|
||
---
|
||
|
||
## ۳. API (خلاصه)
|
||
|
||
پیشوند پیشنهادی: `/api/v1/customer-club/business/{business_id}/...`
|
||
|
||
- `GET /settings` — نیاز به `view`
|
||
- `PUT /settings` — نیاز به `manage`
|
||
- `GET /persons/{person_id}/balance` — `view`
|
||
- `GET /ledger` — صفحهبندی، فیلتر `person_id` — `view`
|
||
- `POST /adjustments` — بدنه: `person_id`, `delta_points`, `description` — `adjust`
|
||
|
||
پاسخها با `success_response` و در صورت نیاز `format_datetime_fields`.
|
||
|
||
---
|
||
|
||
## ۴. فرانتاند (Flutter)
|
||
|
||
- مسیرها زیر شِل کسبوکار: `/business/:id/customer-club` (داشبورد با تبها)، `/customer-club/settings`.
|
||
- منوی کناری: نمایش فقط اگر پلاگین فعال و `customer_club.view`.
|
||
- صفحهٔ دسترسیها: گروه «باشگاه مشتریان» با اکشنهای `view`, `manage`, `adjust`.
|
||
|
||
---
|
||
|
||
## ۵. استقرار (Operations)
|
||
|
||
1. اجرای مهاجرت Alembic برای جداول جدید.
|
||
2. اجرای اسکریپت ثبت افزونه در بازار (یا ثبت دستی معادل در پنل ادمین بازار در صورت وجود).
|
||
3. اعطای مجوز به نقشها از مسیر کاربران کسبوکار.
|
||
4. پایش لاگ برای خطاهای غیرمسدودکنندهٔ باشگاه پس از استقرار.
|
||
|
||
---
|
||
|
||
## ۶. پیروی از مقررات و حسابرسی
|
||
|
||
- تمام تغییرات مانده از طریق `ledger` با `balance_after` ثبت میشود.
|
||
- تراکنشهای دستی با نوع `adjustment` و توضیح الزامی در API.
|
||
|
||
---
|
||
|
||
## ۷. نقشهٔ راه بعدی (خارج از این نسخه)
|
||
|
||
- مصرف امتیاز در فاکتور فروش و جلوگیری از ماندهٔ منفی.
|
||
- سطحبندی (Tier) و کمپینها.
|
||
- اعلان خودکار و اتصال به Workflow برای پیامک/ایمیل.
|
||
|
||
---
|
||
|
||
**نسخهٔ سند:** ۱.۰ — همتراز با پیادهسازی مخزن در تاریخ ایجاد فایل.
|
||
|
||
---
|
||
|
||
## ۸. دستورات استقرار (خلاصهٔ عملیاتی)
|
||
|
||
در ریشهٔ پروژهٔ API (`hesabixAPI`):
|
||
|
||
```bash
|
||
cd hesabixAPI
|
||
alembic upgrade head
|
||
python scripts/add_customer_club_plugin.py
|
||
```
|
||
|
||
سپس اپلیکیشن وب و API را طبق روال استقرار شما بازنشانی کنید.
|
||
|
||
پس از استقرار، از مسیر «کاربران و دسترسیها» برای نقشهای غیرمالک، دسترسیهای `customer_club.view`، `manage` و در صورت نیاز `adjust` را فعال کنید.
|