# Moon ERP — what exists for IVF / fertility (read-only map, 2026-10-24)

**Bottom line:** fertility is built *clinically* (couple assessment, semen with automatic WHO 2021, prior ART, OI/IVF cycle cards). The **IVF lab** is not built: no per-oocyte / per-embryo records, no cryobank, no lab worklist, no consents, no OPU/ET procedures, no KPIs. Lots to reuse nearby: LIS, ART billing codes, packages, day-case theatres, lot/expiry stock, documents, follow-ups.

BE = `/home/moonui3/moon-erp-be/Modules`, FE = `/home/moonui3/public_html/moon-erp/src/app/features`.

## 1. Fertility as built (G3a BE `094eed591`, G3b FE `cf5a4443`, cleanup `a77650fcf`)
- 6 definitions in `Gyn/database/data/gyn_schema.json` (= `p3c-schema-fert.js`), installed by `Gyn/database/migrations/2026_11_03_390000_install_gyn_fertility_modules.php` + `GynFieldPackSeeder`; no own tables. `infertility`, `semen`, `prev_art`, `diag_lap` = visit answers (`semen.sa`, `prev_art.cyc` repeats). `oi`/`ivf` = record-scope answers on `clinical_episodes` (`kind='treatment_cycle'`, `ref_type='gyn.cycle.oi|ivf'`). Behind `gyn.feature.fertility`.
- **IVF fields `gyn_ivf_*` (flat):** prep (kind IVF/ICSI/FET/egg freezing/PGT, attempt, protocol long/antagonist/short/PPOS/mild/natural/duostim, cd1, amh, afc, sperm ejaculate/frozen/TESA/TESE/micro-TESE/donor, center); stim (gn rFSH/HMG/uFSH/corifollitropin, dose, days, antag_cd, **`stim` table** per scan: cd, date, dose, et, r10, r14, r17, l10, l14, l17, e2, p4, lh; trigger hCG/rhCG/GnRHa/dual, trigger_dt **free text**, trigger_e2, ohss_risk); OPU/lab (opu_date, oocytes, mii, mi, gv, anesth, opu_comp, inseminated, fert 2PN, fert_rate computed, d3, blast, **grades free text**, pgt, euploid, lab_notes); transfer/freeze (et_type fresh/freeze-all/FET/cancelled, et_date, et_day, et_n, **et_grade text**, et_diff, et_blood, frozen count, frozen_stage, fet_prep, fet_et, **thaw_n text**, luteal, cancel_reason); outcome (hcg_date, hcg, hcg2, sac_date, sacs, fhr, outcome ongoing…live birth/multiple/OHSS/cancelled, ohss).
- **OI `gyn_oi_cycle_*`:** no, cd1, aim TI/IUI, meds, dose, start/end cd; `visits` table (cd, date, et, rf/lf free text, e2, decision); trigger (lead, et_trig, trigger, dt, cd); IUI (dt, prep, count); luteal; hcg; outcome.
- **Semen `gyn_semen_*`:** `sa_*` rows (date, lab, method conventional/CASA, abst, vol, conc, total computed, tm, pr, morph, vit, pus, interp computed); andrology (adv, FSH, LH, T, PRL, E2, inhibin, scrotal, karyotype, Yq, SDF, TESE, dx, plan). `Gyn/app/Support/SemenWho.php` WHO 2021 limits + flags, per-row computed in `Clinic/app/Services/HistoryService.php`; `fertRate()` = 2PN ÷ (inseminated ‖ MII); FE `gyn/engine/computed.ts`.
- **Prior ART rows:** year, center, kind, protocol, oocytes, MII, fert, embryos, transferred, grade, day, frozen, PGT, outcome, complication.
- **Cycle service** `Gyn/app/Services/TreatmentCycleService.php` (on C1 `EpisodeService`): open (one open cycle per patient), close (outcome required), cancel (reason, freezes), attach visit; read model with monitoring rows, lead follicle, fert_rate, AMH/AFC (from visit answers only, not LIS).
- **Endpoints** `api/gyn`: `GET|POST patients/{p}/cycles`, `GET cycles/{e}`, `POST cycles/{e}/close|cancel`, `PUT cycles/{e}/encounter`; husband `GET|PUT|POST|DELETE patients/{p}/spouse` (`GynSpouseService`, male `lab_patients` row, `spouse_patient_id` both sides); fields via `PUT api/clinic/records/clinical_episode/{id}/fields`.
- **Permissions** `gyn.cycles.view|manage`; roles gyn_consultant/doctor/team_member manage, nurse/sonographer view. **No embryologist / andrologist role.**
- **Summaries** `Gyn/app/Summary/{Infertility,Semen,PrevArt,Oi,Ivf,DiagLap}Template.php`; types `fertility`, `couple` (`Clinic/app/Clinical/ClinicalTypeRegistry.php:146,155`).
- **FE** `gyn/cards/gyn-cycle-cards.component.ts` (list, new cycle, collapsible card, attach/move, close/cancel), monitoring grid = `table` in `gyn/form/gyn-module-form.component.html:132`, `gyn/state/gyn-cycle.store.ts`, `gyn/cards/gyn-spouse-panel.component.ts`. Demo ICSI cycle in `Clinic/database/seeders/Demo/GynCases.php::ivf`.
- **Known gaps:** write guard can't see target record; fertility off doesn't hide fertility/couple summary types; no cycle follow-up rules; counts only (no per-oocyte/embryo); E2/P4/LH typed by hand; trigger time free text; no drug calendar; FET not linked to source cycle's frozen embryos; no consents, cryo, lab worklist, KPIs.

## 2. Reusable capabilities
| Capability | Where | Fit / gap |
|---|---|---|
| Semen panel | LIS `house_catalog.json`; plan `lis-casa-semen-analysis-plan.html` | Phase 1 done (manual seminogram); CASA phases 2–5 not started; LIS result (husband) and `gyn_semen_sa` rows (her visit) not synced |
| Hormones | `LIS/database/data/nafis_catalog.csv`: AMH, E2, FSH, LH, P4, β-hCG, PRL, T, inhibin | present but seeded `is_searchable=false`; abnormal flags/critical alerts exist; `PatientLabHistoryService::lastPerRef` can fill the stim grid |
| ART billing codes | NAFIS SBS 73400-* (oocyte identification, culture, ICSI ≤10/>10, hatching, ET prep, embryo/oocyte/sperm cryo, storage per year, thaw, PGD biopsy) | exist, inactive → configuration |
| Samples / worklists | `LabSample.barcode`, `LabSampleCustodyLog`, `WorklistController`, `LabSectionKanbanController` | andrology OK; no embryology worklist |
| Husband orders | spouse LIS patient row; `PrescriptionSubject::Spouse` | Rx for husband works; `ServiceOrderLine` has no subject → his labs can't be ordered from her visit |
| Packages | `PackageGrant`, `ClinicService.is_package`, `ClinicPackageRevenue` per_session | equal sessions only; IVF needs stage-based revenue |
| Billing / insurance | `ServiceOrder`, `ClinicNphiesClaimService`, `PayerContract`, `RevenueSplitScheme`, Hospital `Preauth` | reusable |
| Inventory | `InventoryLotBalance` (lot/expiry/owner), lot allocations, consignment, `Hospital/SurgeryItem` | gonadotropins + lab consumables OK; **no cryo locations** |
| OR / day-case | `hospital.mode=day_center`, `Theatre`, `TheatreBlock`, `surgeries/day`, `EncounterKind::DayCase` | base for OPU/ET board; OPU/ET/IUI/TESE **missing** from `GynProcedureCatalog` and `hospital_operations` |
| Gyn operations | `Gyn/app/Services/GynOperationService.php` | could hold OPU/ET |
| Documents / print | `ClinicalDocType` (no consent), `ClinicalPdfService` + `ArabicShaper` | consent = new type + template |
| Attachments | `ClinicPatientAttachment::KINDS` has `consent`; `clinical_episode` not attachable | add to allow-list |
| Follow-ups | `FollowUpService::generate`, `dueList` | no cycle triggers |
| Appointments | `Appointment`, `DoctorScheduleSlot`, `ClinicRoom`, `ClinicDevice` | no protocol calendar |
| Portal | `LIS/.../PatientPortalController.php` | lab results + loyalty only |
| Reports | `ClinicReportController`, `ClinicDashboardService`, `ExpectedBirthsReport`, `GynResearchExport` | no ART stats |

## 3. Gaps for a full IVF unit
Embryology lab sheet (per oocyte → per embryo D1–D6, grading Gardner/ASEBIR, fate) · time-lapse/incubator/dish · witnessing (double sign-off + barcode labels) · cryobank (tank→canister→cane→straw, LN2 log, storage contracts + yearly fees + renewal + discard consent) · thaw/FET consuming specific straws · sperm bank (frozen/TESE vials) · donor (likely off for Egypt — owner decision) · couple consents with expiry · OPU/ET/IUI board (trigger→OPU 36 h) · nurse protocol/drug calendar + gonadotropin stock issue · LIS link (order E2/P4/LH/β-hCG from the cycle, pull results, spouse subject, semen sync) · stage-based IVF package · KPIs/registry (fert, cleavage, blast, implantation, CPR, LBR per started cycle/OPU/ET, OHSS, cumulative, by age band/embryologist, ESHRE/ICMART export) · embryologist/andrologist roles · typed trigger datetime, fresh→FET link, write-guard fix.
