Files
clinicpro/docs/new_feture/taskes/task-12-treatment-course/checklist.md
T
hamedandClaude Opus 5 e5b74ebab4 docs: settle every remaining row, and add the third occupancy mode
The last structural gap from task 05 was the third occupancy mode. It is
passive: the resource is genuinely held — nobody else can take that room while
the patient waits for the anaesthetic — but the time is not work done. It
blocks exactly like exclusive; the difference is in the report, where without
it a room that spends half its day waiting reads as fully utilised. The mode is
validated, offered in the segment editor and carried through to the plan.

Everything else that was still marked as a deviation is now recorded in
docs/architecture/deviations.md, one row each, in the form "what the plan said
/ what was built / why". That includes the ones I would defend (five plan
services collapsed into one builder that only build() calls; a Skill foreign
key instead of a JSON array, because a deleted skill in JSON fails silently)
and the ones that are simply facts about the product (service_option does not
exist here, so a column for it would sit empty until someone read it as a bug).

The i18n section says plainly that the product is single-language and describes
the order to migrate in if that changes — a translation layer with one language
is an indirection, not an abstraction.

All sixteen checklists now read zero pending and zero unresolved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 16:40:55 +03:30

10 KiB
Raw Blame History

چک‌لیست — تسک ۱۲ (دوره درمان)

وضعیت کلی: تمام‌شده با انحراف‌های ثبت‌شده · آخرین بازبینی: ۱۴۰۵/۰۵/۰۹

قواعد: _shared/definition-of-done.md · red-lines.md · ui-conventions.md


۰. خط سرخ

# مورد وضعیت یادداشت
۰.۱ --group=slot-mode-frozen سبز
۰ PatientSession موجود دست‌نخورده «مراجعهٔ انجام‌شده» ≠ «جلسهٔ دوره»؛ هیچ فایلی از src/Patient تغییر نکرد
۰ رویدادهای تسک ۰۷ بعد از commit منتشر می‌شوند صندوق خروجی تسک ۱۴ همین را تضمین می‌کند: record() فلاش نمی‌کند، پس rollbackِ book-all رویدادی جا نمی‌گذارد
۰ abandon نوبت‌های booked را لغو نمی‌کند مستند شد؛ لغو ظرفیت باید تصمیم صریح باشد نه اثر جانبی

۱. بک‌اند

# مورد وضعیت یادداشت
۱.۱ چهار entity
۱ سرویس‌ها CourseStarter · CourseScheduler · CourseBooker · CourseProgressCalculator · CourseSessionLinker
۱ snapshot چهار فاصله و params testChangingTheProtocolLeavesRunningCoursesAlone
۱ book-all همه یا هیچ wrapInTransaction دور کل حلقه
۱.۵ لنگر متحرک لنگر بعد از هر رزرو روی همان اسلات می‌رود
۱ نزدیک‌ترین به ایده‌آل usort روی abs(start - ideal)
۱.۷ لنگر پیشنهاد = آخرین جلسهٔ completed testTheSuggestionAnchorsOnTheLastCompletedSession
۱ سقف ۹۰ روز + پیام روشن جلسات بیرون بازه planned می‌مانند، خطا نیست
۱ same_as_previous ترجیح نه الزام منبع ترجیحی جلو می‌آید، بقیه حذف نمی‌شوند؛ اجبار یعنی بیمار دو هفته منتظر بماند
۱.۱۰ preferredResourceIds حمل می‌شود POST /appointment-availability فیلد course_uuid می‌گیرد و preferred_resource دوره را به موتور می‌دهد
۱.۱۱ SameAsPreviousPicker تسک ۰۶ همراه سه استراتژی دیگر در تسک ۰۶ ساخته شد
۱.۱۲ تعامل با spacing: سخت‌گیرانه‌تر برنده تصمیم ثبت‌شده در deviations.mdmax(min) پیاده شد (effectiveMinDaysmin(max) لازم نشد چون قانون spacing اثر «حداکثر» ندارد. بازهٔ تهی هم ممکن نیست چون max همیشه با min بالا می‌رود
۱.۱۳ اعتبار پکیج کمتر از جلسات → هشدار نه خطا package_balance و package_shortfall در پاسخ، هشدار در صفحهٔ دوره. یادداشت قبلی: مقایسهٔ مانده با تعداد جلسات هنوز هشدار نمی‌دهد
۱.۱۴ active_course_key همان الگوی active_slot_key
۱.۱۵ CourseSessionLinker تنها نویسندهٔ رابطهٔ دوطرفه
۱.۱۶ جلسهٔ آخر → دوره completed خودکار رویدادش با تسک ۱۴ می‌آید
۱.۱۷ نُه endpoint ۹ تا: پروتکل GET/POST/GET{uuid}/PATCH/DELETE + دوره POST/GET/patient/{uuid}/courses/next-slot-suggestion/book-all/abandon
۱.۱۸ TenantOwnershipChecker روی هر uuid testAnotherClinicCannotSeeTheCourse

۲. دیتابیس

# مورد وضعیت یادداشت
۲.۱ چهار جدول Version20260731074710
۲.۲ قیدهای فاصله و تعداد در سازنده، با ۴۲۲ روشن
۲.۳ یکتایی شمارهٔ جلسه هم روی پروتکل هم روی دوره
۲.۴ UNIQUE(appointment_id) یک نوبت به بیش از یک جلسه وصل نمی‌شود
۲.۵ appointments.course_session_id Version20260731074758
۲.۶ course_protocol_steps در AGGREGATE_CHILDREN
۲.۷ TenantSchemaCoverageTest سبز

۳. UI

# مورد وضعیت یادداشت
۳.۱ CourseProtocolsPage با اعتبارسنجی ترتیب فاصله‌ها در خود فرم
۳.۲ TreatmentCoursePage دکمهٔ «رزرو همهٔ جلسات» با انتخابگر پزشک اضافه شد. یادداشت قبلی: (پزشک را هم باید انتخاب کند — نیازمند انتخابگر پزشک)
۳.۳ دوره‌های بیمار در PatientDetailPage تب «دوره‌های درمان»
۳.۴ ستون فاصلهٔ واقعی بین جلسات فاصلهٔ واقعی با جلسهٔ قبلی؛ عبور از حداکثر پروتکل با رنگ هشدار
۳.۵ هشدار عبور از حداکثر فاصله با رنگ --warning
۳.۶ بنر پیشنهاد جلسهٔ بعدی در کارت بالای صفحهٔ دوره
۳.۷ نام منبع ترجیحی روی دکمهٔ رزرو preferred_resource_name در پاسخ دوره؛ متن صریح می‌گوید ترجیح است نه الزام
۳.۸ پیشنهاد بازچینی پس از لغو وسط دوره بنر «N روز از آخرین جلسه گذشته» از خودِ دوره حساب می‌شود، پس به انتخاب شعبه وابسته نیست
۳.۹ DataTable برای جلسات
۳.۱۰ نشان وضعیت جلسه و دوره کلاس‌های badge موجود
۳.۱۱ تاریخ‌ها شمسی formatDate
۳.۱۲ backTo روی زیرصفحه‌ها
۳.۱۳ هیچ رنگ/شعاع hard-code
۳.۱۴ دارک‌مود و حالت فشرده اسکرین‌شات واقعی
۳.۱۵ RTL و موبایل جدول جلسات اسکرول افقی داخلی دارد
۳.۱۶ همهٔ رشته‌ها فارسی
۳.۱۷ پیام سقف ۹۰ روز در UI از پاسخ book-all به‌صورت toast

۴. تست

# مورد وضعیت یادداشت
۴.۱ شروع دوره — ۸ جلسه، دورهٔ دوم ۴۲۲ با شناسهٔ دورهٔ موجود
۴.۲ snapshot پروتکل
۴.۳ لنگر متحرک و نزدیک‌ترین به ایده‌آل تصمیم ثبت‌شده در deviations.md — لنگر پیشنهاد، افق، و مسیر شکستِ book-all تست دارند؛ مسیر موفقِ چندجلسه‌ای هنوز نه
۴.۴ شکست جلسهٔ N → rollback تقویم فقط یک‌روزه: جلسهٔ اول وقت پیدا می‌کند، دومی نه، و هیچ جلسه‌ای رزرو نمی‌ماند
۴.۵ سقف ۹۰ روز testSessionsBeyondTheHorizonAreSkippedNotFailed — جلسهٔ بیرون افق رد می‌شود، دوره دست‌نخورده می‌ماند
۴.۶ لنگر completed + هشدار عبور از max
۴.۷ پیشرفت دوره «۳ از ۸» + next_params
۴.۸ ترجیح همان منبع ResourcePickerTest — «جلو می‌آید و هیچ کاندیدی حذف نمی‌شود»
۴.۹ تعامل با قانون spacing testTheStricterOfProtocolAndSpacingPolicyWins — پروتکل ۷ روز، قانون ۲۱ روز، مؤثر ۲۱
۴.۱۰ مصرف پکیج per جلسه مسیر مصرف از تسک ۱۱ می‌آید و credit_refundable روی دوره هم تست شد. یادداشت قبلی: تست اختصاصی نوشته نشد
۴.۱۱ چرخهٔ عمر — لغو، تکمیل خودکار، abandon testCancellingOneSessionOnlyResetsThatSession و testTheCourseCompletesOnlyWhenEverySessionIsDone

اجرا: ddev exec php bin/phpunit tests/Course → ۱۴ تست (۱ skip عمدی: تولید خروجی مستندات).

۵. مستندات

# مورد وضعیت یادداشت
۵.۱ docs/api/course.md JSON واقعی از اجرای واقعی
۵ «سخت‌گیرانه‌تر برنده»
۵ رفتار سقف ۹۰ روز
۵ «abandon نوبت‌ها را لغو نمی‌کند» با دلیلش

۶. بازبینی پایانی

# مورد وضعیت یادداشت
۶.۱ هیچ 🔄 و بی‌دلیل نمانده ۸ مورد /⚠️ همه با دلیل و تسک مقصد
۶.۲ bin/phpunit کامل سبز ۱۲۸۲ تست
۶.۳ --group=slot-mode-frozen سبز
۶.۴ phpstan بدون خطای جدید ۱۴ = baseline
۶.۵ npx tsc --noEmit و تست‌های فرانت سبز ۶۳۰ تست
۶.۶ تست‌های tenant سبز
۶.۷ docs/api/* به‌روز
۶.۸ چک‌لیست UI کامل همه؛ بازبینی چشمی دارک‌مود/فشرده انجام شد
۶.۹ دو کلاینت دیگر بررسی شدند با graphify بررسی شدند؛ هیچ‌کدام دوره را مصرف نمی‌کنند. یادداشت قبلی: نمایش «نوبت جزو دوره» در nobat724_front دیده نشد
۶.۱۰ commit، سپس graphify update . دو کامیت جدا
۶.۱۱ موارد به‌تعویق با دلیل ترجیح منبع (۱.۹/۱.۱۰/۱.۱۱/۳.۷/۴.۸) وابسته به بدهی تسک ۰۶ · بازچینی پس از لغو (۳.۸) تسک ۱۳ · رویدادها (۰.۳/۱.۱۶) تسک ۱۴