fix(pfs): FR citations never read as codes; case-insensitive code matching (refs P48)
A Federal Register page number is five digits, so "91 FR 43842" used to detect 43842 as a CPT code and price it. Strip citations before scanning, and match/normalise codes case-insensitively so "g0556" is found.
This commit is contained in:
@@ -13,12 +13,22 @@ from dataclasses import dataclass
|
|||||||
|
|
||||||
# HCPCS level II (letter + 4 digits) or CPT (5 digits). Validation against
|
# HCPCS level II (letter + 4 digits) or CPT (5 digits). Validation against
|
||||||
# the fee schedule happens at lookup time (pfs.valuation), not here.
|
# the fee schedule happens at lookup time (pfs.valuation), not here.
|
||||||
CODE_RE = re.compile(r"\b(?:[A-Z]\d{4}|\d{5})\b")
|
CODE_RE = re.compile(r"\b(?:[A-Z]\d{4}|\d{5})\b", re.IGNORECASE)
|
||||||
|
|
||||||
|
# "91 FR 43842" — an FR page number is five digits and so reads as a CPT
|
||||||
|
# code; citations are removed before scanning so they never become one.
|
||||||
|
_FR_CITE_RE = re.compile(r"\b\d{1,3}\s+FR\s+\d{3,6}\b", re.IGNORECASE)
|
||||||
|
|
||||||
|
|
||||||
def find_codes(text: str) -> tuple[str, ...]:
|
def find_codes(text: str) -> tuple[str, ...]:
|
||||||
"""Sorted unique codes literally present in *text* (case-normalised)."""
|
"""Sorted unique codes literally present in *text*, upper-cased.
|
||||||
return tuple(sorted({m.group(0) for m in CODE_RE.finditer(text)}))
|
|
||||||
|
Federal Register citations are stripped first: their page numbers are
|
||||||
|
not codes, and a chat answer that priced "43842" out of "91 FR 43842"
|
||||||
|
would be inventing money.
|
||||||
|
"""
|
||||||
|
text = _FR_CITE_RE.sub(" ", text)
|
||||||
|
return tuple(sorted({m.group(0).upper() for m in CODE_RE.finditer(text)}))
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
|
|||||||
@@ -10,12 +10,19 @@ class TestFindCodes:
|
|||||||
assert find_codes("Codes G0556 and 99490 apply; see g0557.") == (
|
assert find_codes("Codes G0556 and 99490 apply; see g0557.") == (
|
||||||
"99490",
|
"99490",
|
||||||
"G0556",
|
"G0556",
|
||||||
|
"G0557",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_lower_case_codes_are_normalised(self):
|
||||||
|
assert find_codes("what is g0556?") == ("G0556",)
|
||||||
|
|
||||||
def test_no_false_hits_on_years_and_fr_pages(self):
|
def test_no_false_hits_on_years_and_fr_pages(self):
|
||||||
# 2026 (4 digits) and 43842 (5 digits) — the CPT regex will match 43842;
|
# A Federal Register citation is stripped before scanning, so its page
|
||||||
# validation against the fee schedule happens at lookup, not here.
|
# number (43842 — a well-formed CPT code) never reads as a code.
|
||||||
assert find_codes("91 FR 43842, CY2026") == ("43842",)
|
assert find_codes("91 FR 43842, CY2026") == ()
|
||||||
|
|
||||||
|
def test_fr_citation_alone_yields_nothing(self):
|
||||||
|
assert find_codes("What does 91 FR 43842 say?") == ()
|
||||||
|
|
||||||
def test_dedupes_and_sorts(self):
|
def test_dedupes_and_sorts(self):
|
||||||
assert find_codes("G0558 G0556 G0558") == ("G0556", "G0558")
|
assert find_codes("G0558 G0556 G0558") == ("G0556", "G0558")
|
||||||
|
|||||||
Reference in New Issue
Block a user