feat(course): show how the course is actually going, not just how it was planned

Three gaps on the treatment-course page, all of them about the difference
between the protocol and reality.

The sessions table listed each date but not the gap between them, leaving the
operator to subtract two Jalali dates in their head. It now shows the real gap
and colours it as a warning past the protocol maximum.

A course cancelled mid-way stretches silently: the session goes back to
planned and nobody is told. The suggestion endpoint does warn, but only once a
branch is picked, so the warning could go unseen indefinitely. The page now
derives "N days since the last session, past the protocol maximum" from the
course itself, so it shows immediately.

The course's preferred resource was applied by the engine but never named in
the UI. The API now returns preferred_resource_name alongside the uuid, and
the text says plainly that it is a preference — the engine moves it up the
list, it does not hold the slot.

Two backend tests that were owed: the stricter of the protocol spacing and a
spacing policy wins (protocol 7 days, policy 21, effective 21 — otherwise a
clinic's safety rule could be bypassed by writing a short protocol), and a
session whose earliest possible date falls outside the 90-day horizon is
skipped rather than failing book-all, leaving the course untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
hamed
2026-08-01 13:51:34 +03:30
co-authored by Claude Opus 5
parent 83704f9d30
commit e9e61adfee
7 changed files with 267 additions and 8 deletions
+7
View File
@@ -125,6 +125,7 @@
"max_days": 45,
"patient_package_uuid": null,
"preferred_resource_uuid": null,
"preferred_resource_name": null,
"status": "active",
"abandon_reason": null,
"started_at": 1785484481,
@@ -155,6 +156,12 @@
}
```
> `preferred_resource_name` نام همان منبع است و فقط برای نمایش می‌آید — پنل با آن روی
> پیشنهاد جلسهٔ بعدی می‌نویسد کدام دستگاه ترجیح داده می‌شود. **ترجیح است نه الزام:**
> موتور آن را جلوتر می‌آورد ولی اگر آزاد نباشد منبع دیگری می‌دهد، و متن UI هم همین را
> می‌گوید تا انتظار اشتباه نسازد.
### Errors
| Code | HTTP | Description |
|---|---|---|