fix(pfs): new_payment never flags a year whose year-1 is outside the supplied window (R84b)
This commit is contained in:
@@ -322,20 +322,37 @@ def new_codes_in(
|
||||
"""The family's new payment events in *year* (R84): a code payable in
|
||||
*year* (status A/R/T) that was not payable, or absent, in year-1 (judged
|
||||
only when year-1 is in *payment*), and every curated link with
|
||||
``since == year``. A link target is never judged by payability (R84a). Pass the full
|
||||
payment history: a truncated window makes a code look absent in year-1."""
|
||||
``since == year``. A link target is never judged by payability (R84a). A year-1 before the
|
||||
first supplied year is unknown, and so is a code whose row count equals the
|
||||
longest history (a ``valuation(years=N)`` window cut) while starting after
|
||||
the family's first year: neither is flagged (R84b)."""
|
||||
payable = {
|
||||
(v.code, v.year)
|
||||
for v in payment
|
||||
if not v.proposed and v.status.strip().upper() in PAID_STATUSES
|
||||
}
|
||||
years = {v.year for v in payment if not v.proposed}
|
||||
by_code: dict[str, set[int]] = {}
|
||||
for v in payment:
|
||||
if not v.proposed:
|
||||
by_code.setdefault(v.code, set()).add(v.year)
|
||||
first = min((min(ys) for ys in by_code.values()), default=year)
|
||||
longest = max((len(ys) for ys in by_code.values()), default=0)
|
||||
|
||||
def truncated(code: str) -> bool:
|
||||
# ``valuation(years=N)`` keeps the last N vintages per code, so a code
|
||||
# with N rows that starts after the family's first year may have lost
|
||||
# its earlier rows: its year-1 is unknown, never "absent" (R84b)
|
||||
ys = by_code.get(code, set())
|
||||
return bool(ys) and min(ys) > first and len(ys) == longest
|
||||
|
||||
targets = {getattr(link, "target", None) or link.code for link in links}
|
||||
# R84a: payability counts only for the family's own member codes; a link
|
||||
# target is new only in its link ``since`` year (G2211 became payable for
|
||||
# office visits in 2024 but joins the home-visit family in 2026)
|
||||
found = {
|
||||
c for c, y in payable if y == year and year - 1 in years and c not in targets
|
||||
c
|
||||
for c, y in payable
|
||||
if y == year and year - 1 >= first and c not in targets and not truncated(c)
|
||||
}
|
||||
found -= {c for c, y in payable if y == year - 1}
|
||||
found |= {
|
||||
|
||||
@@ -477,3 +477,20 @@ def test_link_target_flags_only_in_its_since_year_not_when_first_payable():
|
||||
payment.append(val("G0318", 2024, 1.0))
|
||||
(m,) = money_by_specialty(payment, psps, year=2024, links=links)
|
||||
assert m.new_codes == ("G0318",)
|
||||
|
||||
|
||||
def test_truncated_window_flags_nothing_in_its_first_year():
|
||||
# valuation(years=7) shape: predecessors 2016-2022, current codes cut to
|
||||
# 2021-2027 (their earlier rows fell out of the window), a real new code
|
||||
payment = [val("99324", y, 50.0) for y in range(2016, 2023)]
|
||||
payment += [val("99350", y, 100.0) for y in range(2021, 2028)]
|
||||
payment += [val("G0318", y, 15.0) for y in range(2023, 2028)]
|
||||
psps = [ps(2015, "99350", "Family Practice", 10.0)]
|
||||
new = {
|
||||
y: money_by_specialty(payment, psps, year=y)[0].new_codes
|
||||
for y in range(2016, 2028)
|
||||
}
|
||||
assert new[2021] == () # 99350's year-1 is outside its window
|
||||
assert new[2016] == () # before the first supplied year
|
||||
assert new[2023] == ("G0318",)
|
||||
assert [y for y, c in new.items() if c] == [2023]
|
||||
|
||||
Reference in New Issue
Block a user