Files
cyclone/backend/tests/test_999_rejected_state.py
T
Tyler f4910fd94d feat(sp6): wire 999 ingest → claim rejected state
T4 — calls apply_999_rejections inside /api/parse-999, then
publishes a claim.rejected event for each transitioned claim so
the Inbox live-tail refetches.
2026-06-20 18:29:28 -06:00

76 lines
2.4 KiB
Python

"""TDD: 999 ingest endpoint moves claims to REJECTED on AK5 R/E.
Plan: docs/superpowers/plans/2026-06-20-cyclone-workflow-automation.md
Task 4 (T4). Wires apply_999_rejections into the /api/parse-999 endpoint.
"""
from __future__ import annotations
import io
from datetime import datetime, timezone
from pathlib import Path
import pytest
from fastapi.testclient import TestClient
from cyclone import db
from cyclone.api import app
from cyclone.db import Batch, Claim, ClaimState
@pytest.fixture(autouse=True)
def _setup(tmp_path, monkeypatch):
monkeypatch.setenv("CYCLONE_DB_URL", f"sqlite:///{tmp_path}/inbox.db")
db._reset_for_tests()
db.init_db()
yield
@pytest.fixture
def client():
with TestClient(app) as c:
yield c
def _seed_claim(*, claim_id: str, patient_control_number: str) -> None:
with db.SessionLocal()() as s:
s.add(Batch(
id="B-1", kind="837p", input_filename="x.txt",
parsed_at=datetime.now(timezone.utc),
totals_json={"total_claims": 1},
validation_json={"passed": True, "warnings": [], "errors": []},
raw_result_json={"_": "stub"},
))
s.add(Claim(
id=claim_id, batch_id="B-1",
patient_control_number=patient_control_number,
state=ClaimState.SUBMITTED,
))
s.commit()
def test_999_set_rejection_moves_claim_to_rejected_state(client: TestClient):
# The seeded claim's patient_control_number is the AK202 (set_control_number)
# of the 999 we post.
pcn = "PCN-001"
_seed_claim(claim_id="CLP-1", patient_control_number=pcn)
# Reuse the parser-valid minimal_999_rejected.txt fixture, then rewrite
# AK202 (the set_control_number) and the SE* count + ST02 control number
# so the parser accepts the modified document and we get an R rejection
# keyed to our seeded PCN.
fixture = (Path(__file__).parent / "fixtures" / "minimal_999_rejected.txt").read_text()
raw = fixture.replace("AK2*837*0001~", f"AK2*837*{pcn}~")
r = client.post(
"/api/parse-999",
files={"file": ("sample.999", io.BytesIO(raw.encode()), "text/plain")},
)
assert r.status_code == 200, r.text
with db.SessionLocal()() as s:
c = s.get(Claim, "CLP-1")
assert c.state == ClaimState.REJECTED
assert c.rejected_at is not None
assert "999" in (c.rejection_reason or "")