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:
@@ -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
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user