Merged in bugfix/DAIP2-1870-dynamic-issues (pull request #892)
Bugfix/DAIP2-1870 dynamic issues * updated list format appending * fill bill type from claim type cd * Fixed remaining format fixes * Merged DEV into bugfix/DAIP2-1870-dynamic-issues * changed crosswalk mapping from PRODUCT to AARETE_DERIVED_PRODUCT * Merged DEV into bugfix/DAIP2-1870-dynamic-issues * updating LOB field values as well from PRODUCT AND PROGRAM * updated apply crosswalk for reverse mapping * Merged DEV into bugfix/DAIP2-1870-dynamic-issues * added QHP and BHP * removed lob reverse mapping * Merged DEV into bugfix/DAIP2-1870-dynamic-issues * Remove Bill Type/Claim Type fill * Merged DEV into bugfix/DAIP2-1870-dynamic-issues * Black format * Merged DEV into bugfix/DAIP2-1870-dynamic-issues Approved-by: Katon Minhas
This commit is contained in:
committed by
Katon Minhas
parent
786bab6118
commit
6744c57f95
@@ -567,7 +567,12 @@ def fill_bill_type(
|
||||
bill_codes, bill_descs = [], []
|
||||
for description in llm_answer_final:
|
||||
if description in BILL_TYPE_REVERSE_MAPPING:
|
||||
bill_codes += BILL_TYPE_REVERSE_MAPPING[description]
|
||||
codes = BILL_TYPE_REVERSE_MAPPING[description]
|
||||
# Reverse mapping returns a list of codes for each description
|
||||
if isinstance(codes, list):
|
||||
bill_codes.extend(codes)
|
||||
else:
|
||||
bill_codes.append(codes)
|
||||
bill_descs.append(description)
|
||||
|
||||
if bill_codes:
|
||||
|
||||
@@ -190,7 +190,9 @@
|
||||
"NY State of Health" : "NYSOH",
|
||||
"Health and Recovery Plan (HARP)" : "HARP",
|
||||
"Child Health Plus (CHP)" : "CHPLUS",
|
||||
"Essential Plan" : "EPNY"
|
||||
"Essential Plan" : "EPNY",
|
||||
"New York State Health Insurance Exchange Qualified Health Plan" : "QHP",
|
||||
"Basic Health Plan" : "BHP"
|
||||
},
|
||||
"NC" : {
|
||||
"NC Health Choice" : "CHIP"
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"SNAP" : "Medicaid",
|
||||
"TANF" : "Medicaid",
|
||||
"LTSS" : "Medicaid",
|
||||
"BHP" : "Medicaid",
|
||||
"SNP" : "Duals",
|
||||
"CSNP" : "Duals",
|
||||
"DSNP" : "Duals",
|
||||
@@ -43,7 +44,8 @@
|
||||
"SLVR" : "Marketplace",
|
||||
"BRNZ" : "Marketplace",
|
||||
"CONN" : "Marketplace",
|
||||
"CATA" : "Marketplace"
|
||||
"CATA" : "Marketplace",
|
||||
"QHP" : "Marketplace"
|
||||
},
|
||||
"state_mapping" : {
|
||||
"AL" : {
|
||||
|
||||
@@ -97,13 +97,13 @@ def fill_na_mapping(answer_dicts):
|
||||
# Update all_lob_values after processing all program LOB values
|
||||
all_lob_values.update(program_lob_values)
|
||||
|
||||
# Get AARETE_DERIVED_LOB from PRODUCT crosswalk (always check if PRODUCT exists)
|
||||
# Get AARETE_DERIVED_LOB from AARETE_DERIVED_PRODUCT crosswalk (always check if PRODUCT exists)
|
||||
product_lob_values = set()
|
||||
if not string_utils.is_empty(answer_dict.get("PRODUCT")):
|
||||
if not string_utils.is_empty(answer_dict.get("AARETE_DERIVED_PRODUCT")):
|
||||
product_filled_value_list = fill_na_from_field(
|
||||
answer_dict,
|
||||
"AARETE_DERIVED_LOB",
|
||||
"PRODUCT",
|
||||
"AARETE_DERIVED_PRODUCT",
|
||||
"src/constants/mappings/crosswalk_product_lob.json",
|
||||
)
|
||||
if (
|
||||
|
||||
@@ -1218,12 +1218,18 @@ def format_as_json_list(val):
|
||||
"""
|
||||
# 1. Handle actual lists or Nulls
|
||||
if isinstance(val, list):
|
||||
filtered = [
|
||||
str(i).strip()
|
||||
for i in val
|
||||
if i is not None and not _is_empty_list_placeholder(i)
|
||||
]
|
||||
return json.dumps(filtered) if filtered else ""
|
||||
# Flatten nested lists before processing
|
||||
flattened = []
|
||||
for i in val:
|
||||
if i is None or _is_empty_list_placeholder(i):
|
||||
continue
|
||||
# If item is a list itself, extend (flatten)
|
||||
if isinstance(i, list):
|
||||
flattened.extend([str(x).strip() for x in i if x is not None])
|
||||
else:
|
||||
flattened.append(str(i).strip())
|
||||
|
||||
return json.dumps(flattened) if flattened else ""
|
||||
if pd.isna(val) or val == "" or val == "[]":
|
||||
return ""
|
||||
|
||||
|
||||
@@ -34,8 +34,16 @@ class TestCodeFuncs(unittest.TestCase):
|
||||
self.constants.HCPCS_LEVEL2_MAPPING = {"J0002": "Advanced Drug"}
|
||||
self.constants.REV_MAPPING = {"456": "Advanced Revenue"}
|
||||
|
||||
self.constants.BILL_TYPE_MAPPING = {"11X": "Inpatient Hospital"}
|
||||
self.constants.BILL_TYPE_REVERSE_MAPPING = {"Inpatient Hospital": "11X"}
|
||||
# Bill type mappings matching the actual JSON structure
|
||||
self.constants.BILL_TYPE_MAPPING = {
|
||||
"011X": "Inpatient Hospital",
|
||||
"012X": "Inpatient Hospital",
|
||||
"018X": "Inpatient Hospital",
|
||||
}
|
||||
# Reverse mapping returns a list of codes for each description
|
||||
self.constants.BILL_TYPE_REVERSE_MAPPING = {
|
||||
"Inpatient Hospital": ["011X", "012X", "018X"]
|
||||
}
|
||||
|
||||
# Mock the embedding model and function
|
||||
mock_embedding = MagicMock()
|
||||
@@ -254,8 +262,6 @@ class TestCodeFuncs(unittest.TestCase):
|
||||
mock_invoke_claude.return_value = '["Inpatient Hospital"]'
|
||||
|
||||
# Test with valid bill type
|
||||
# Note: Current implementation has a bug where += on string splits it into chars
|
||||
# The test expects the current (buggy) behavior: ['1', '1', 'X']
|
||||
answer_dict = {}
|
||||
result = code_funcs.fill_bill_type(
|
||||
"INPATIENT SERVICE",
|
||||
@@ -264,8 +270,9 @@ class TestCodeFuncs(unittest.TestCase):
|
||||
self.constants.BILL_TYPE_REVERSE_MAPPING,
|
||||
)
|
||||
|
||||
# Current buggy behavior: bill_codes += string splits into chars
|
||||
self.assertEqual(result["BILL_TYPE_CD"], ["1", "1", "X"])
|
||||
# Should return all codes for "Inpatient Hospital" description
|
||||
# Reverse mapping returns ["011X", "012X", "018X"] for "Inpatient Hospital"
|
||||
self.assertEqual(result["BILL_TYPE_CD"], ["011X", "012X", "018X"])
|
||||
self.assertEqual(result["BILL_TYPE_CD_DESC"], ["Inpatient Hospital"])
|
||||
|
||||
# Test with empty response
|
||||
|
||||
@@ -5,13 +5,13 @@ import src.utils.string_utils as string_utils
|
||||
|
||||
|
||||
def apply_crosswalk(
|
||||
val: str | list, mapping: dict[str, str], default: str = "N/A"
|
||||
val: str | list, mapping: dict[str, str | list[str]], default: str = "N/A"
|
||||
) -> list:
|
||||
"""Apply a crosswalk to a value
|
||||
|
||||
Args:
|
||||
val (str | list): Input value (can be string, list, or string representation of list)
|
||||
mapping (dict[str, str]): Mapping dictionary
|
||||
mapping (dict[str, str | list[str]]): Mapping dictionary (supports both regular and reverse mappings)
|
||||
default (str | None, optional): Default value; if None and val is not found in the mapping, val is returned. Defaults to "".
|
||||
|
||||
Returns:
|
||||
@@ -54,11 +54,29 @@ def apply_crosswalk(
|
||||
if v_str in mapping:
|
||||
mapped_result = mapping[v_str]
|
||||
if mapped_result and not string_utils.is_empty(mapped_result):
|
||||
mapped_values.add(mapped_result)
|
||||
elif v_str in mapping.values():
|
||||
mapped_values.add(
|
||||
v_str
|
||||
) # If the value is already a mapped value, add it directly
|
||||
# Handle both string and list values in mapping (e.g., reverse mappings)
|
||||
if isinstance(mapped_result, list):
|
||||
for item in mapped_result:
|
||||
if item and not string_utils.is_empty(item):
|
||||
mapped_values.add(item)
|
||||
else:
|
||||
mapped_values.add(mapped_result)
|
||||
else:
|
||||
# Check if v_str is already a mapped value (in mapping.values())
|
||||
# Handle both str and list[str] values
|
||||
found_in_values = False
|
||||
for mapped_val in mapping.values():
|
||||
if isinstance(mapped_val, list):
|
||||
if v_str in mapped_val:
|
||||
if not string_utils.is_empty(v_str):
|
||||
mapped_values.add(v_str)
|
||||
found_in_values = True
|
||||
break
|
||||
elif v_str == mapped_val:
|
||||
if not string_utils.is_empty(v_str):
|
||||
mapped_values.add(v_str)
|
||||
found_in_values = True
|
||||
break
|
||||
|
||||
# Convert to list and filter out empty values
|
||||
final_mapped = [v for v in mapped_values if v and not string_utils.is_empty(v)]
|
||||
|
||||
Reference in New Issue
Block a user