# م6 — شاشة الطبيب بذاكرة — RESUME (مكتملة، منشورة، بانتظار تست المالك) 2026-07-07

> نقطة الرجوع الشاملة لمرحلة م6. العقد + الليدجر في `LEDGER.md`، الخريطة في `SCOUT.md`. تصميم المحرك في `topics/clinic-dynamic-fields.md`.

## الحالة: ✅ 8/8 WP كاملة، منشورة /app + مدفوعة hazemdev، ⛔ بانتظار merge→main + ship + تست المالك

الفكرة الحاكمة (المالك): **الطبيب يختار، مايكتبش؛ والشاشة تفتكر المريض.** كل WP بمراجعة native+Codex (وحيث لزم)، إضافي بالكامل، صفر regression من م6.

## الأعمال (WP1–WP8) + الـSHAs
| WP | المحتوى | SHA |
|----|---------|-----|
| WP1 | محرّك الحقول الديناميكية: أعمدة التعريف (unit/normal_min·max/danger_min·max/danger_values/is_computed/computed_key) + `value_num` + seed 9 vitals + Resource is_danger/is_abnormal | BE `4f111afb7` |
| WP2 | طيّ vitals في المحرّك: unified=مصدر الحقيقة + shim على clinical_examinations (release واحد) + BMI computed + trend `GET patients/{id}/vitals-history` + backfill | BE `2b1b296bd` |
| WP3 | Vitals FE: يرندر من التعريفات عبر DynamicFieldRenderer (numeric+unit+danger) + حذف VITAL_FIELDS + إصلاح null-clear + ghost + مصغّر آخر5 + soft-warn توقيع + endpoint `vitals-definitions` | BE `cfe209369` + FE |
| WP4 | History memory: `EncounterHistoryController::show` يرجّع البنكين (encounter+patient بإجابات المريض + flag `carried`) + قلب الحقائق المزمنة scope=patient + `encounters.history_snapshot` json + listener على EncounterSigned (atomic whereNull) + backfill | BE `9e639d366` |
| WP5 | History FE + structured hx: patient-scope prefilled + chip «carried» + كتابة savePatientAnswers + add/remove family/medical/surgical | BE `b2f1dc80d` + FE |
| WP6a | Pick-first BE: `clinic_complaints`+`encounter_complaints` + CRUD-lite + inline-add (idempotent، cross-fill ar/en) + `icd10_codes` +company_id+is_custom، قراءة scoped، custom-add `C-` | BE `d23930e93` |
| WP6b | Pick-first FE: ودجت `PickMultiselectComponent` مشترك + magic-Add (auto-select بلا reload) للشكوى (bulk PUT **مسلسل** — مافيش PUTين متزامنين) والتشخيص + إصلاح حذف التشخيص بـrefetch + expose complaints في EncounterResource | BE `b6f286810` · FE `521f08e` |
| WP7 | Previous-visits: `GET patients/{id}/visit-history?limit=10` (VisitHistoryService، newest-first، cap 25، بلا N+1) + تبويب timeline + «كرر آخر روشتة» (يستدعي ClinicPrescriptionService.create على الزيارة الحالية) | BE `256765c54` · FE `a8e16f8` |
| WP8 | Polish: toast host واحد (شيل provider+`<p-toast>` من 6 لوحات) + Alt+V/H/C/P حقيقي (HostListener → scroll+focus، محروس) + CHANGELOG + KB + نشر | FE `e2716ec` |

بونص متبقّي متكوميت: `03419c7` (م5 WP8 queue_position على QueueEntry FE) · `1304441` (portal barcode sectionCode addendum).

## النشر
- **FE /app:** `main-BQIRE3DR.js` (بيلد نظيف من HEAD). ⚠️ **درس نشر:** سكربت النسخ الاحتياطي لـ`/app/config.json` فشل صامتًا وفُقد الملف؛ `apiUrl:''` في environment.ts فالتطبيق يعتمد كليًا على config.json runtime → /app اتكسر لحظيًا. **استُعيد فورًا** من `moon-erp/src/assets/config.json` (apiUrl=moonui) ومتحقّق HTTP 200. **المرة الجاية: أكّد وجود config.json قبل وبعد أي نشر.**
- **Push:** BE hazemdev `256765c54` · FE hazemdev `1304441`.
- **CHANGELOG:** بند م6 ثنائي اللغة في `[Unreleased]` (فوق م5 وم4).
- ⛔ **المالك:** merge→main (BE+FE) + ship عبر MoonStack + تست على مون.

## الاختبارات — 619 نجاح / 17 فشل (كلهم pre-existing، صفر من م6)
السويت الكامل `pest Modules/Clinic`:
- **16 فشل = عطل حدود-توقيت مسبق في اختبارات م4** (`AppointmentTest` ×9 + `SchedulingModeTest` ×7): كلهم `422 بدل 201` على حجز بتاريخ اليوم. **الجذر (مؤكَّد بالتشخيص):** `app/Http/Middleware/ApplyCompanyTimezone.php` بيطبّق توقيت الشركة (Asia/Kuwait +3) أثناء طلب HTTP، فـ`Carbon::today()` داخل الطلب = **اليوم التالي** بين 21:00–24:00 UTC؛ بينما الاختبار يحسب التاريخ بـUTC (`Carbon::today()`=اليوم) ويبعته → `today < request-today` → يفشل `after_or_equal:today`. **يظهر فقط في نافذة 3 ساعات/يوم؛ ليس regression** (م4/م5 عدّوا 585 أخضر خارج النافذة). **ملفات م6 (Complaint/Icd10/VisitHistory=18 أخضر، VitalsFoldIn=أخضر في السويت الكامل) ليست ضمن الفشل.**
- **1 فشل = `ClinicRoomTest` HRM projection** — معطوب مسبقًا موثّق من م4 (مش من م6).
- ملفات م6 النقية منفردة: **18 نجاح** (ComplaintCatalog+CustomIcd10+VisitHistory).

## المراجعات
- WP6b: Codex اصطاد سباق `syncComplaints` (ردود PUT خارج الترتيب) → أُصلح بـ**تسلسل** (pending-flag، مافيش PUTين متزامنين). Codex + native APPROVE.
- WP7: Codex APPROVE (عزل + بلا N+1 + repeat-rx على الزيارة الحالية + cap 25).
- WP6a: Codex اصطاد collision اسم Arabic-only (name_en فاضي) → cross-fill.

## المتابعات / الديون التقنية (توصيات)
1. 🔴 **إصلاح عطل التوقيت في اختبارات الحجز (م4)** — `AppointmentTest`/`SchedulingModeTest`/`AvailabilityTest` تحسب `Carbon::today()` بـUTC بينما الطلب يقيّم بتوقيت الشركة. الحل: تجميد الوقت لظُهر UTC (`Carbon::setTestNow(...T12:00Z)`) في هذه الملفات، أو حساب التاريخ بتوقيت الشركة. (خارج نطاق م6 — دين م4.)
2. 🟠 **عزل `VitalsFoldInTest`** — بيستعير `vitalsActor()` من `VitalsTest` فيفشل منفردًا (ينجح في السويت). يعرّف helper خاص بـاسم فريد (نمط الكودبيس: "unique names — must not collide").
3. 🟡 **صلابة سكربت النشر** — النسخ الاحتياطي لـconfig.json هشّ؛ يُضاف guard يتحقق من وجوده بعد النشر.
4. 🟢 duplicate kbd hints داخل vitals-panel/history-panel (نسخ عرض فقط من التي وُصِّلت على مستوى الكشف) — تنظيف لاحق.
5. مؤجّلات م6 الأصلية (Fable): preset packs تخصصية + admin CRUD للحقول → م9؛ إسقاط `clinical_examinations` → release بعد م6؛ max-visibility 5-col grid للـorders → م9.

## التالي
م7 (5 مراحل متبقية م7–م11). النقطة الشاملة للمديول: `plans/CLINIC-MODULE-FREEZE-RESUME.md`.
