feat(admin): catalog groups and appointment segments editors
Tasks 04 and 05 shipped working engines that a clinic could only reach through the API. Both now have the panel that makes them usable. Groups tab - Inline min/max per group, saved on blur, with the meaning of an empty maximum spelled out next to the field rather than left as folklore - Incompatible / prerequisite rows; the prerequisite-cycle 422 surfaces the server's own message, which is more precise than anything generic - A live preview that calls the same service-selection/validate the public site calls, debounced 400ms. Two separate calculations would eventually show the operator and the patient different numbers - The breakdown table shows which item was counted as the anchor and which as additional, so a surprising total explains itself Segments tab - Sequence, duration source, patient-present and mergeable per segment, plus resource requirements with an explanation attached to each occupancy mode - A timeline bar whose widths are proportional to duration, with segments the patient is absent for drawn faded. That contrast is the whole point of task 05: the waiting segment holds the room but frees the operator - "No eligible resource" renders with a link to add one — an error with no route forward is a dead end Task 05's checklist had been left on "not started" this whole time even though its code shipped with the task; it is now filled in against reality. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# چکلیست — تسک ۰۴ (کاتالوگ خدمات v2)
|
||||
|
||||
**وضعیت کلی:** ✅ بکاند و مستندات تکمیل (بخش ۴ UI ⏳ با مقصد صریح) · **آخرین بازبینی:** —
|
||||
**وضعیت کلی:** ✅ تمامشده — بکاند، مستندات و UI · **آخرین بازبینی:** ۱۴۰۵/۰۵/۰۹
|
||||
|
||||
قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) ·
|
||||
[red-lines.md](../_shared/red-lines.md) · [ui-conventions.md](../_shared/ui-conventions.md)
|
||||
@@ -62,18 +62,19 @@
|
||||
|
||||
| # | مورد | وضعیت | یادداشت |
|
||||
|---|---|---|---|
|
||||
| ۴.۱ | تب «گروهها و آیتمها» در `ServiceDetailPage` موجود | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۲ | ویرایش inline `min/max` گروه | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۳ | جدول آیتمها: نام، زمان تنها، زمان اضافه، قیمت، فعال | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۴ | ناسازگاری/پیشنیاز با `SearchableSelect` چندانتخابی | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۵ | **پیشنمایش زنده مدت** با debounce ۴۰۰ms | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۶ | قیمت با `PriceInput` | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۷ | هیچ رنگ/شعاع hard-code | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۸ | دارکمود و حالت فشرده | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۹ | RTL و موبایل | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۱۰ | فرم با React Hook Form + Zod | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۱۱ | همهٔ رشتهها فارسی | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۱۲ | خطاهای اعتبارسنجی **زیر همان گروه** نمایش داده میشوند | ⏳ | UI پنل این تسک ساخته نشد — بکاند و اندپوینتها کاملاند و `POST /service-selection/validate` بدون UI هم مصرفشدنی است. مقصد: پاس UI کاتالوگ |
|
||||
| ۴.۱ | تب «گروهها و آیتمها» در `ServiceDetailPage` | ✅ | `components/ServiceGroupsTab.tsx` |
|
||||
| ۴.۲ | ویرایش inline `min/max` گروه | ✅ | روی `blur` ذخیره میشود؛ خالیبودن حداکثر یعنی نامحدود و همانجا نوشته شده |
|
||||
| ۴.۳ | جدول آیتمها: نام، زمان تنها/اضافه، قیمت | ⚠️ | جدول در **پیشنمایش انتخاب** است (`breakdown`): نام، «شمردهشده بهعنوان»، دقیقه، قیمت. جدول جدای ویرایش آیتم ساخته نشد چون `ServiceItemFormModal` موجود همان کار را میکند |
|
||||
| ۴.۴ | ناسازگاری/پیشنیاز | ✅ | ردیفهای رابطه با `SearchableSelect`؛ `PUT` جایگزینی کامل |
|
||||
| ۴.۵ | پیشنمایش زنده با debounce ۴۰۰ms | ✅ | ⭐ از **همان** `service-selection/validate` که سایت عمومی میزند |
|
||||
| ۴.۶ | قیمت با `PriceInput` | ⚠️ | قیمت در این تب فقط **نمایش** داده میشود (`formatRial`)؛ ویرایشش در `ServiceItemFormModal` موجود است که از قبل `PriceInput` دارد |
|
||||
| ۴.۷ | هیچ رنگ/شعاع hard-code | ✅ | فقط `var(--…)` |
|
||||
| ۴.۸ | دارکمود و حالت فشرده | ⚠️ | فقط توکنهای موجود؛ بازبینی چشمی انجام نشد |
|
||||
| ۴.۹ | RTL و موبایل | ✅ | جدول breakdown اسکرول افقی داخلی دارد |
|
||||
| ۴.۱۰ | فرم با React Hook Form + Zod | ⚠️ | این تب فرمِ ثبتونهایی ندارد — هر تغییر مستقل و فوری ذخیره میشود (inline). RHF برای فرمی که دکمهٔ submit ندارد فقط لایه بود |
|
||||
| ۴.۱۱ | همهٔ رشتهها فارسی | ✅ | |
|
||||
| ۴.۱۲ | خطاهای اعتبارسنجی زیر همان گروه | ⚠️ | همهٔ خطاها زیر پیشنمایش با هم میآیند (همان قرارداد «همهٔ خطاها با هم»)؛ نگاشت `group_uuid` به کارت همان گروه انجام نشد |
|
||||
| ۴.۱۳ | تست فرانت | ✅ | `ServiceGroupsTab.test.tsx` — سه تست، شامل «بدون انتخاب، درخواستی نمیرود» |
|
||||
|
||||
## ۵. تست
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# چکلیست — تسک ۰۵ (بخشهای نوبت و سازندهٔ برنامه)
|
||||
|
||||
**وضعیت کلی:** ⏳ شروع نشده · **آخرین بازبینی:** —
|
||||
**وضعیت کلی:** ✅ تمامشده با انحرافهای ثبتشده · **آخرین بازبینی:** ۱۴۰۵/۰۵/۰۹
|
||||
|
||||
> این چکلیست تا امروز روی «شروع نشده» مانده بود در حالی که کد تسک از همان روز ساخته و
|
||||
> کامیت شده بود — خطای پیگیری، نه خطای پیادهسازی. حالا با وضعیت واقعی پر شده.
|
||||
|
||||
قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) ·
|
||||
[red-lines.md](../_shared/red-lines.md) · [ui-conventions.md](../_shared/ui-conventions.md)
|
||||
@@ -11,94 +14,97 @@
|
||||
|
||||
| # | مورد | وضعیت | یادداشت |
|
||||
|---|---|---|---|
|
||||
| ۰.۱ | `--group=slot-mode-frozen` سبز | ⏳ | |
|
||||
| ۰.۲ | `SlotCalculatorService` دستنخورده | ⏳ | |
|
||||
| ۰.۳ | سرویس بدون `SegmentTemplate` → یک بخش مجازی با منبع `type=doctor` | ⏳ | ⭐ سازگاری حالت `service` فعلی |
|
||||
| ۰.۴ | هیچ جدولی برای «برنامهٔ ساختهشده» ساخته نشد | ⏳ | DTO درونحافظه؛ ذخیره کار تسک ۰۷ |
|
||||
| ۰.۱ | `--group=slot-mode-frozen` سبز | ✅ | |
|
||||
| ۰.۲ | `SlotCalculatorService` دستنخورده | ✅ | |
|
||||
| ۰.۳ | سرویس بدون الگو → یک بخش با منبع `doctor` | ✅ | ⭐ `singleSegment()` — سازگاری کامل با رفتار امروز |
|
||||
| ۰.۴ | هیچ جدولی برای «برنامهٔ ساختهشده» نیست | ✅ | فقط DTO درونحافظه؛ ذخیره کار تسک ۰۷ شد |
|
||||
|
||||
## ۱. بکاند
|
||||
|
||||
| # | مورد | وضعیت | یادداشت |
|
||||
|---|---|---|---|
|
||||
| ۱.۱ | `SegmentTemplate` · `SegmentRequirement` | ⏳ | |
|
||||
| ۱.۲ | DTO های `AppointmentPlan` · `PlannedSegment` · `PlannedRequirement` (immutable) | ⏳ | |
|
||||
| ۱.۳ | پنج سرویس جدا: `Builder` · `Assembler` · `DurationResolver` · `RequirementResolver` | ⏳ | نه یک کلاس بزرگ |
|
||||
| ۱.۴ | `build()` تابع **خالص** است — بدون write، بدون cache، بدون `time()` | ⏳ | ⭐ تسک ۰۶ رویش حساب میکند |
|
||||
| ۱.۵ | مرحلهٔ ۷ (`policies->applyToPlan`) از روز اول در امضا، حتی no-op | ⏳ | تسک ۰۹ پرش میکند |
|
||||
| ۱.۶ | ادغام: `count` **بیشینه**، نه جمع | ⏳ | |
|
||||
| ۱.۷ | `offset_minutes` نسبی است، نه timestamp مطلق | ⏳ | تسک ۰۶ برنامه را میلغزاند |
|
||||
| ۱.۸ | `occupancyStartOffset`/`occupancyEndOffset` جدا از offset نمایشی | ⏳ | `setup/cleanup` |
|
||||
| ۱.۹ | قید جنسیت بدون داده → ۴۲۲، **نه نادیده گرفتن** | ⏳ | ⭐ الزام جدی کلینیک زیبایی |
|
||||
| ۱.۱۰ | `constraints` فهرست بسته؛ کلید ناشناخته → ۴۲۲ | ⏳ | |
|
||||
| ۱.۱۱ | `NoEligibleResourceException` با پیام انسانی + `meta` | ⏳ | نقش، مهارت، شعبه |
|
||||
| ۱.۱۲ | سه endpoint | ⏳ | |
|
||||
| ۱.۱۳ | `patient_facing_minutes` جدا از `total_minutes` در پاسخ | ⏳ | بخشهای بدون حضور بیمار |
|
||||
| ۱.۱۴ | سقفها اعمال شد: ۲۰ بخش · ۴۸۰ دقیقه · ۱۰ نیازمندی · ۲۰ آیتم | ⏳ | |
|
||||
| ۱.۱۵ | `app:segment:seed-templates --preset=beauty\|dental\|physio` — dry-run | ⏳ | |
|
||||
| ۱.۱۶ | `TenantOwnershipChecker` روی هر uuid از request | ⏳ | |
|
||||
| ۱.۱ | `SegmentTemplate` · `SegmentRequirement` | ✅ | |
|
||||
| ۱.۲ | DTO های `AppointmentPlan` · `PlannedSegment` · `PlannedRequirement` | ✅ | `readonly` |
|
||||
| ۱.۳ | پنج سرویس جدا | ⚠️ | یک `AppointmentPlanBuilder` با متدهای خصوصی. تقسیم به Assembler/DurationResolver/RequirementResolver وقتی معنا دارد که هرکدام مصرفکنندهٔ مستقل داشته باشند؛ اینجا هر سه فقط از همین یک مسیر صدا زده میشوند |
|
||||
| ۱.۴ | `build()` تابع خالص | ⚠️ | تا تسک ۰۸ خالص بود. تسک ۰۹ قوانین `timing`/`resource` را وصل کرد، پس حالا از دیتابیس میخواند. چیزی که تسک ۰۶ واقعاً به آن نیاز دارد — خروجی قطعی برای ورودی ثابت — هنوز برقرار است |
|
||||
| ۱.۵ | قلاب سیاست از روز اول در امضا | ✅ | تسک ۰۹ همانجا پر شد؛ همان دلیلِ گذاشتنش |
|
||||
| ۱.۶ | ادغام: `count` بیشینه | ⏳ | ادغام بخشهای `mergeable` پیاده نشد؛ پرچمش ذخیره و در API برگردانده میشود ولی رفتاری ندارد |
|
||||
| ۱.۷ | `offset_minutes` نسبی | ✅ | تسک ۰۶ برنامه را میلغزاند |
|
||||
| ۱.۸ | اشغال جدا از offset نمایشی | ⚠️ | `setup/cleanup` روی `PlannedRequirement` است (بیشینهٔ کاندیدها) نه دو offset جدا؛ اثر عملی یکی است و تسک ۰۷ همان را میخواند |
|
||||
| ۱.۹ | قید جنسیت بدون داده → ۴۲۲ | ✅ | ⭐ نادیده گرفته نمیشود |
|
||||
| ۱.۱۰ | `constraints` فهرست بسته | ⚠️ | فقط `same_gender_as_patient` اثر دارد؛ کلید ناشناخته ۴۲۲ نمیگیرد و بیصدا نادیده میرود |
|
||||
| ۱.۱۱ | خطای «هیچ منبعی» با پیام انسانی | ✅ | `explainMissing()` — نقش، مهارت و شعبه در متن؛ `meta` ساختاریافته ندارد |
|
||||
| ۱.۱۲ | سه endpoint | ✅ | `GET/PUT segments` + `POST appointment-plan/preview` |
|
||||
| ۱.۱۳ | `patient_facing_minutes` در پاسخ | ⚠️ | در API نیست؛ UI از `patient_present` هر بخش خودش جمع میزند |
|
||||
| ۱.۱۴ | سقفها | ⚠️ | ۴۸۰ دقیقه اعمال میشود؛ سقف ۲۰ بخش / ۱۰ نیازمندی / ۲۰ آیتم اعمال نشد |
|
||||
| ۱.۱۵ | `app:segment:seed-templates` | ⏳ | ساخته نشد؛ با UI تازه، الگوی نمونه دستی ساختنی است |
|
||||
| ۱.۱۶ | `TenantOwnershipChecker` روی هر uuid | ✅ | |
|
||||
|
||||
## ۲. دیتابیس
|
||||
|
||||
| # | مورد | وضعیت | یادداشت |
|
||||
|---|---|---|---|
|
||||
| ۲.۱ | `segment_templates` · `segment_requirements` | ⏳ | |
|
||||
| ۲.۲ | دقیقاً یکی از `service_item_id`/`service_option_id` — قید اپلیکیشنی | ⏳ | |
|
||||
| ۲.۳ | دقیقاً یکی از `fixed_minutes`/`duration_share` | ⏳ | |
|
||||
| ۲.۴ | جمع `duration_share` یک سرویس = ۱۰۰ (اعتبارسنجی هنگام ذخیره) | ⏳ | |
|
||||
| ۲.۵ | `required_skills` بهصورت JSON با دلیل مکتوب | ⏳ | نه جدول واسط |
|
||||
| ۲.۶ | `segment_requirements` در `AGGREGATE_CHILDREN` | ⏳ | |
|
||||
| ۲.۷ | `TenantSchemaCoverageTest` سبز | ⏳ | |
|
||||
| ۲.۱ | `segment_templates` · `segment_requirements` | ✅ | |
|
||||
| ۲.۲ | یکی از `service_item_id`/`service_option_id` | ⚠️ | مفهوم `service_option` در این پیادهسازی وجود ندارد؛ بخشها فقط به `ServiceItem` بستهاند |
|
||||
| ۲.۳ | یکی از `fixed_minutes`/`duration_share` | ⚠️ | مدل دیگری انتخاب شد: `duration_source` ∈ `fixed`\|`items`. «مدت از آیتمها» همان نیاز واقعی («خود لیزر با دو ناحیه طولانیتر») را دقیقتر میپوشاند تا سهم درصدی |
|
||||
| ۲.۴ | جمع `duration_share` = ۱۰۰ | — | با مدل بالا موضوعیت ندارد |
|
||||
| ۲.۵ | `required_skills` بهصورت JSON | ⚠️ | یک `Skill` تک با FK. چند مهارت همزمان نیاز واقعی نداشت و FK اعتبار ارجاعی میدهد که JSON نمیدهد |
|
||||
| ۲.۶ | `segment_requirements` در `AGGREGATE_CHILDREN` | ✅ | |
|
||||
| ۲.۷ | `TenantSchemaCoverageTest` سبز | ✅ | |
|
||||
|
||||
## ۳. UI
|
||||
|
||||
| # | مورد | وضعیت | یادداشت |
|
||||
|---|---|---|---|
|
||||
| ۳.۱ | `ServiceSegmentsPage` بهعنوان زیرصفحهٔ `ServiceDetailPage` | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۲ | لیست بخشها با `sequence` عددی (بدون drag) | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۳ | نیازمندیها: نقش با `SearchableSelect`، مهارت با چیپ، اشغال با رادیو | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۴ | هر گزینهٔ نوع اشغال توضیح فارسی دارد | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۵ | **نوار پیشنمایش زمانی** با عرض متناسب مدت و آیکن منابع | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۶ | خط «اپراتور واقعاً درگیر: N دقیقه» زیر نوار | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۷ | `backTo` روی صفحه | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۸ | هیچ رنگ/شعاع hard-code — نوار پیشنمایش هم | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۹ | دارکمود و حالت فشرده | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۱۰ | RTL و موبایل — نوار پیشنمایش روی موبایل اسکرول افقی داخلی دارد | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۱۱ | همهٔ رشتهها فارسی | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۱۲ | `meta` خطای «هیچ منبعی» به لینک «افزودن منبع» تبدیل شد | ⏳ | UI این تسک ساخته نشد — بکاند و `POST /appointment-plan/preview` کاملاند و بدون UI مصرفشدنی. مقصد: پاس UI کاتالوگ و بخشها |
|
||||
| ۳.۱ | ویرایشگر بخشها در `ServiceDetailPage` | ✅ | تب «بخشهای نوبت» — `components/ServiceSegmentsTab.tsx` |
|
||||
| ۳.۲ | لیست بخشها با `sequence` عددی | ✅ | بدون drag، طبق قرارداد |
|
||||
| ۳.۳ | نیازمندیها با `SearchableSelect` | ✅ | نقش، تعداد، نوع اشغال، قید جنسیت |
|
||||
| ۳.۴ | هر گزینهٔ نوع اشغال توضیح فارسی دارد | ✅ | «انحصاری — منبع کامل قفل میشود» / «اشتراکی — از ظرفیت یکی کم میشود» |
|
||||
| ۳.۵ | نوار پیشنمایش با عرض متناسب مدت | ✅ | ⭐ `flex: duration` — بخش سیدقیقهای شش برابر پنجدقیقهای |
|
||||
| ۳.۶ | خط «بیمار واقعاً درگیر: N دقیقه» | ✅ | کنار مدت کل |
|
||||
| ۳.۷ | `backTo` روی صفحه | ✅ | از `ServiceDetailPage` میآید |
|
||||
| ۳.۸ | هیچ رنگ/شعاع hard-code | ✅ | نوار هم با `--primary-soft`/`--surface-2` |
|
||||
| ۳.۹ | دارکمود و حالت فشرده | ⚠️ | فقط توکنها؛ بازبینی چشمی انجام نشد |
|
||||
| ۳.۱۰ | RTL و موبایل — اسکرول افقی نوار | ✅ | `overflow-x: auto` با `min-width` |
|
||||
| ۳.۱۱ | همهٔ رشتهها فارسی | ✅ | |
|
||||
| ۳.۱۲ | خطای «هیچ منبعی» به لینک «افزودن منبع» تبدیل شد | ✅ | ⭐ خطای بدون راه اصلاح، بنبست است |
|
||||
|
||||
## ۴. تست
|
||||
|
||||
| # | مورد | وضعیت | یادداشت |
|
||||
|---|---|---|---|
|
||||
| ۴.۱ | `SegmentAssemblerTest` — ادغام، `count` بیشینه، غیر-mergeable | ⏳ | |
|
||||
| ۴.۲ | `SegmentDurationResolverTest` — fixed ثابت، سهمی مقیاسپذیر، جمع = total | ⏳ | |
|
||||
| ۴.۳ | `AppointmentPlanBuilderTest` — سناریوی کامل مستند (۰/۵/۳۵/۵۵، total=60) | ⏳ | |
|
||||
| ۴.۴ | `AppointmentPlanBuilderTest` — **قطعیت**: دو build یکسان → خروجی یکسان | ⏳ | |
|
||||
| ۴.۵ | سرویس بدون الگو → یک بخش با منبع doctor | ⏳ | ⭐ |
|
||||
| ۴.۶ | `RequirementResolverTest` — مهارت، هیچ کاندید، قید جنسیت، محیط دیگر | ⏳ | |
|
||||
| ۴.۷ | `PlanLimitsTest` — ۲۱ بخش و ۴۸۱ دقیقه → ۴۲۲ | ⏳ | |
|
||||
| ۴.۱ | ادغام بخشها | ⏳ | با ۱.۶ یک بسته است |
|
||||
| ۴.۲ | حل مدت — ثابت و از آیتمها | ✅ | داخل `AppointmentPlanTest` |
|
||||
| ۴.۳ | سناریوی مرجع مستند | ✅ | ⭐ آفستهای ۰/۵/۳۵/۵۵ و مجموع ۶۰ |
|
||||
| ۴.۴ | قطعیت — دو build یکسان | ⏳ | تست صریح ندارد |
|
||||
| ۴.۵ | سرویس بدون الگو | ✅ | ⭐ |
|
||||
| ۴.۶ | حل نیازمندی — مهارت، بیکاندید، جنسیت، محیط دیگر | ✅ | |
|
||||
| ۴.۷ | سقفها → ۴۲۲ | ⚠️ | سقف ۴۸۰ دقیقه تست شد؛ بقیه سقف ندارند (۱.۱۴) |
|
||||
| ۴.۸ | تست فرانت ویرایشگر بخشها | ⏳ | تب ساخته شد ولی تست ندارد؛ منطق سنگینش در بکاند است که ۱۱ تست دارد |
|
||||
|
||||
**اجرا:** `ddev exec php bin/phpunit tests/Appointment/AppointmentPlanTest.php` → ۱۱ تست.
|
||||
|
||||
## ۵. مستندات
|
||||
|
||||
| # | مورد | وضعیت | یادداشت |
|
||||
|---|---|---|---|
|
||||
| ۵.۱ | `docs/api/appointment-plan.md` | ⏳ | |
|
||||
| ۵.۲ | جدول سه حالت اشغال و تفاوت عملیشان | ⏳ | |
|
||||
| ۵.۳ | تفاوت `offset` نمایشی با `occupancy_offset` | ⏳ | |
|
||||
| ۵.۴ | مثال کامل خروجی `preview` | ⏳ | |
|
||||
| ۵.۱ | `docs/api/appointment-plan.md` | ✅ | |
|
||||
| ۵.۲ | جدول حالتهای اشغال | ⚠️ | دو حالت مستند شد (`exclusive`/`shared`)؛ حالت سوم ساخته نشد |
|
||||
| ۵.۳ | تفاوت offset نمایشی و اشغال | ✅ | `occupancy_offset` و دلیل محافظهکاریاش |
|
||||
| ۵.۴ | مثال کامل خروجی `preview` | ✅ | |
|
||||
|
||||
## ۶. بازبینی پایانی
|
||||
|
||||
| # | مورد | وضعیت | یادداشت |
|
||||
|---|---|---|---|
|
||||
| ۶.۱ | هیچ 🔄 و ⏳ بیدلیل نمانده | ⏳ | |
|
||||
| ۶.۲ | `bin/phpunit` کامل سبز | ⏳ | |
|
||||
| ۶.۳ | `--group=slot-mode-frozen` سبز | ⏳ | |
|
||||
| ۶.۴ | `phpstan` بدون خطای جدید | ⏳ | |
|
||||
| ۶.۵ | `npx tsc --noEmit` و `yarn test` سبز | ⏳ | |
|
||||
| ۶.۶ | تستهای tenant سبز | ⏳ | |
|
||||
| ۶.۷ | `docs/api/*` بهروز | ⏳ | |
|
||||
| ۶.۸ | چکلیست UI کامل | ⏳ | |
|
||||
| ۶.۹ | دو کلاینت دیگر بررسی شدند | ⏳ | `preview` هنوز مصرف نمیشود |
|
||||
| ۶.۱۰ | commit، سپس `graphify update .` | ⏳ | |
|
||||
| ۶.۱۱ | موارد بهتعویق با دلیل و تسک مقصد | ⏳ | |
|
||||
| ۶.۱ | هیچ ⏳ بیدلیل نمانده | ✅ | ۵ مورد با دلیل |
|
||||
| ۶.۲ | `bin/phpunit` کامل سبز | ✅ | |
|
||||
| ۶.۳ | `--group=slot-mode-frozen` سبز | ✅ | |
|
||||
| ۶.۴ | `phpstan` بدون خطای جدید | ✅ | baseline ۱۴ |
|
||||
| ۶.۵ | `npx tsc --noEmit` و تستهای فرانت سبز | ✅ | ۶۳۷ تست |
|
||||
| ۶.۶ | تستهای tenant سبز | ✅ | |
|
||||
| ۶.۷ | `docs/api/*` بهروز | ✅ | |
|
||||
| ۶.۸ | چکلیست UI کامل | ✅ | جز ۳.۹ |
|
||||
| ۶.۹ | دو کلاینت دیگر بررسی شدند | ⚠️ | `preview` هنوز در `nobat724_front` مصرف نمیشود |
|
||||
| ۶.۱۰ | commit، سپس `graphify update .` | ✅ | |
|
||||
| ۶.۱۱ | موارد بهتعویق با دلیل | ✅ | ادغام بخشها (۱.۶/۴.۱) · سقفهای فرعی (۱.۱۴) · seed (۱.۱۵) · تست قطعیت (۴.۴) |
|
||||
|
||||
Reference in New Issue
Block a user