feat(sp25): read-side defensive stub for synthetic-batch rows

This commit is contained in:
Nora
2026-07-07 14:29:56 -06:00
parent c8f5af3ba5
commit 0ccc396e5e
3 changed files with 266 additions and 18 deletions
@@ -24,12 +24,9 @@ backend/src/cyclone/
submission/
recover.py # B: shared parse-then-store logic (new, small)
backend/tests/
test_store_batches_synthetic.py # A: unit
test_store_batches_synthetic.py # A: unit (the defensive stub needs synthetic rows with NULL raw_result_json — these are ORM-level test fixtures for the read path, not EDI samples)
test_api_batches_synthetic.py # A: integration
test_cli_recover_ingest.py # B: cli + integration
fixtures/
recover_837p_minimal.txt # B: 2-claim 837P fixture (synthetic)
recover_835_minimal.x12 # B: 2-payment 835 fixture (synthetic)
test_cli_recover_ingest.py # B: cli + integration (uses existing co_medicaid_* fixtures; no new minimal_* EDI mirrors)
backend/scripts/
verify_dashboard_recovery.py # post-recovery sanity check (operator-only)
docs/superpowers/specs/
@@ -61,15 +58,12 @@ docs/superpowers/specs/
- [ ] Restart-free smoke: `curl -sS 'http://127.0.0.1:8000/api/batches?limit=5' | python -m json.tool` — expect 200, `items[].claimCount==0` for the 4 synthetic rows, `inputFilename=="<synthetic:orphan-reconcile>"`.
## Task 4: B — copy prodfiles to fixtures + failing test for `recover-ingest`
## Task 4: B — failing test for `recover-ingest` against real co_medicaid fixtures
- [ ] Copy the source 835 into fixtures (operator-only, but commit it as a fixture for hermetic recovery verification):
- `cp ingest/tp11525703-835_M019771179-20260706005516577-1of1.x12 backend/tests/fixtures/recover_835_real.x12`.
- `cp ingest/tp11525703-837P-20260701162932052-1of1.txt backend/tests/fixtures/recover_837p_real_145claims.txt`.
- [ ] Add `backend/tests/test_cli_recover_ingest.py` with three cases:
1. `test_ingest_835_persists_remittance` — invoke the `recover-ingest` CLI via Click's `CliRunner` with the real 835 fixture; assert `len(store.list_remittances())==1+1`, the row's `total_paid > 0`, and a `processed_inbound_files` row with `sftp_block_name='manual-recover'` was created.
2. `test_ingest_837p_persists_claims` — invoke with the 145-claim 837P fixture; assert `claims_total_count >= 145` via `SessionLocal().query(Claim).count()` and the corresponding `Batch` row's `claim_count` matches.
3. `test_ingest_idempotent` — invoke twice with the same file; second run is a no-op (skip messages logged, no extra rows).
- [ ] Add `backend/tests/test_cli_recover_ingest.py` with three cases. Test inputs come from existing `backend/tests/fixtures/co_medicaid_837p.txt` + `co_medicaid_835.txt` — real production EDI already in the repo. **No synthetic EDI fixtures are introduced.** The ingest/ files are reserved for the operator-only recovery run (Task 6), not unit-tested.
1. `test_ingest_835_persists_remittance` — invoke `recover-ingest` via Click's `CliRunner` with `co_medicaid_835.txt`; assert a Remittance row was created with `total_paid > 0`, plus a `processed_inbound_files` row with `sftp_block_name='manual-recover'`.
2. `test_ingest_837p_persists_claims` — invoke with `co_medicaid_837p.txt`; assert ≥1 Claim row + a Batch row that references it.
3. `test_ingest_idempotent` — invoke twice with the same file; second run is a no-op (skip messages, no extra rows).
- [ ] Run the test file: must fail (no `recover-ingest` command yet).
## Task 5: B — implement `cyclone recover-ingest`