From f5713640e482c981626ebf9754ebdce61b24230a Mon Sep 17 00:00:00 2001 From: Nora Date: Wed, 8 Jul 2026 22:35:44 -0600 Subject: [PATCH] test(sp24): regression test pinning PATIENT_LOOP_DEFAULT_INCLUDED to False MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds test_serialize_837_patient_loop_default_is_false — the long-term guard against the SP24 bug coming back via a future refactor: 1. Asserts the module-level PATIENT_LOOP_DEFAULT_INCLUDED constant is exactly False (not just falsy). 2. Calls _build_subscriber_block with no kwarg and verifies the output contains no HL*3 segment + HL*2 child_count = 0. 3. The assertion message points at the SP24 spec §2 Decision 2 so a future maintainer sees the regression story immediately. Autoreview: confirmed the test fails when the constant is flipped to True (the broken pattern from 2026-07-08), with the expected 'PATIENT_LOOP_DEFAULT_INCLUDED must be False' assertion message. --- backend/tests/test_serialize_837.py | 66 +++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/backend/tests/test_serialize_837.py b/backend/tests/test_serialize_837.py index 610fa49..37ed100 100644 --- a/backend/tests/test_serialize_837.py +++ b/backend/tests/test_serialize_837.py @@ -738,3 +738,69 @@ def test_sbr_segment_respects_explicit_claim_filing_indicator(): sbr_line = next(s for s in text.split("~") if s.startswith("SBR")) parts = sbr_line.split("*") assert parts[9] == "16", f"SBR-09 should reflect explicit kwarg, got {parts[9]!r}" + + +# --------------------------------------------------------------------------- +# SP24 — IG-correctness regression test +# +# The 2000C Patient Hierarchical Level (HL*3 → PAT → NM1*QC) MUST be +# absent when SBR02 == "18" (Self-pay, the CO-Medicaid IHSS workflow). +# This test pins the PATIENT_LOOP_DEFAULT_INCLUDED constant to False so +# a future refactor cannot silently reintroduce the broken pattern that +# surfaced in the 2026-07-08 Edifabric 999 audit. +# --------------------------------------------------------------------------- + + +def test_serialize_837_patient_loop_default_is_false(): + """SP24 regression: PATIENT_LOOP_DEFAULT_INCLUDED must stay False. + + Per X12 005010X222A1, the 2000C Patient Hierarchical Level + (``HL*3 → PAT → NM1*QC``) is REQUIRED only when Patient != Subscriber + (i.e. ``SBR02 != "18"``). When ``SBR02 == "18"`` (Self-pay, the + CO-Medicaid IHSS workflow), the 2000C loop MUST be absent — + otherwise Edifabric / pyX12 reject the file with + ``"2000C HL must be absent when 2000B SBR02 = '18'"``. + + The serializer encodes this invariant as a module-level constant + ``PATIENT_LOOP_DEFAULT_INCLUDED``. Flipping the default back to + ``True`` would re-introduce the rejection on every self-pay claim + in the dzinesco pipeline. This test pins the constant + verifies + the helper actually honors it on a no-kwarg call. + + Reference: ``docs/superpowers/specs/2026-07-08-cyclone-reissue-claims-design.md`` + """ + from datetime import date as _date + from cyclone.parsers.models import Subscriber + from cyclone.parsers.serialize_837 import ( + PATIENT_LOOP_DEFAULT_INCLUDED, + _build_subscriber_block, + ) + + # 1. The constant itself is False — the IG-correct shape. + assert PATIENT_LOOP_DEFAULT_INCLUDED is False, ( + f"PATIENT_LOOP_DEFAULT_INCLUDED must be False " + f"(got {PATIENT_LOOP_DEFAULT_INCLUDED!r}); the IG-correct " + f"serializer shape for SBR02='18' claims is 2000C-absent. " + f"See the SP24 spec §2 Decision 2 for the regression story." + ) + + # 2. Calling _build_subscriber_block with no kwarg honors the + # constant — no HL*3 segment emitted, HL*2 child count = 0. + sub = Subscriber( + member_id="TEST123", + first_name="Test", + last_name="Patient", + dob=_date(1990, 1, 1), + gender="F", + ) + out = _build_subscriber_block(sub, "MC") + assert not any(seg.startswith("HL*3") for seg in out), ( + f"HL*3 emitted with the IG-correct default; segments={out!r}" + ) + # HL*2 child_count must be 0, not 1. + hl2_line = next(seg for seg in out if seg.startswith("HL*2")) + hl2_parts = hl2_line.rstrip("~").split("*") + assert hl2_parts[4] == "0", ( + f"HL*2 child_count must be 0 (no 2000C children); got {hl2_parts[4]!r}. " + f"Line: {hl2_line!r}" + )