""" doc_state_machine.py Signal — STTIL Solutions Computes per-patient documentation status across 5 items. Requirements are payer-dependent. Produces cascade consequence chain. PHI Contract: no patient names, DOBs, or contact info in any parameter. """ from dataclasses import dataclass, field from datetime import date from typing import Optional # Payer types that require PECOS enrollment _PECOS_REQUIRED = {"medicare", "medicare_advantage"} # Payer types that require Prior Authorization for CGM _PA_REQUIRED = {"medicare_advantage", "medicaid", "commercial"} # Medicare FFS: PA not required (CGM coverage expansion 2023 + CMS-1828-F exemption path) _PA_NOT_REQUIRED = {"medicare"} @dataclass class DocState: swo: str = "Pending" # "On File" | "Pending" | "Expired" visit: str = "Not Confirmed" # "Confirmed YYYY-MM-DD" | "Estimated YYYY-MM-DD" | "Not Confirmed" pecos: str = "Not Verified" # "Verified" | "Not Verified" | "N/A" | "Pending — Verify" pa: str = "Required — Not Started" # "Not Required" | "Approved" | "Pending" | "Denied" | "Required — Not Started" | "Pending — Verify" diagnosis: str = "Missing" # "On File" | "Missing" | "Pending — Verify" cascade: list = field(default_factory=list) def _resolve_visit_display( csv_visit_date: Optional[date], confirmed_visit_date: Optional[date], is_transfer: bool, ) -> tuple[str, bool]: """ Returns (display_string, is_confirmed). is_confirmed=True means the date is reliable (from CSV or staff-confirmed). """ if is_transfer: return "Pending — Verify", False if csv_visit_date: return f"Confirmed {csv_visit_date.isoformat()}", True if confirmed_visit_date: return f"Confirmed {confirmed_visit_date.isoformat()}", True return "Not Confirmed — Estimated Only", False def _build_cascade( swo: str, visit_confirmed: bool, pecos: str, pa: str, diagnosis: str, payer_type: str, swo_supplied: bool = True, visit_supplied: bool = True, diagnosis_supplied: bool = True, pecos_supplied: bool = True, pa_supplied: bool = True, ) -> list: """ Build the full consequence chain for all documentation gaps. Only flags gaps for columns that were actually present in the CSV. An absent column is "not evaluated", not a gap — green means no known blocker. Type A = doc gaps Signal can help close. Type B = route-to-action alerts for denials. """ cascade = [] # Type A: Documentation gaps — only fire when the column was supplied if visit_supplied and not visit_confirmed: cascade.append( "Qualifying visit not on file — confirm with prescriber before scheduling shipment" ) if swo_supplied and swo in ("Pending", "Expired"): label = "not on file" if swo == "Pending" else "expired" cascade.append( f"Written order {label} — obtain from prescriber before claim submission" ) if diagnosis_supplied and diagnosis == "Missing": cascade.append( "Diagnosis code not on file — obtain from prescriber records before billing" ) if pecos_supplied and payer_type in _PECOS_REQUIRED and pecos == "Not Verified": cascade.append( "Ordering provider PECOS enrollment not verified — confirm NPI is active before claim submission" ) if pa_supplied and payer_type not in _PA_NOT_REQUIRED and pa == "Required — Not Started": cascade.append( "Prior authorization not started — obtain before scheduling shipment" ) # Type B: Route-to-action alert — PA denied is always surfaced (supplied-and-bad) if pa == "Denied": cascade.append( "Prior authorization denied — file Level 1 appeal within 65 days. " "Approximately 80% of first-level Medicare Advantage appeals succeed." ) return cascade def compute_doc_state( payer_type: str, csv_swo_status: Optional[str], csv_visit_date: Optional[date], confirmed_visit_date: Optional[date], csv_pecos_verified: Optional[str], csv_pa_status: Optional[str], csv_diagnosis_on_file: Optional[str], is_transfer: bool = False, ) -> DocState: """ Compute the full documentation state for one patient. payer_type: "medicare" | "medicare_advantage" | "medicaid" | "commercial" All csv_* fields are Optional — None means not present in the CSV. """ # Transfer patients: everything is pending verification if is_transfer: return DocState( swo="Pending — Verify", visit="Pending — Verify", pecos="Pending — Verify", pa="Pending — Verify", diagnosis="Pending — Verify", cascade=[ "Patient transferred from prior supplier", "Verify: SWO from current prescriber, qualifying visit within 6 months, PA status with current payer", ], ) # SWO swo_map = {"on file": "On File", "pending": "Pending", "expired": "Expired"} swo = swo_map.get((csv_swo_status or "").strip().lower(), "Pending") # Visit visit_display, visit_confirmed = _resolve_visit_display( csv_visit_date, confirmed_visit_date, is_transfer ) # PECOS — only required for Medicare if payer_type in _PECOS_REQUIRED: pecos_val = (csv_pecos_verified or "").strip().lower() pecos = "Verified" if pecos_val in ("yes", "verified", "true", "1") else "Not Verified" else: pecos = "N/A" # PA — not required for Medicare FFS; required for MA, Medicaid, Commercial if payer_type in _PA_NOT_REQUIRED: pa = "Not Required" elif csv_pa_status: pa_map = { "approved": "Approved", "pending": "Pending", "denied": "Denied", "not required": "Not Required", "not started": "Required — Not Started", } pa_key = csv_pa_status.strip().lower() pa = pa_map.get(pa_key, "Required — Not Started") else: pa = "Required — Not Started" # Diagnosis dx_val = (csv_diagnosis_on_file or "").strip().lower() diagnosis = "On File" if dx_val in ("yes", "true", "on file", "1") else "Missing" swo_supplied = csv_swo_status is not None visit_supplied = (csv_visit_date is not None) or (confirmed_visit_date is not None) diagnosis_supplied = csv_diagnosis_on_file is not None pecos_supplied = csv_pecos_verified is not None pa_supplied = csv_pa_status is not None cascade = _build_cascade( swo, visit_confirmed, pecos, pa, diagnosis, payer_type, swo_supplied=swo_supplied, visit_supplied=visit_supplied, diagnosis_supplied=diagnosis_supplied, pecos_supplied=pecos_supplied, pa_supplied=pa_supplied, ) return DocState( swo=swo, visit=visit_display, pecos=pecos, pa=pa, diagnosis=diagnosis, cascade=cascade, )