fix(sp41): tighten pipeline_a write_files contract + cleanup imports
This commit is contained in:
@@ -19,6 +19,8 @@ from cyclone.rebill.reconcile import ReconcileOutcome, OutcomeCategory
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RebillClaim:
|
||||
"""Pre-emission 837P shape for Pipeline A. The serializer adapter (Task 12) converts this to a ClaimOutput for serialize_837."""
|
||||
|
||||
claim_id: str # reuses original claim_submit_id
|
||||
member_id: str
|
||||
procedure: str
|
||||
@@ -35,9 +37,10 @@ def build_pipeline_a_claims(
|
||||
carc_decisions: list[CarcDecision],
|
||||
cas_reasons_per_visit: list[tuple[str, ...]],
|
||||
) -> list[RebillClaim]:
|
||||
"""One input list per visit; align by index."""
|
||||
"""Zip three parallel per-visit lists by index; drop PAID/NOT_IN_835 outcomes and EXCLUDED CARC decisions; emit one frequency-7 RebillClaim per survivor."""
|
||||
out: list[RebillClaim] = []
|
||||
for vo, carc, reasons in zip(visit_outcomes, carc_decisions, cas_reasons_per_visit):
|
||||
# strict=True: all three lists must be the same length; a mismatch is a contract bug, fail loud.
|
||||
for vo, carc, reasons in zip(visit_outcomes, carc_decisions, cas_reasons_per_visit, strict=True):
|
||||
if vo.category not in (OutcomeCategory.DENIED, OutcomeCategory.PARTIAL):
|
||||
continue
|
||||
if carc == CarcDecision.EXCLUDED:
|
||||
@@ -50,7 +53,7 @@ def build_pipeline_a_claims(
|
||||
charge=vo.visit.billed,
|
||||
frequency_code="7",
|
||||
needs_review=(carc == CarcDecision.REVIEW),
|
||||
original_carc_reasons=tuple(reasons),
|
||||
original_carc_reasons=reasons,
|
||||
))
|
||||
return out
|
||||
|
||||
@@ -58,14 +61,16 @@ def build_pipeline_a_claims(
|
||||
def write_pipeline_a_files(
|
||||
claims: list[RebillClaim],
|
||||
out_dir: Path,
|
||||
serialize_837_fn, # injected: cyclone.parsers.serialize_837.serialize_837
|
||||
serialize_837_fn, # injected: callable[[RebillClaim], str] (orchestrator-supplied adapter)
|
||||
tpid: str,
|
||||
) -> list[Path]:
|
||||
"""Write one 837P per claim, using HCPF-spec filenames via build_outbound_filename.
|
||||
|
||||
`serialize_837_fn(claim)` returns the X12 byte string. The filename is
|
||||
`serialize_837_fn(claim)` returns the X12 string. The 837P envelope is
|
||||
pure ASCII so we write it as text. The filename is
|
||||
`cyclone.edi.filenames.build_outbound_filename(tpid, '837P')`.
|
||||
"""
|
||||
# Lazy: keep cyclone.rebill.pipeline_a importable without zoneinfo from filenames.
|
||||
from cyclone.edi.filenames import build_outbound_filename
|
||||
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
@@ -74,6 +79,6 @@ def write_pipeline_a_files(
|
||||
body = serialize_837_fn(c)
|
||||
fname = build_outbound_filename(tpid, "837P")
|
||||
path = out_dir / fname
|
||||
path.write_bytes(body)
|
||||
path.write_text(body, encoding="ascii")
|
||||
paths.append(path)
|
||||
return paths
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
"""Pipeline A: denied/partial visits become frequency-7 replacement claims."""
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
from pathlib import Path
|
||||
from cyclone.rebill.pipeline_a import (
|
||||
RebillClaim,
|
||||
build_pipeline_a_claims,
|
||||
write_pipeline_a_files,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user