- Add implementation notes for cancellation and waitlist features. - Create task documentation outlining goals, current status, and acceptance criteria for cancellation policy and resource utilization reporting. - Establish architecture for domain events and outbox pattern to ensure reliable event publishing. - Define database schema for domain events and necessary queries for resource utilization and plan accuracy reports. - Implement detailed implementation notes covering edge cases, testing strategies, and documentation requirements.
4.7 KiB
تسک ۱۱ — پکیج و دفتر اعتبار جلسات
فاز: ۳ (کسبوکار) · وابستگی: ۰۸ · زمان: ۱۰-۱۲ ساعت
هدف
مستند بند ۱۲: «پکیج شش جلسه لیزر» حالت رایج کلینیک زیبایی است. بیمار یکجا پول میدهد و بعداً جلساتش را رزرو میکند.
نکتهٔ فنی مستند: اعتبار را به صورت دفتر حساب نگه میداریم، نه یک عدد شمارنده.
وضعیت فعلی
هیچ مفهومی از پکیج وجود ندارد. ولی الگوی «دفتر حساب» از قبل در پروژه هست و درست
پیاده شده: WalletTransaction + getWalletBalance(user) — موجودی از جمع تراکنشها
محاسبه میشود، نه از یک ستون شمارنده. همان الگو اینجا تکرار میشود.
⚠️ نکتهٔ tenancy: wallet_transactions عمداً ENTITIES است (پول مال شخص است) ولی هر
ردیف recorded_entity_* دارد. دفتر اعتبار جلسه متفاوت است: اعتبار جلسهٔ لیزر در
کلینیک الف در کلینیک ب معنا ندارد. پس جفت tenant واقعی میگیرد، نه انتساب.
دامنه
هست:
Package— تعریف پکیج (سرویس، تعداد جلسه، قیمت، اعتبار زمانی)PatientPackage— پکیج خریداریشدهٔ یک بیمارSessionCreditLedger— دفتر اعتبار: هر تراکنش یک ردیف- مصرف اعتبار در
confirmنوبت، بازگشت در لغو - اتصال به
PricingEngineمرحلهٔ ۴ (قلاب تسک ۰۸)
نیست: پروتکل دوره و فاصلهٔ جلسات (تسک ۱۲)، سیاست لغو (تسک ۱۳).
Endpoint ها
| متد | مسیر | توضیح |
|---|---|---|
| GET/POST | /api/v1/packages |
تعریف پکیج |
| GET/PATCH/DELETE | /api/v1/package/{uuid} |
|
| POST | /api/v1/patient/{uuid}/package |
فروش پکیج به بیمار |
| GET | /api/v1/patient/{uuid}/packages |
پکیجهای بیمار + مانده |
| GET | /api/v1/patient-package/{uuid}/ledger |
دفتر تراکنشهای اعتبار |
| POST | /api/v1/patient-package/{uuid}/adjust |
اصلاح دستی با دلیل (فقط مدیر) |
| POST | /api/v1/patient-package/{uuid}/expire |
ابطال دستی |
معیار پذیرش
- ✅ موفق: پکیج «۶ جلسه لیزر فولبادی» با قیمت تعریف میشود، به بیمار فروخته میشود →
GET /patient/{uuid}/packagesمانده6میدهد و دفتر یک ردیفpurchase +6دارد. - ✅ موفق: ثبت نوبت لیزر برای همان بیمار →
PricingEngineمرحلهٔ ۴ یک واحد کسر میکند، مبلغ نهایی صفر میشود، دفتر ردیفconsume -1میگیرد، مانده5. - ✅ موفق: لغو همان نوبت → ردیف
refund +1، مانده6. ردیفconsumeحذف نمیشود. - ✅ موفق (دفتر، نه شمارنده): مانده همیشه
SUM(delta)است. یک تست باید ثابت کند هیچ ستونremainingیاused_countدر schema وجود ندارد. - ✅ موفق:
POST /adjustبا دلیل → ردیفadjustmentباreasonوcreated_by. - ❌ خطا: ثبت نوبت با پکیجی که ماندهاش صفر است → پکیج اعمال نمیشود، مبلغ کامل محاسبه میشود (نه خطا — بیمار میتواند نقدی بپردازد).
- ❌ خطا: پکیج محیط الف روی نوبت محیط ب →
404. - ❌ خطا:
adjustبا نقش منشی →403. - ⚠️ مرزی: پکیج منقضیشده (
valid_toگذشته) → مانده در نمایش صفر میشود ولی دفتر دستنخورده میماند؛ ردیفexpiryبا delta منفی برابر مانده ثبت میشود. - ⚠️ مرزی: دو نوبت همزمان که هر دو آخرین اعتبار را میخواهند → یکی میگیرد، دیگری مبلغ کامل. بدون منفی شدن مانده.
- ⚠️ مرزی: بیمار دو پکیج معتبر برای یک سرویس دارد → قدیمیترِ منقضینشده اول مصرف شود (FIFO).
- ⚠️ مرزی: پکیجی که هیچ سرویسی به آن وصل نیست →
422هنگام ساخت.
خروجی
src/Package/assets/admin/pages/PackagesPage.tsx+ کارت پکیج درPatientDetailPage.tsxdocs/api/package.md