# م9 (التأمين) — عقد Fable + ليدجر (2026-07-09)

> العقد المُلزِم (Fable 5). الخريطة `SCOUT.md`. **أخطر مرحلة GL** — WP1+WP4 مراجعة مزدوجة (native+Codex+Fable). المرجع: ملحق أ (H1-H4/M5/M6).

## نموذج الاعتراف (الحاكم)
اعتراف **مقسوم، نقطة واحدة لكل حصة:** حصة المريض (copay) عند تحصيل الإيصال (موجود، **بلا تغيير**، `PostReceiptJournalEntry`) → `clinic.revenue_account_id`/`clinic.ar_account_id`. حصة المؤمِّن عند **الاعتماد من `total_covered` المعتمد** → `payer_contracts.revenue_account_id` (authoritative) / `insurance_receivable_account_id`. **نتيجة مبسِّطة:** المؤمِّن مايتعرفش إلا عند الاعتماد → الرفض/الشطب = **صفر JE** (مفيش حاجة تُعكَس، مفيش bad-debt account في م9).

## الـJEs
- **B (adjudication accepted/partial — الوحيد الجديد):** Dr insurance_receivable = `total_covered` · Cr contract.revenue = `total_covered`. `entry_type=clinic_claim_adjudication` · `idempotency_key=clinic_claim_adj_{id}`. **مفيش سطور مريض، مفيش مبالغ مُقدَّمة.**
- Rejected/Write-off/Rebill/Assemble = صفر JE. Insurer cash settlement = مؤجّل (إيصال خزينة يدوي مؤقتًا).
- copay/shortfall delta = عرض فقط (badge)، بلا JE تلقائي.

## 📊 ليدجر
| WP | المحتوى | يعتمد | مراجعة | الحالة |
|----|---------|-------|--------|--------|
| WP1 | **recognition core (H1+H2+M6) [GL-CRITICAL]:** action `AdjudicateClaim` (كاتب واحد يدوي+NPHIES؛ guard Submitted؛ fail-before-write على contract GL؛ validate؛ DB::transaction → dispatch ClaimAdjudicated). إعادة كتابة `ApplyAdjudicationToLedger` = JE B فقط (من total_covered، شيل سطور المريض والإجمالي، covered>0). M6: شيل try/catch (يرمي→rollback). refactor NPHIES writeback ينادي AdjudicateClaim (per-line). JE type جديد. assemble duplicate-guard (يرفض claim فعّال ثاني للأوردر). | — | **native+Codex+Fable** | ✅ |
| WP2 | **manual adjudication (H3):** `POST clinic/claims/{claim}/adjudicate` (perm جديد `clinic.claim.adjudicate`) + FormRequest (outcome/covered/copay/reason/lines?) wrapper على AdjudicateClaim. يشتغل manual+NPHIES. | WP1 | Codex | ✅ |
| WP3 | **write-off+rebill:** ClaimStatus `WrittenOff` + migration `2026_07_09_000010` (adjudication_ref/rejection_reason/adjudicated_by/written_off_*/rebilled_from|to). `POST writeoff` (perm `clinic.claim.writeoff`، status=Rejected، صفر JE). `POST rebill` (perm assemble، Rejected/WrittenOff، re-assemble مش clone، يربط rebilled_from/to). | WP1 | Codex | ✅ |
| WP4 | **caps live (M5) [GL-CRITICAL]:** enforce عند line-add (freeze-aware، seeded من snapshot — **F-A** مايعيدش التسعير) + annual YTD حقيقي + **F-B** qty scaling للتغطية. call sites: AddServiceOrderLine + updateLine + line-cancel (لو payer_contract). VisitQuoteService يطابق. **شيل تسجيل ServiceRendered الميت + H4 party-accrual مؤجّل رسميًا.** | — | **native+Codex+Fable** | ✅ |
| WP5 | **FE claim detail + actions:** `insurance/claims/:id` (getClaimById) — timeline + submitted/expected/adjudicated + copay_delta badge + lines + actions (record-adjudication/write-off/rebill perm-gated) + list→detail link. | WP2·WP3 | single | ✅ |
| WP6 | **integration sweep + check script:** رحلة مؤمَّنة كاملة (cap→collect→assemble→adjudicate partial→invariant واحد-اعتراف→reject→writeoff→rebill→accept) + سكربت يفلّق JEs `clinic_claim_adj_%` المعطوبة على dev (void قبل retest) + CHANGELOG + KB. | الكل | single | ⬜ |

**DAG:** WP1 ‖ WP4 (full-kit، منفصلين) → WP2‖WP3 بعد WP1 → WP5 بعد WP2+WP3 → WP6. migration واحدة (WP3، ≥ `2026_07_08_000020`).

## قرارات للمالك (flag، مش بلوكر)
حسابا إيراد (per-contract insurer + setting patient) تصميم مقصود · copay-delta عرض فقط v1 · **H4 عمولات مؤجّل رسميًا** (تعارض نموذج الاعتراف) · annual cap = سنة تقويمية per patient+contract · PartiallyPaid = «موافقة جزئية» (label FE) · مؤجّلات: insurer cash settlement + aging · bad-debt للمؤمِّن غير المدفوع · auto patient-delta billing · ServiceRendered/H4 · contract-anniversary caps.

## ⚠️ dev data: JEs `clinic_claim_adj_*` قديمة اتقيّدت بالخطأ (نفس الـkey هيعيد استخدامها) → WP6 سكربت void قبل الـretest.
