feat(parsers): R034 REF*G1 enforcement + R035 BHT06 transaction type code (SP3 P1)

- R034 _r034_ref_g1_required: when payer opts in (require_ref_g1_for_adjustments),
  emit error if frequency_code is 7/8 and no REF*G1 segment appears in raw_segments.
  CO Medicaid stays lenient in v1 (gate is False by default).
- R035 _r035_bht06_allowed: BHT06 transaction type code must be in cfg.allowed_bht06.
  Skipped silently when transaction_type_code is None.
- Add transaction_type_code (str|None) to Envelope and ClaimOutput.
- parse_837: read BHT06 (seg[6]) in _build_envelope; mirror onto each ClaimOutput
  via the existing model_copy(update={...}) call site.
- 9 new tests in test_validator.py: 5 R034 (incl. lenient no-op) + 4 R035.
  213 passed, 1 skipped (prodfile corpus present-conditional).
This commit is contained in:
Tyler
2026-06-20 07:25:29 -06:00
parent 763ca3d758
commit 716bfb0a26
4 changed files with 182 additions and 0 deletions
+120
View File
@@ -193,3 +193,123 @@ def test_r033_errors_with_invalid_pos_code():
report = validate(claim, cfg)
assert any(i.rule == "R033_clm05_1_place_of_service_code" and i.severity == "error" for i in report.errors)
assert report.passed is False
# --------------------------------------------------------------------------- #
# R034 — REF*G1 enforcement (SP3 Phase 1)
# --------------------------------------------------------------------------- #
def _strict_cfg() -> PayerConfig:
"""Strict cfg that mirrors the CO Medicaid defaults but turns on R034 enforcement.
We don't modify :meth:`PayerConfig.co_medicaid` — the lenient default stays
in v1. This local fixture lets us exercise the strict path without leaking
config changes across the suite.
"""
return PayerConfig(
name="StrictTest",
require_ref_g1_for_adjustments=True,
allowed_bht06={"CH"},
payer_id="X",
)
def test_r034_ref_g1_required_freq_7_no_ref_g1_errors():
cfg = _strict_cfg()
claim = _build_claim()
claim.claim.frequency_code = "7"
claim.raw_segments = []
report = validate(claim, cfg)
assert any(
i.rule == "R034_ref_g1_required" and i.severity == "error" for i in report.errors
)
assert report.passed is False
def test_r034_ref_g1_required_freq_8_no_ref_g1_errors():
cfg = _strict_cfg()
claim = _build_claim()
claim.claim.frequency_code = "8"
claim.raw_segments = []
report = validate(claim, cfg)
assert any(
i.rule == "R034_ref_g1_required" and i.severity == "error" for i in report.errors
)
assert report.passed is False
def test_r034_ref_g1_required_freq_7_with_ref_g1_passes():
cfg = _strict_cfg()
claim = _build_claim()
claim.claim.frequency_code = "7"
claim.raw_segments = [["REF", "G1", "12345"]]
report = validate(claim, cfg)
assert not any(
i.rule == "R034_ref_g1_required" for i in report.errors + report.warnings
)
def test_r034_ref_g1_required_freq_1_no_ref_g1_passes():
cfg = _strict_cfg()
claim = _build_claim()
claim.claim.frequency_code = "1"
claim.raw_segments = []
report = validate(claim, cfg)
assert not any(
i.rule == "R034_ref_g1_required" for i in report.errors + report.warnings
)
def test_r034_ref_g1_lenient_cfg_never_errors():
cfg = PayerConfig.co_medicaid() # require_ref_g1_for_adjustments=False (lenient v1)
claim = _build_claim()
claim.claim.frequency_code = "7"
claim.raw_segments = []
report = validate(claim, cfg)
assert not any(
i.rule == "R034_ref_g1_required" for i in report.errors + report.warnings
)
# --------------------------------------------------------------------------- #
# R035 — BHT06 transaction type code (SP3 Phase 1)
# --------------------------------------------------------------------------- #
def test_r035_bht06_allowed_ch_passes():
cfg = PayerConfig.co_medicaid()
claim = _build_claim(transaction_type_code="CH")
report = validate(claim, cfg)
assert not any(
i.rule == "R035_bht06_allowed" for i in report.errors + report.warnings
)
def test_r035_bht06_allowed_rp_errors_for_co_medicaid():
cfg = PayerConfig.co_medicaid()
claim = _build_claim(transaction_type_code="RP")
report = validate(claim, cfg)
assert any(
i.rule == "R035_bht06_allowed" and i.severity == "error" for i in report.errors
)
assert report.passed is False
def test_r035_bht06_missing_skips():
cfg = PayerConfig.co_medicaid()
claim = _build_claim(transaction_type_code=None)
assert claim.transaction_type_code is None
report = validate(claim, cfg)
assert not any(
i.rule == "R035_bht06_allowed" for i in report.errors + report.warnings
)
def test_r035_bht06_rp_allowed_for_generic_837p():
cfg = PayerConfig.generic_837p() # allows {"CH", "RP"}
claim = _build_claim(transaction_type_code="RP")
report = validate(claim, cfg)
assert not any(
i.rule == "R035_bht06_allowed" for i in report.errors + report.warnings
)