Files
cyclone/backend/tests/test_payer_config_loading.py
T
Tyler c62826daea feat(sp9): multi-payer, multi-NPI, SFTP stub for dzinesco/TOC
- providers table seeded with 3 NPIs (Montrose, Delta, Salida)
- payers + payer_configs (per-tx config) join table
- clearhouse singleton (dzinesco identity, SFTP block, filename block)
- config/payers.yaml loader with Pydantic schema validation
- cyclone/edi/filenames.py: HCPF X12 File Naming Standards helpers
- cyclone/clearhouse/sftp.py: stub that copies to ./var/sftp/staging/...
- cyclone/secrets.py: macOS Keychain wrapper via keyring
- 11 new validation rules R200-R210 (CO MAP + HCPF naming)
- 6 new API endpoints (/api/clearhouse/*, /api/config/*, /api/admin/reload-config)
- migration 0007
- 72 new tests (646 total passing, was 574)

See spec: docs/superpowers/specs/2026-06-20-cyclone-multi-payer-npi-sftp-design.md
2026-06-20 23:07:31 -06:00

114 lines
3.7 KiB
Python

"""SP9 — payer config YAML loader tests."""
from __future__ import annotations
from pathlib import Path
import pytest
import yaml
from cyclone import payers
@pytest.fixture(autouse=True)
def _reset_registry():
payers.reset()
yield
payers.reset()
def test_load_default_config_has_co_txix_837p():
configs = payers.load_payer_configs()
assert ("CO_TXIX", "837P") in configs
block = configs[("CO_TXIX", "837P")]
assert block["payer_id"] == "CO_TXIX"
assert "CH" in block["bht06_allowed"]
assert "RP" in block["bht06_allowed"]
assert block["bht06_default"] == "CH"
assert block["sbr09_default"] == "MC"
def test_load_default_config_has_co_txix_835():
configs = payers.load_payer_configs()
assert ("CO_TXIX", "835") in configs
block = configs[("CO_TXIX", "835")]
assert "1811725341" in block["expected_payer_tax_ids"]
assert block["expected_payer_health_plan_id"] == "7912900843"
def test_get_config_returns_block():
payers.load_payer_configs()
block = payers.get_config("CO_TXIX", "837P")
assert block is not None
assert block["submitter_name"] == "Dzinesco"
def test_get_config_returns_none_for_missing():
payers.load_payer_configs()
assert payers.get_config("UNKNOWN_PAYER", "837P") is None
def test_load_invalid_yaml_raises(tmp_path):
bad = tmp_path / "bad.yaml"
bad.write_text(yaml.safe_dump({"payers": [
{"payer_id": "X", "configs": {"837P": {"submitter_name": "ok"}}} # missing required keys
]}))
with pytest.raises(ValueError, match="invalid config"):
payers.load_payer_configs(bad)
def test_load_missing_payers_key_raises(tmp_path):
bad = tmp_path / "bad.yaml"
bad.write_text("not_a_payers_key: 1")
with pytest.raises(ValueError, match="missing top-level 'payers:'"):
payers.load_payer_configs(bad)
def test_load_missing_file_warns_and_clears(tmp_path, caplog):
fake = tmp_path / "does-not-exist.yaml"
with caplog.at_level("WARNING"):
result = payers.load_payer_configs(fake)
assert result == {}
def test_all_configs_returns_snapshot():
payers.load_payer_configs()
snap = payers.all_configs()
assert isinstance(snap, dict)
assert len(snap) >= 2
# Mutating snapshot must not affect registry
snap.clear()
assert len(payers.all_configs()) >= 2
def test_reload_picks_up_changes(tmp_path):
a = tmp_path / "a.yaml"
a.write_text(yaml.safe_dump({"payers": [
{"payer_id": "AAA", "configs": {"837P": {
"submitter_name": "A", "submitter_contact_name": "A",
"submitter_contact_email": "a@a",
"receiver_name": "R", "receiver_id": "R",
"bht06_allowed": ["CH"], "bht06_default": "CH",
"sbr09_default": "MC", "sbr09_allowed": ["MC"],
"payer_id_qualifier": "PI", "payer_id": "AAA",
"pwk_supported": False, "cas_2320_group_allowed": False,
}}}
]}))
b = tmp_path / "b.yaml"
b.write_text(yaml.safe_dump({"payers": [
{"payer_id": "BBB", "configs": {"837P": {
"submitter_name": "B", "submitter_contact_name": "B",
"submitter_contact_email": "b@b",
"receiver_name": "R", "receiver_id": "R",
"bht06_allowed": ["CH"], "bht06_default": "CH",
"sbr09_default": "MC", "sbr09_allowed": ["MC"],
"payer_id_qualifier": "PI", "payer_id": "BBB",
"pwk_supported": False, "cas_2320_group_allowed": False,
}}}
]}))
payers.load_payer_configs(a)
assert payers.get_config("AAA", "837P") is not None
payers.load_payer_configs(b)
assert payers.get_config("BBB", "837P") is not None
assert payers.get_config("AAA", "837P") is None