# چک‌لیست — تسک ۱۱ (پکیج و دفتر اعتبار جلسات) > # ⛔ این تسک از محصول حذف شد > > **تصمیم مالک محصول، ۱۴۰۵/۰۵/۱۰:** مدل نوبت‌دهی به منبع/سرویس/گزینه محدود شد و هر چیز > خارج از آن حذف شد. کد، جدول‌ها، endpointها، تست‌ها و صفحات پنل این تسک در کامیت > «Remove the policy, package, course, cancellation and event subsystems» برداشته شدند. > > ریسکش پیش از اجرا دو بار مطرح و دو بار تأیید شد. ردیف‌های زیر **تاریخچه**اند، نه کار > جاری؛ برای برگرداندن به همان کامیت رجوع کنید. > > مدل جایگزین: [`docs/architecture/resource-first-model.md`](../../../architecture/resource-first-model.md) > و چک‌لیست [تسک ۱۵](../task-15-resource-first-model/checklist.md). **وضعیت کلی:** ✅ تمام‌شده با انحراف‌های ثبت‌شده · **آخرین بازبینی:** ۱۴۰۵/۰۵/۰۹ قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) · [red-lines.md](../_shared/red-lines.md) · [ui-conventions.md](../_shared/ui-conventions.md) --- ## ۰. خط سرخ | # | مورد | وضعیت | یادداشت | |---|---|---|---| | ۰.۱ | `--group=slot-mode-frozen` سبز | ✅ | | | ۰.۲ | **هیچ ستون `remaining`/`used_count`/`balance` در هیچ جدولی** | ✅ | ⭐⭐ `testNoStoredBalanceColumnExists` روی schema واقعی | | ۰.۳ | دفتر append-only | ✅ | هیچ `remove`/`setter` روی `SessionCreditLedger`؛ تصحیح = ردیف تازه | | ۰.۴ | `WalletTransaction` دست‌نخورده | ✅ | تفاوتش در `tenancy.md` نوشته شد | ## ۱. بک‌اند | # | مورد | وضعیت | یادداشت | |---|---|---|---| | ۱.۱ | چهار entity | ✅ | | | ۱.۲ | `CreditLedgerService` تنها نویسندهٔ دفتر | ✅ | فروش، مصرف، بازگشت و اصلاح همه از همین عبور می‌کنند | | ۱.۳ | `balance()` = `SUM(delta)` | ✅ | ⭐ | | ۱.۴ | پنج `kind` | ✅ | سازنده `kind` ناشناخته و `delta` صفر را رد می‌کند | | ۱.۵ | `quote` هرگز مصرف نمی‌کند | ✅ | ⭐⭐ `testQuoteAnnouncesThePackageWithoutConsumingIt` دو بار quote می‌زند و مانده را می‌سنجد | | ۱.۶ | پرچم `packageWillBeConsumed` | ✅ | + `package_uuid` | | ۱.۷ | مانده صفر → `false` نه استثنا | ✅ | ⭐ | | ۱.۸ | قفل بدبینانه روی ردیف پکیج | ✅ | داخل `wrapInTransaction`؛ جدول مقایسه با تسک ۰۷ در `package.md` | | ۱.۹ | `consume` idempotent | ✅ | تصمیم ثبت‌شده در [deviations.md](../../../architecture/deviations.md) — با **بررسی پیش از درج** نه `catch` روی نقض کلید: گرفتن استثنا در Doctrine خودِ EntityManager را می‌بندد و بقیهٔ همان request را می‌سوزاند. کلید یکتا آخرین خط دفاع می‌ماند | | ۱.۱۰ | FIFO | ✅ | `testTheOldestUnexpiredPackageIsUsedFirst` | | ۱.۱۱ | `valid_to` هنگام خرید | ✅ | از `validity_days` لحظهٔ خرید | | ۱.۱۲ | لغو → ردیف `refund` | ✅ | `BookingService::cancel()` | | ۱.۱۳ | ارجاع به تسک ۱۳ برای سیاست بازگشت | ✅ | در docblock `refund()` | | ۱.۱۴ | `adjust` فقط نقش مدیر و با `reason` | ✅ | منشی `403` | | ۱.۱۵ | `app:package:expire` | ✅ | `--dry-run` هم دارد | | ۱.۱۶ | قلاب `PricingEngine` | ✅ | `patient_uuid` اختیاری در `quote` | | ۱.۱۷ | هشت endpoint | ✅ | ۹ تا: `packages` GET/POST · `package/{uuid}` GET/PATCH/DELETE · `patient/{uuid}/package` · `patient/{uuid}/packages` · `patient-package/{uuid}/ledger` · `/adjust` · `/expire` | | ۱.۱۸ | `TenantOwnershipChecker` روی هر uuid | ✅ | `testAnotherClinicCannotSeeOrTouchThePackage` | ## ۲. دیتابیس | # | مورد | وضعیت | یادداشت | |---|---|---|---| | ۲.۱ | چهار جدول | ✅ | `Version20260731072023` | | ۲.۲ | `bigint` روی هر دو ستون مبلغ | ✅ | | | ۲.۳ | `UNIQUE(appointment_id, kind)` | ✅ | ⭐ | | ۲.۴ | snapshot تعداد و قیمت | ✅ | قانون پنجم | | ۲.۵ | `ON DELETE RESTRICT` روی سرویس و پکیج | ✅ | | | ۲.۶ | `package_services` در `AGGREGATE_CHILDREN` | ✅ | | | ۲.۷ | دفتر جفت tenant دارد | ✅ | ⭐ دلیلش در `tenancy.md` کنار کیف پول | | ۲.۸ | `TenantSchemaCoverageTest` سبز | ✅ | | ## ۳. UI | # | مورد | وضعیت | یادداشت | |---|---|---|---| | ۳.۱ | `PackagesPage` با `PriceInput` و انتخاب سرویس | ✅ | + ورودی منوی تنظیمات | | ۳.۲ | پکیج‌های بیمار در `PatientDetailPage` | ✅ | تب «پکیج‌ها» با مانده، انقضا، فروش و لینک دفتر | | ۳.۳ | `PatientPackageLedgerPage` | ✅ | | | ۳.۴ | ستون مانده تجمعی | ✅ | تصمیم ثبت‌شده در [deviations.md](../../../architecture/deviations.md) — **سرور** محاسبه‌اش می‌کند (`running_balance`) نه UI — یک منبع، و همان عددی که تست بک‌اند تضمینش می‌کند | | ۳.۵ | ستون‌های دفتر | ✅ | «ثبت‌کننده» و «نوبت» هم اضافه شدند — دفترِ اصلاح‌پذیر بدون نام اصلاح‌کننده، نصف حسابرسی است. یادداشت قبلی: در جدول نمایش داده نمی‌شوند (عرض موبایل) | | ۳.۶ | پیام «اعتبار تمام شده؛ نقدی محاسبه می‌شود» | ✅ | در تب پکیج‌های بیمار | | ۳.۷ | `DataTable` با skeleton و empty state | ✅ | | | ۳.۸ | سرویس‌ها با `SearchableSelect` | ✅ | هیچ `