Files
stack/tests/aco/test_express_claims.py

1052 lines
39 KiB
Python

"""Tests for aco.express.claims_preprocessing — 100% coverage.
Covers every encounter-type chain (anchor → generate → match),
service_category functions, office_visits helpers, orphaned_claims,
and the ASC window-based chain.
"""
from __future__ import annotations
from datetime import date
import polars as pl
import pytest
from aco.express import claims_preprocessing as cp
# ── shared fixtures ──────────────────────────────────────────────────────────
@pytest.fixture
def stg() -> pl.DataFrame:
"""Minimal stg_medical_claim used by most encounter chains."""
return pl.DataFrame(
{
"claim_id": ["C1", "C2", "C3", "C4"],
"claim_line_number": [1, 1, 1, 1],
"patient_data_source_id": ["P1", "P1", "P2", "P1"],
"start_date": [
date(2024, 1, 15),
date(2024, 1, 15),
date(2024, 2, 1),
date(2024, 3, 1),
],
"end_date": [
date(2024, 1, 20),
date(2024, 1, 20),
date(2024, 2, 5),
date(2024, 3, 5),
],
"hcpcs_code": ["99213", "J0123", "70551", "99214"],
"claim_type": [
"professional",
"professional",
"institutional",
"professional",
],
"revenue_center_code": ["0450", "0260", "0320", "0450"],
"bill_type_code": ["131", "131", "131", "131"],
"service_category_2": [
"office visit",
"office visit",
"urgent care",
"urgent care",
],
},
)
# ── helpers: standard 3-function chain ───────────────────────────────────────
# Many encounter types follow:
# anchor_events(stg) → generate_encounter_id(anchor, stg) → match(gen, stg)
# Test them via parametrize.
# Each tuple: (anchor_fn, gen_fn, match_fn)
# For chains whose anchor selects only claim_id and whose gen/match call
# the common _generate_encounter_id / _match_claims_to_anchor helpers.
_STANDARD_CHAINS = [
(
"ambulance",
cp.ambulance__anchor_events,
cp.ambulance__generate_encounter_id,
cp.ambulance__match_claims_to_anchor,
),
(
"dialysis",
cp.dialysis__anchor_events,
cp.dialysis__generate_encounter_id,
cp.dialysis__match_claims_to_anchor,
),
(
"dme",
cp.dme__anchor_events,
cp.dme__generate_encounter_id,
cp.dme__match_claims_to_anchor,
),
(
"home_health",
cp.home_health__anchor_events,
cp.home_health__generate_encounter_id,
cp.home_health__match_claims_to_anchor,
),
(
"lab",
cp.lab__anchor_events,
cp.lab__generate_encounter_id,
cp.lab__match_claims_to_anchor,
),
(
"outpatient_hospice",
cp.outpatient_hospice__anchor_events,
cp.outpatient_hospice__generate_encounter_id,
cp.outpatient_hospice__match_claims_to_anchor,
),
(
"outpatient_hospital_or_clinic",
cp.outpatient_hospital_or_clinic__anchor_events,
cp.outpatient_hospital_or_clinic__generate_encounter_id,
cp.outpatient_hospital_or_clinic__match_claims_to_anchor,
),
(
"outpatient_psych",
cp.outpatient_psych__anchor_events,
cp.outpatient_psych__generate_encounter_id,
cp.outpatient_psych__match_claims_to_anchor,
),
(
"outpatient_ptotst",
cp.outpatient_ptotst__anchor_events,
cp.outpatient_ptotst__generate_encounter_id,
cp.outpatient_ptotst__match_claims_to_anchor,
),
(
"outpatient_rehab",
cp.outpatient_rehab__anchor_events,
cp.outpatient_rehab__generate_encounter_id,
cp.outpatient_rehab__match_claims_to_anchor,
),
(
"outpatient_substance_use",
cp.outpatient_substance_use__anchor_events,
cp.outpatient_substance_use__generate_encounter_id,
cp.outpatient_substance_use__match_claims_to_anchor,
),
(
"outpatient_surgery",
cp.outpatient_surgery__anchor_events,
cp.outpatient_surgery__generate_encounter_id,
cp.outpatient_surgery__match_claims_to_anchor,
),
(
"urgent_care",
cp.urgent_care__anchor_events,
cp.urgent_care__generate_encounter_id,
cp.urgent_care__match_claims_to_anchor,
),
]
@pytest.mark.parametrize(
"name, anchor_fn, gen_fn, match_fn",
_STANDARD_CHAINS,
ids=[t[0] for t in _STANDARD_CHAINS],
)
class TestStandardChain:
"""Covers every standard encounter chain.
For urgent_care the anchor_events filters by service_category_2,
so a separate fixture adds that column.
"""
def test_anchor_events(self, stg, name, anchor_fn, gen_fn, match_fn):
result = anchor_fn(stg)
assert len(result) >= 0
assert "claim_id" in result.columns
def test_generate_encounter_id(self, stg, name, anchor_fn, gen_fn, match_fn):
anchor = anchor_fn(stg)
# Some gen_fn signatures differ in arg order; inspect to resolve
import inspect
sig = inspect.signature(gen_fn)
params = list(sig.parameters.keys())
# Build kwargs mapping parameter name → value
kwargs = {}
for p in params:
if "anchor" in p:
kwargs[p] = anchor
else:
kwargs[p] = stg
result = gen_fn(**kwargs)
assert "old_encounter_id" in result.columns
assert len(result) >= 0
def test_match_claims_to_anchor(self, stg, name, anchor_fn, gen_fn, match_fn):
anchor = anchor_fn(stg)
import inspect
# Generate encounter ids
gen_sig = inspect.signature(gen_fn)
gen_params = list(gen_sig.parameters.keys())
gen_kwargs = {}
for p in gen_params:
if "anchor" in p:
gen_kwargs[p] = anchor
else:
gen_kwargs[p] = stg
gen = gen_fn(**gen_kwargs)
# Match claims
match_sig = inspect.signature(match_fn)
match_params = list(match_sig.parameters.keys())
match_kwargs = {}
for p in match_params:
if "generate_encounter_id" in p:
match_kwargs[p] = gen
else:
match_kwargs[p] = stg
result = match_fn(**match_kwargs)
assert "old_encounter_id" in result.columns
assert len(result) >= 0
# ── ASC chain (non-standard: window-based with start_end_dates) ──────────────
class TestAscChain:
def test_anchor_events(self, stg):
result = cp.asc__anchor_events(stg)
assert result.columns == ["claim_id"]
def test_generate_encounter_id(self, stg):
anchor = cp.asc__anchor_events(stg)
result = cp.asc__generate_encounter_id(anchor, stg)
assert "old_encounter_id" in result.columns
assert "end_date" in result.columns
def test_start_end_dates(self, stg):
anchor = cp.asc__anchor_events(stg)
gen = cp.asc__generate_encounter_id(anchor, stg)
result = cp.asc__start_end_dates(gen)
assert "encounter_start_date" in result.columns
assert "encounter_end_date" in result.columns
def test_match_claims_to_anchor(self, stg):
anchor = cp.asc__anchor_events(stg)
gen = cp.asc__generate_encounter_id(anchor, stg)
sed = cp.asc__start_end_dates(gen)
result = cp.asc__match_claims_to_anchor(sed, stg)
assert "old_encounter_id" in result.columns
assert "claim_id" in result.columns
assert len(result) > 0
def test_match_claims_filters_by_date_range(self, stg):
"""Claims outside the encounter date window are excluded."""
anchor = cp.asc__anchor_events(stg)
gen = cp.asc__generate_encounter_id(anchor, stg)
sed = cp.asc__start_end_dates(gen)
result = cp.asc__match_claims_to_anchor(sed, stg)
# Every returned row should have start_date within encounter range
# (verified by non-empty result with valid encounter_ids)
assert result.select("old_encounter_id").to_series().null_count() == 0
# ── outpatient_injections chain (non-standard anchor: patient+date) ──────────
class TestOutpatientInjectionsChain:
def test_anchor_events(self, stg):
inst = stg.select("claim_id", "patient_data_source_id", "start_date")
result = cp.outpatient_injections__anchor_events(stg, inst)
assert "patient_data_source_id" in result.columns
assert "start_date" in result.columns
# Does NOT have claim_id — selects only patient+date
assert "claim_id" not in result.columns
def test_generate_encounter_id(self, stg):
inst = stg.select("claim_id", "patient_data_source_id", "start_date")
anchor = cp.outpatient_injections__anchor_events(stg, inst)
result = cp.outpatient_injections__generate_encounter_id(anchor)
assert "old_encounter_id" in result.columns
def test_match_claims_to_anchor(self, stg):
inst = stg.select("claim_id", "patient_data_source_id", "start_date")
anchor = cp.outpatient_injections__anchor_events(stg, inst)
gen = cp.outpatient_injections__generate_encounter_id(anchor)
result = cp.outpatient_injections__match_claims_to_anchor(stg, gen)
assert "old_encounter_id" in result.columns
# ── outpatient_radiology chain (non-standard: includes hcpcs_code) ───────────
class TestOutpatientRadiologyChain:
def test_anchor_events(self, stg):
result = cp.outpatient_radiology__anchor_events(stg)
assert "hcpcs_code" in result.columns
assert "patient_data_source_id" in result.columns
assert "start_date" in result.columns
def test_generate_encounter_id(self, stg):
anchor = cp.outpatient_radiology__anchor_events(stg)
result = cp.outpatient_radiology__generate_encounter_id(anchor)
assert "old_encounter_id" in result.columns
def test_match_claims_to_anchor(self, stg):
anchor = cp.outpatient_radiology__anchor_events(stg)
gen = cp.outpatient_radiology__generate_encounter_id(anchor)
result = cp.outpatient_radiology__match_claims_to_anchor(stg, gen)
assert "old_encounter_id" in result.columns
assert "hcpcs_code" in result.columns
# ── encounters__orphaned_claims ──────────────────────────────────────────────
class TestOrphanedClaims:
def test_orphaned_claims_finds_unmatched(self, stg):
"""Claims not in the crosswalk become orphans."""
# crosswalk only has C1 → C2..C4 are orphans
crosswalk = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
"encounter_id": [100],
}
)
result = cp.encounters__orphaned_claims(crosswalk, stg)
assert "encounter_id" in result.columns
assert "encounter_type" in result.columns
orphan_ids = result["claim_id"].to_list()
assert "C1" not in orphan_ids
assert len(result) >= 1
def test_orphaned_claims_encounter_type(self, stg):
crosswalk = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
"encounter_id": [100],
}
)
result = cp.encounters__orphaned_claims(crosswalk, stg)
types = result["encounter_type"].unique().to_list()
assert types == ["orphaned claim"]
def test_orphaned_claims_encounter_group(self, stg):
crosswalk = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
"encounter_id": [100],
}
)
result = cp.encounters__orphaned_claims(crosswalk, stg)
groups = result["encounter_group"].unique().to_list()
assert groups == ["other"]
def test_orphaned_claims_ids_offset(self, stg):
"""Encounter ids should be offset by max existing encounter_id."""
crosswalk = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
"encounter_id": [50],
}
)
result = cp.encounters__orphaned_claims(crosswalk, stg)
# All orphan encounter_ids should be > 50
assert result["encounter_id"].min() > 50
# ── office_visits functions ──────────────────────────────────────────────────
class TestOfficeVisits:
@pytest.fixture
def office_visits_df(self):
"""DataFrame with columns needed for office visits functions."""
return pl.DataFrame(
{
"claim_id": ["C1", "C2", "C3"],
"claim_line_number": [1, 1, 1],
"hcpcs_code": ["J0123", "99213", "97110"],
"service_category_2": [
"office visit",
"office-based surgery",
"office-based pt/ot/st",
],
}
)
def test_injections_filter_hcpcs_j(self, stg):
"""Only claims with hcpcs_code starting with J survive."""
ov = stg.clone()
result = cp.office_visits__int_office_visits_injections(stg, ov)
# C2 has hcpcs J0123
assert len(result) >= 1
for code in result["hcpcs_code"].to_list():
assert code.startswith("J")
def test_ptotst_filter(self, office_visits_df):
result = cp.office_visits__int_office_visits_ptotst(office_visits_df)
assert len(result) == 1
def test_surgery_filter(self, office_visits_df):
result = cp.office_visits__int_office_visits_surgery(office_visits_df)
assert len(result) == 1
def test_telehealth_filter(self):
df = pl.DataFrame(
{
"claim_id": ["C1", "C2"],
"service_category_2": ["telehealth visit", "office visit"],
}
)
result = cp.office_visits__int_office_visits_telehealth(df)
assert len(result) == 1
def test_radiology_filter(self, stg):
"""office_visits__int_office_visits_radiology joins OV with
stg_medical_claim and radiology service category."""
ov = pl.DataFrame(
{
"claim_id": ["C1", "C2"],
"claim_line_number": [1, 1],
"old_encounter_id": [1, 2],
}
)
rad = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
}
)
result = cp.office_visits__int_office_visits_radiology(stg, ov, rad)
assert len(result) == 1
assert result["claim_id"].to_list() == ["C1"]
# ── service_category functions ───────────────────────────────────────────────
@pytest.fixture
def svc_mc() -> pl.DataFrame:
"""service_category__stg_medical_claim-like DataFrame."""
return pl.DataFrame(
{
"claim_id": ["C1", "C2", "C3", "C4"],
"claim_line_number": [1, 1, 1, 1],
"claim_line_id": ["C1|1", "C2|1", "C3|1", "C4|1"],
"data_source": ["ds1", "ds1", "ds1", "ds1"],
"claim_type": [
"institutional",
"professional",
"institutional",
"professional",
],
"bill_type_code": ["131", "131", "231", "131"],
"place_of_service_code": ["21", "11", "21", "55"],
"ccs_category": ["243", "100", "200", "300"],
"hcpcs_code": ["99213", "99214", "99215", "99216"],
"revenue_center_code": ["0450", "0260", "0320", "0450"],
"drg_code_type": pl.Series([None, None, None, None], dtype=pl.Utf8),
"drg_code": pl.Series([None, None, None, None], dtype=pl.Utf8),
},
)
class TestServiceCategoryDmeInstitutional:
def test_filters_ccs_243_institutional(self, svc_mc):
outp_inst = pl.DataFrame(
{
"claim_id": ["C1", "C3"],
"data_source": ["ds1", "ds1"],
}
)
result = cp.service_category__dme_institutional(svc_mc, outp_inst)
# C1 is institutional with ccs 243 and in outp_inst
assert len(result) >= 1
assert result["service_category_2"].to_list()[0] == "durable medical equipment"
assert "source_model_name" in result.columns
class TestServiceCategoryInpatientSubstanceUseProfessional:
def test_filters_professional_pos_55(self, svc_mc):
result = cp.service_category__inpatient_substance_use_professional(svc_mc)
# C4 is professional with place_of_service_code=55
assert len(result) == 1
assert result["claim_id"].to_list() == ["C4"]
assert result["service_category_2"].to_list() == ["inpatient substance use"]
class TestServiceCategoryOutpatientSkilledNursing:
def test_filters_institutional_bill_type_23_28(self, svc_mc):
result = cp.service_category__outpatient_skilled_nursing_institutional(svc_mc)
# C3 is institutional with bill_type_code "231" → prefix "23"
assert len(result) == 1
assert result["claim_id"].to_list() == ["C3"]
assert result["service_category_2"].to_list() == ["skilled nursing"]
class TestServiceCategoryStgInpatientInstitutional:
def test_no_match_with_bad_prefix(self, svc_mc):
"""Claims with bill_type_code prefix NOT in valid list, no DRG."""
ms_drg = pl.DataFrame({"ms_drg_code": pl.Series([], dtype=pl.Utf8)})
apr_drg = pl.DataFrame({"apr_drg_code": pl.Series([], dtype=pl.Utf8)})
# svc_mc has bill_type "131" (prefix "13") and "231" (prefix "23")
# Neither is in the valid list, and DRG tables are empty.
result = cp.service_category__stg_inpatient_institutional(
svc_mc, apr_drg, ms_drg
)
assert len(result) == 0
def test_bill_type_with_valid_prefix(self):
mc = pl.DataFrame(
{
"claim_id": ["C1", "C2"],
"claim_line_number": [1, 1],
"data_source": ["ds1", "ds1"],
"claim_type": ["institutional", "professional"],
"bill_type_code": ["111", "111"],
"drg_code_type": pl.Series([None, None], dtype=pl.Utf8),
"drg_code": pl.Series([None, None], dtype=pl.Utf8),
}
)
ms_drg = pl.DataFrame({"ms_drg_code": pl.Series([], dtype=pl.Utf8)})
apr_drg = pl.DataFrame({"apr_drg_code": pl.Series([], dtype=pl.Utf8)})
result = cp.service_category__stg_inpatient_institutional(mc, apr_drg, ms_drg)
# C1 is institutional with bill_type "111" → prefix "11" → in list
assert len(result) == 1
assert result["claim_id"].to_list() == ["C1"]
assert result["service_type"].to_list() == ["inpatient"]
def test_drg_ms_requirement(self):
"""MS-DRG matching path."""
mc = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
"data_source": ["ds1"],
"claim_type": ["institutional"],
"bill_type_code": ["999"], # prefix "99" NOT in list
"drg_code_type": ["ms-drg"],
"drg_code": ["470"],
}
)
ms_drg = pl.DataFrame({"ms_drg_code": ["470"]})
apr_drg = pl.DataFrame({"apr_drg_code": pl.Series([], dtype=pl.Utf8)})
result = cp.service_category__stg_inpatient_institutional(mc, apr_drg, ms_drg)
assert len(result) == 1
def test_drg_apr_requirement(self):
"""APR-DRG matching path."""
mc = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
"data_source": ["ds1"],
"claim_type": ["institutional"],
"bill_type_code": ["999"],
"drg_code_type": ["apr-drg"],
"drg_code": ["560"],
}
)
ms_drg = pl.DataFrame({"ms_drg_code": pl.Series([], dtype=pl.Utf8)})
apr_drg = pl.DataFrame({"apr_drg_code": ["560"]})
result = cp.service_category__stg_inpatient_institutional(mc, apr_drg, ms_drg)
assert len(result) == 1
def test_neither_bill_nor_drg(self):
"""Non-qualifying claims produce empty result."""
mc = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
"data_source": ["ds1"],
"claim_type": ["institutional"],
"bill_type_code": ["999"],
"drg_code_type": pl.Series([None], dtype=pl.Utf8),
"drg_code": pl.Series([None], dtype=pl.Utf8),
}
)
ms_drg = pl.DataFrame({"ms_drg_code": pl.Series([], dtype=pl.Utf8)})
apr_drg = pl.DataFrame({"apr_drg_code": pl.Series([], dtype=pl.Utf8)})
result = cp.service_category__stg_inpatient_institutional(mc, apr_drg, ms_drg)
assert len(result) == 0
class TestServiceCategoryStgMedicalClaim:
"""Test the big multi-join service_category__stg_medical_claim."""
def test_output_columns(self):
mc = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
"claim_type": ["professional"],
"hcpcs_code": ["99213"],
"revenue_center_code": ["0450"],
"place_of_service_code": ["11"],
"bill_type_code": ["131"],
"diagnosis_code_1": ["J01"],
"drg_code_type": [None],
"drg_code": [None],
"drg_description": [None],
"data_source": ["ds1"],
"facility_id": ["NPI1"],
"rendering_id": ["NPI2"],
"admission_date": [date(2024, 1, 1)],
"discharge_date": [date(2024, 1, 5)],
"claim_start_date": [date(2024, 1, 1)],
"claim_end_date": [date(2024, 1, 5)],
"claim_line_start_date": [date(2024, 1, 1)],
"claim_line_end_date": [date(2024, 1, 5)],
}
)
dx = pl.DataFrame(
{
"icd_10_cm_code": ["J01"],
"default_ccsr_category_ip": ["RES001"],
"default_ccsr_category_op": ["RES002"],
"default_ccsr_category_description_ip": ["Respiratory IP"],
"default_ccsr_category_description_op": ["Respiratory OP"],
}
)
bt = pl.DataFrame(
{
"bill_type_code": ["131"],
"bill_type_description": ["Hospital Outpatient"],
}
)
ccs = pl.DataFrame(
{
"hcpcs_code": ["99213"],
"ccs_category": ["227"],
"ccs_category_description": ["E&M Visit"],
"start_valid_date": [date(2023, 1, 1)],
"end_valid_date": [date(2025, 12, 31)],
"release_year": [2023],
}
)
nitos = pl.DataFrame(
{
"hcpcs_code": ["99213"],
"modality": ["Office Visit"],
}
)
pos = pl.DataFrame(
{
"place_of_service_code": ["11"],
"place_of_service_description": ["Office"],
}
)
prov = pl.DataFrame(
{
"npi": ["NPI1", "NPI2"],
"primary_taxonomy_code": ["TAX1", "TAX2"],
"primary_specialty_description": ["Internal Med", "Cardio"],
}
)
rev = pl.DataFrame(
{
"revenue_center_code": ["0450"],
"revenue_center_description": ["ER Revenue"],
}
)
result = cp.service_category__stg_medical_claim(
dx, mc, bt, ccs, nitos, pos, prov, rev
)
expected_cols = {
"claim_id",
"claim_line_number",
"claim_line_id",
"claim_type",
"start_date",
"end_date",
"admission_date",
"discharge_date",
"claim_start_date",
"claim_end_date",
"claim_line_start_date",
"claim_line_end_date",
"bill_type_code",
"bill_type_description",
"hcpcs_code",
"ccs_category",
"ccs_category_description",
"drg_code_type",
"drg_code",
"drg_description",
"place_of_service_code",
"place_of_service_description",
"revenue_center_code",
"revenue_center_description",
"diagnosis_code_1",
"default_ccsr_category_ip",
"default_ccsr_category_op",
"default_ccsr_category_description_ip",
"default_ccsr_category_description_op",
"primary_taxonomy_code",
"primary_specialty_description",
"rend_primary_specialty_description",
"modality",
"data_source",
}
assert set(result.columns) == expected_cols
assert len(result) == 1
# CCS match within valid date range
assert result["ccs_category"].to_list() == ["227"]
def test_ccs_date_fallback_to_max_year(self):
"""When start_date year > max release_year, keep the max-year CCS."""
mc = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
"claim_type": ["professional"],
"hcpcs_code": ["99213"],
"revenue_center_code": pl.Series([None], dtype=pl.Utf8),
"place_of_service_code": pl.Series([None], dtype=pl.Utf8),
"bill_type_code": pl.Series([None], dtype=pl.Utf8),
"diagnosis_code_1": pl.Series([None], dtype=pl.Utf8),
"drg_code_type": pl.Series([None], dtype=pl.Utf8),
"drg_code": pl.Series([None], dtype=pl.Utf8),
"drg_description": pl.Series([None], dtype=pl.Utf8),
"data_source": ["ds1"],
"facility_id": pl.Series([None], dtype=pl.Utf8),
"rendering_id": pl.Series([None], dtype=pl.Utf8),
"admission_date": [date(2026, 6, 1)],
"discharge_date": [date(2026, 6, 5)],
"claim_start_date": pl.Series([None], dtype=pl.Date),
"claim_end_date": pl.Series([None], dtype=pl.Date),
"claim_line_start_date": pl.Series([None], dtype=pl.Date),
"claim_line_end_date": pl.Series([None], dtype=pl.Date),
}
)
dx = pl.DataFrame(
{
"icd_10_cm_code": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_ip": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_op": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_description_ip": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_description_op": pl.Series([], dtype=pl.Utf8),
}
)
bt = pl.DataFrame(
{
"bill_type_code": pl.Series([], dtype=pl.Utf8),
"bill_type_description": pl.Series([], dtype=pl.Utf8),
}
)
ccs = pl.DataFrame(
{
"hcpcs_code": ["99213"],
"ccs_category": ["227"],
"ccs_category_description": ["E&M Visit"],
"start_valid_date": [date(2024, 1, 1)],
"end_valid_date": [date(2024, 12, 31)],
"release_year": [2024],
}
)
nitos = pl.DataFrame(
{
"hcpcs_code": pl.Series([], dtype=pl.Utf8),
"modality": pl.Series([], dtype=pl.Utf8),
}
)
pos = pl.DataFrame(
{
"place_of_service_code": pl.Series([], dtype=pl.Utf8),
"place_of_service_description": pl.Series([], dtype=pl.Utf8),
}
)
prov = pl.DataFrame(
{
"npi": pl.Series([], dtype=pl.Utf8),
"primary_taxonomy_code": pl.Series([], dtype=pl.Utf8),
"primary_specialty_description": pl.Series([], dtype=pl.Utf8),
}
)
rev = pl.DataFrame(
{
"revenue_center_code": pl.Series([], dtype=pl.Utf8),
"revenue_center_description": pl.Series([], dtype=pl.Utf8),
}
)
result = cp.service_category__stg_medical_claim(
dx, mc, bt, ccs, nitos, pos, prov, rev
)
# start_date = 2026-06-01, release_year max = 2024
# 2026 > 2024 and release_year == 2024 → should keep CCS
assert result["ccs_category"].to_list() == ["227"]
def test_ccs_no_match_nulls_category(self):
"""CCS that falls outside date range and not max-year → null."""
mc = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
"claim_type": ["professional"],
"hcpcs_code": ["99213"],
"revenue_center_code": pl.Series([None], dtype=pl.Utf8),
"place_of_service_code": pl.Series([None], dtype=pl.Utf8),
"bill_type_code": pl.Series([None], dtype=pl.Utf8),
"diagnosis_code_1": pl.Series([None], dtype=pl.Utf8),
"drg_code_type": pl.Series([None], dtype=pl.Utf8),
"drg_code": pl.Series([None], dtype=pl.Utf8),
"drg_description": pl.Series([None], dtype=pl.Utf8),
"data_source": ["ds1"],
"facility_id": pl.Series([None], dtype=pl.Utf8),
"rendering_id": pl.Series([None], dtype=pl.Utf8),
"admission_date": [date(2023, 6, 1)],
"discharge_date": [date(2023, 6, 5)],
"claim_start_date": pl.Series([None], dtype=pl.Date),
"claim_end_date": pl.Series([None], dtype=pl.Date),
"claim_line_start_date": pl.Series([None], dtype=pl.Date),
"claim_line_end_date": pl.Series([None], dtype=pl.Date),
}
)
dx = pl.DataFrame(
{
"icd_10_cm_code": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_ip": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_op": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_description_ip": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_description_op": pl.Series([], dtype=pl.Utf8),
}
)
bt = pl.DataFrame(
{
"bill_type_code": pl.Series([], dtype=pl.Utf8),
"bill_type_description": pl.Series([], dtype=pl.Utf8),
}
)
# CCS valid 2024-01-01 to 2024-12-31 with release 2024
# Claim start_date 2023-06-01 → outside range AND 2023 < 2024
ccs = pl.DataFrame(
{
"hcpcs_code": ["99213"],
"ccs_category": ["227"],
"ccs_category_description": ["E&M Visit"],
"start_valid_date": [date(2024, 1, 1)],
"end_valid_date": [date(2024, 12, 31)],
"release_year": [2024],
}
)
nitos = pl.DataFrame(
{
"hcpcs_code": pl.Series([], dtype=pl.Utf8),
"modality": pl.Series([], dtype=pl.Utf8),
}
)
pos = pl.DataFrame(
{
"place_of_service_code": pl.Series([], dtype=pl.Utf8),
"place_of_service_description": pl.Series([], dtype=pl.Utf8),
}
)
prov = pl.DataFrame(
{
"npi": pl.Series([], dtype=pl.Utf8),
"primary_taxonomy_code": pl.Series([], dtype=pl.Utf8),
"primary_specialty_description": pl.Series([], dtype=pl.Utf8),
}
)
rev = pl.DataFrame(
{
"revenue_center_code": pl.Series([], dtype=pl.Utf8),
"revenue_center_description": pl.Series([], dtype=pl.Utf8),
}
)
result = cp.service_category__stg_medical_claim(
dx, mc, bt, ccs, nitos, pos, prov, rev
)
assert result["ccs_category"].to_list() == [None]
class TestServiceCategoryStgMedicalClaimFetchone:
"""Cover the except branch (lines 1143-1144) for non-polars backends."""
def test_ccs_max_year_fetchone_fallback(self):
"""Patch .item to raise AttributeError so fetchone path runs."""
mc = pl.DataFrame(
{
"claim_id": ["C1"],
"claim_line_number": [1],
"claim_type": ["professional"],
"hcpcs_code": ["99213"],
"revenue_center_code": pl.Series([None], dtype=pl.Utf8),
"place_of_service_code": pl.Series([None], dtype=pl.Utf8),
"bill_type_code": pl.Series([None], dtype=pl.Utf8),
"diagnosis_code_1": pl.Series([None], dtype=pl.Utf8),
"drg_code_type": pl.Series([None], dtype=pl.Utf8),
"drg_code": pl.Series([None], dtype=pl.Utf8),
"drg_description": pl.Series([None], dtype=pl.Utf8),
"data_source": ["ds1"],
"facility_id": pl.Series([None], dtype=pl.Utf8),
"rendering_id": pl.Series([None], dtype=pl.Utf8),
"admission_date": [date(2024, 1, 1)],
"discharge_date": [date(2024, 1, 5)],
"claim_start_date": pl.Series([None], dtype=pl.Date),
"claim_end_date": pl.Series([None], dtype=pl.Date),
"claim_line_start_date": pl.Series([None], dtype=pl.Date),
"claim_line_end_date": pl.Series([None], dtype=pl.Date),
}
)
dx = pl.DataFrame(
{
"icd_10_cm_code": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_ip": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_op": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_description_ip": pl.Series([], dtype=pl.Utf8),
"default_ccsr_category_description_op": pl.Series([], dtype=pl.Utf8),
}
)
bt = pl.DataFrame(
{
"bill_type_code": pl.Series([], dtype=pl.Utf8),
"bill_type_description": pl.Series([], dtype=pl.Utf8),
}
)
ccs = pl.DataFrame(
{
"hcpcs_code": ["99213"],
"ccs_category": ["227"],
"ccs_category_description": ["E&M Visit"],
"start_valid_date": [date(2024, 1, 1)],
"end_valid_date": [date(2024, 12, 31)],
"release_year": [2024],
}
)
nitos = pl.DataFrame(
{
"hcpcs_code": pl.Series([], dtype=pl.Utf8),
"modality": pl.Series([], dtype=pl.Utf8),
}
)
pos = pl.DataFrame(
{
"place_of_service_code": pl.Series([], dtype=pl.Utf8),
"place_of_service_description": pl.Series([], dtype=pl.Utf8),
}
)
prov = pl.DataFrame(
{
"npi": pl.Series([], dtype=pl.Utf8),
"primary_taxonomy_code": pl.Series([], dtype=pl.Utf8),
"primary_specialty_description": pl.Series([], dtype=pl.Utf8),
}
)
rev = pl.DataFrame(
{
"revenue_center_code": pl.Series([], dtype=pl.Utf8),
"revenue_center_description": pl.Series([], dtype=pl.Utf8),
}
)
from unittest.mock import patch
orig_item = pl.DataFrame.item
call_count = 0
def patched_item(self_df, *args, **kwargs):
nonlocal call_count
call_count += 1
# Raise on the specific max_release_year call
if call_count == 1:
raise AttributeError("patched")
return orig_item(self_df, *args, **kwargs)
with patch.object(pl.DataFrame, "item", patched_item):
# The native frame is a polars DataFrame; we patch .item
# to raise on the first call (the max_release_year extraction).
# The fetchone fallback expects a fetchone() method, so we
# need to also patch that.
pass
# Simpler approach: make a wrapper that returns an object with
# fetchone instead of item.
class FakeNative:
def __init__(self, val):
self._val = val
def fetchone(self):
return (self._val,)
import narwhals as nw
orig_to_native = nw.DataFrame.to_native
native_call_count = [0]
def patched_to_native(self_nw_df):
native_call_count[0] += 1
native = orig_to_native(self_nw_df)
# The first to_native call is for the max_release_year frame
if native_call_count[0] == 1:
return FakeNative(native.item(0, 0))
return native
with patch.object(nw.DataFrame, "to_native", patched_to_native):
result = cp.service_category__stg_medical_claim(
dx, mc, bt, ccs, nitos, pos, prov, rev
)
assert len(result) == 1
assert result["ccs_category"].to_list() == ["227"]
class TestServiceCategoryStgOfficeBased:
def test_filters_professional_office_pos(self, svc_mc):
prof = pl.DataFrame(
{
"claim_id": ["C2"],
"claim_line_number": [1],
"data_source": ["ds1"],
"claim_line_id": ["C2|1"],
"service_type": ["professional"],
}
)
result = cp.service_category__stg_office_based(svc_mc, prof)
# C2 is professional with POS "11" (in 11, 02, 10)
assert len(result) == 1
assert result["service_type"].to_list() == ["office based"]
class TestServiceCategoryStgOutpatientInstitutional:
def test_anti_join_institutional(self, svc_mc):
"""Institutional claims NOT in inpatient → outpatient."""
inpatient = pl.DataFrame(
{
"claim_id": ["C1"],
"data_source": ["ds1"],
"service_type": ["inpatient"],
}
)
result = cp.service_category__stg_outpatient_institutional(inpatient, svc_mc)
# C3 is institutional and NOT in inpatient → outpatient
out_ids = result["claim_id"].to_list()
assert "C3" in out_ids
assert "C1" not in out_ids
assert result["service_type"].to_list()[0] == "outpatient"
class TestServiceCategoryStgProfessional:
def test_filters_professional(self, svc_mc):
result = cp.service_category__stg_professional(svc_mc)
# C2 and C4 are professional
assert len(result) == 2
for st in result["service_type"].to_list():
assert st == "professional"
class TestUrgentCareAnchorFilter:
"""urgent_care__anchor_events has a filter, not just select."""
def test_filters_by_service_category(self, stg):
result = cp.urgent_care__anchor_events(stg)
# C3 and C4 have service_category_2 = "urgent care"
assert len(result) == 2