feat(admin): build the last two screens, and pin spacing with a test
The cancellation policy page showed only the tenant policy, so nothing said which services opt out of it. Service policies do not blend with the tenant one — a service that has its own follows it completely — and without the table an operator cannot tell why one service's penalty differs. It lists them with a link to each service. The waitlist had the matches endpoint and no way to reach it. The list answers "who is waiting"; the question asked when capacity frees up is "who is waiting for this slot", so the page now takes a service and a date and answers that. The note says plainly that cancelling notifies them anyway — this is for looking before deciding, not a second notification path. Spacing is enforced at hold time rather than during candidate generation, which costs one slot being shown and then refused, and saves a patient-history query per candidate. That trade had no test; now a booking five days after the last one is refused and one thirty days later goes through. Checklists across all sixteen tasks are final: no pending rows, and the warnings that remain are recorded decisions — one resolver instead of six engines, a closed list instead of a registry, sample size three instead of ten — each with the reason it was taken. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -64,7 +64,7 @@
|
||||
| ۳.۷ | کارت فاکتور در `AppointmentDetailPage` | ✅ | `AppointmentInvoiceCard` — ردیفهای صفر پنهان میشوند |
|
||||
| ۳.۸ | متن «قیمت بر اساس تاریخ نوبت محاسبه شده» | ✅ | ⭐ وگرنه کاربری که دیروز تعرفه را عوض کرده فکر میکند سیستم خراب است |
|
||||
| ۳.۹ | هیچ رنگ/شعاع hard-code | ✅ | |
|
||||
| ۳.۱۰ | دارکمود و حالت فشرده | ⚠️ | فقط توکنها؛ بازبینی چشمی انجام نشد |
|
||||
| ۳.۱۰ | دارکمود و حالت فشرده | ✅ | اسکرینشات واقعی در دارکمود و حالت فشرده؛ ایرادی نماند |
|
||||
| ۳.۱۱ | RTL و موبایل | ✅ | جدول لیستها اسکرول افقی داخلی دارد |
|
||||
| ۳.۱۲ | مبالغ با `formatRial` · تاریخ با `formatDate` | ✅ | |
|
||||
| ۳.۱۳ | وضعیت لیست در URL | ✅ | `useUrlState` |
|
||||
@@ -77,12 +77,12 @@
|
||||
|---|---|---|---|
|
||||
| ۴.۱ | ترتیب لایههای قیمت + fallback | ✅ | `testFullChainAppliesInOrder` · `testFallsBackToTheServicePrice` · `testBranchOverrideBeatsThePriceList` |
|
||||
| ۴.۲ | تخفیف پشتسرهم، سقف، منفی → صفر | ✅ | `testDiscountLargerThanTheAmountFloorsAtZero` · `testTotalDiscountCapIsApplied` |
|
||||
| ۴.۳ | invariant جمع ردیفها = مبلغ نهایی | ⚠️ | زنجیره در `testFullChainAppliesInOrder` عددبهعدد سنجیده میشود؛ invariant بهصورت property-based روی سناریوهای تصادفی نوشته نشد |
|
||||
| ۴.۳ | invariant جمع ردیفها = مبلغ نهایی | ✅ | ⭐ `testTheRowsAlwaysAddUpToTheFinalAmount` — خودِ رابطه سنجیده میشود نه عددها؛ ردیفِ تازهای که در جمع نیاید همین را قرمز میکند. یادداشت قبلی: invariant بهصورت property-based روی سناریوهای تصادفی نوشته نشد |
|
||||
| ۴.۴ | تغییرناپذیری فاکتور (قانون پنجم) | ✅ | ⭐ `testBookedAppointmentKeepsItsOriginalInvoiceAfterAPriceChange` |
|
||||
| ۴.۵ | فعالسازی و تداخل بازه | ✅ | `testOverlappingActiveListsAreRejected` · `testBranchListWinsOverTheGeneralList` · `testDraftListHasNoEffectUntilActivated` |
|
||||
| ۴.۶ | محاسبهٔ بیعانه | ⚠️ | درصدی و مبلغی هر دو در `PricingEngine` هست و در زنجیرهٔ کامل تست میشود؛ تست اختصاصی با min/max ندارد |
|
||||
| ۴.۶ | محاسبهٔ بیعانه | ✅ | مبلغی بر درصدی مقدم است و از مبلغ نهایی بیشتر نمیشود — هر دو تست دارند. یادداشت قبلی: تست اختصاصی با min/max ندارد |
|
||||
| ۴.۷ | سرویس محیط دیگر ۴۰۴ | ✅ | `testForeignServiceIsNotFound` |
|
||||
| ۴.۸ | نوبت بدون سرویس → فاکتور با `visit_price_rials` | ⚠️ | مسیرش هست (`recordFlatVisit`)؛ تست اختصاصی ندارد |
|
||||
| ۴.۸ | نوبت بدون سرویس → فاکتور با `visit_price_rials` | ✅ | ثبت بدون `service_uuid` تست شد: فاکتور ساخته میشود و `items_rials` صفر است |
|
||||
| ۴.۹ | قیمت منفی رد میشود | ✅ | `testNegativePriceIsRejected` |
|
||||
| ۴.۱۰ | تست فرانت کارت فاکتور | ✅ | چهار تست |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user