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:
Venkatakrishna Avula
2026-03-06 16:11:59 +00:00
committed by Katon Minhas
parent 786bab6118
commit 6744c57f95
7 changed files with 65 additions and 25 deletions
+6 -1
View File
@@ -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 ""
+13 -6
View File
@@ -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
+25 -7
View File
@@ -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)]