Skip to content

Commit 672e688

Browse files
Create generate_eob_sample.py
1 parent bb05a7f commit 672e688

1 file changed

Lines changed: 253 additions & 0 deletions

File tree

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
import argparse
2+
import json
3+
import sys
4+
from pathlib import Path
5+
from typing import Any
6+
7+
import pandas as pd
8+
9+
10+
def main():
11+
parser = argparse.ArgumentParser(
12+
description="Generate EOB sample JSON from SYNTHETIC_EOB.csv based on claim unique ID."
13+
)
14+
parser.add_argument("--clm_uniq_id", required=True, help="Pass the claim unique ID ")
15+
parser.add_argument("--eob_type", required=True, help="EOB Type")
16+
args = parser.parse_args()
17+
18+
if args.eob_type == "Pharmacy":
19+
result = create_pharmacy(args.clm_uniq_id)
20+
else:
21+
print("Unknown Type")
22+
sys.exit(1)
23+
24+
with Path(result.output_file).open(mode="w", encoding="utf-8") as f:
25+
json.dump(result.result_json, f, indent=2)
26+
27+
print(f"Successfully generated sample JSON: {result.output_file}")
28+
29+
class Result:
30+
result_json: dict[str, Any]
31+
output_file: str
32+
33+
34+
def create_pharmacy(clm_uniq_id: Any) -> Result:
35+
claim_row = read_clm(clm_uniq_id)
36+
37+
provider_npi = str(claim_row.get("PRVDR_PRSCRBNG_PRVDR_NPI_NUM", "")).strip()
38+
39+
prov_row = read_provider(provider_npi)
40+
41+
clm_sig_row = read_sig_line(str(claim_row.get("CLM_DT_SGNTR_SK", "")).strip())
42+
43+
clm_sbmtr_cntrct_num = str(claim_row.get("CLM_SBMTR_CNTRCT_NUM", "")).strip()
44+
clm_sbmtr_cntrct_pbp_num = str(claim_row.get("CLM_SBMTR_CNTRCT_PBP_NUM", "")).strip()
45+
46+
ctr_pmp_row = read_pmp(clm_sbmtr_cntrct_num,clm_sbmtr_cntrct_pbp_num)
47+
48+
clm_lines = read_line(claim_row)
49+
50+
clm_line = {} if clm_lines.empty else clm_lines.iloc[0]
51+
52+
rx_line = read_rx_line(claim_row)
53+
54+
output_json = {
55+
"resourceType": "ExplanationOfBenefit-Pharmacy",
56+
"id": str(clm_uniq_id.replace('-', '')).strip(),
57+
"lastUpdated": str(claim_row.get("IDR_UPDT_TS", "")).strip(),
58+
"CLM_FINL_ACTN_IND": str(claim_row.get("CLM_FINL_ACTN_IND", "")).strip(),
59+
"CLM_SRC_ID": str(claim_row.get("CLM_SRC_ID", "")).strip(),
60+
"BENE_SK": str(claim_row.get("BENE_SK", "")).strip(),
61+
"CLM_TYPE_CD": int(str(claim_row.get("CLM_TYPE_CD", "")).strip()),
62+
"CLM_UNIQ_ID": str(claim_row.get("CLM_UNIQ_ID", "")).strip(),
63+
"CLM_CNTL_NUM": str(claim_row.get("CLM_CNTL_NUM", "")).strip(),
64+
"CLM_ORIG_CNTL_NUM": str(claim_row.get("CLM_ORIG_CNTL_NUM", "")).strip(),
65+
"CLM_FROM_DT": str(claim_row.get("CLM_FROM_DT", "")).strip(),
66+
"CLM_THRU_DT": str(claim_row.get("CLM_THRU_DT", "")).strip(),
67+
"CLM_EFCTV_DT": str(claim_row.get("CLM_EFCTV_DT", "")).strip(),
68+
"CLM_SRVC_PRVDR_GNRC_ID_NUM": str(claim_row.get("CLM_SRVC_PRVDR_GNRC_ID_NUM", "")).strip(),
69+
"CLM_PD_DT": str(claim_row.get("CLM_PD_DT", "")).strip(),
70+
"PRVDR_PRSCRBNG_PRVDR_NPI_NUM": provider_npi,
71+
"CLM_PRSBNG_PRVDR_GNRC_ID_NUM": str(claim_row.get("CLM_PRSBNG_PRVDR_GNRC_ID_NUM", ""))
72+
.strip(),
73+
"PRVDR_PRSBNG_ID_QLFYR_CD": str(claim_row.get("PRVDR_PRSBNG_ID_QLFYR_CD", "")).strip(),
74+
"PRVDR_LAST_NAME": str(prov_row.get("PRVDR_LAST_NAME", "")).strip(),
75+
"CNTRCT_PBP_NAME": str(ctr_pmp_row.get("CNTRCT_PBP_NAME", "")).strip(),
76+
"CLM_BENE_PMT_AMT": str(claim_row.get("CLM_BENE_PMT_AMT", "")).strip(),
77+
"CLM_OTHR_TP_PD_AMT": str(claim_row.get("CLM_OTHR_TP_PD_AMT", "")).strip(),
78+
"META_SRC_SK": str(claim_row.get("META_SRC_SK", "")).strip(),
79+
"PRVDR_SRVC_ID_QLFYR_CD": str(claim_row.get("PRVDR_SRVC_ID_QLFYR_CD", "")).strip(),
80+
"supportingInfoComponents": [],
81+
"lineItemComponents": [
82+
{
83+
"CLM_LINE_NUM": str(clm_line.get("CLM_LINE_NUM", "")).strip(),
84+
"CLM_LINE_FROM_DT": str(clm_line.get("CLM_LINE_FROM_DT", "")).strip(),
85+
"CLM_LINE_NDC_CD": str(clm_line.get("CLM_LINE_NDC_CD", "")).strip(),
86+
"CLM_LINE_NDC_QTY": str(clm_line.get("CLM_LINE_NDC_QTY", "")).strip(),
87+
"CLM_LINE_NDC_QTY_QLFYR_CD": str(clm_line.get("CLM_LINE_NDC_QTY_QLFYR_CD", ""))
88+
.strip(),
89+
"CLM_LINE_CVRD_PD_AMT": str(clm_line.get("CLM_LINE_CVRD_PD_AMT", "")).strip(),
90+
"CLM_LINE_GRS_ABOVE_THRSHLD_AMT": str(rx_line.get(
91+
"CLM_LINE_GRS_ABOVE_THRSHLD_AMT", "")).strip(),
92+
"CLM_LINE_GRS_BLW_THRSHLD_AMT": str(rx_line.get(
93+
"CLM_LINE_GRS_BLW_THRSHLD_AMT", "")).strip(),
94+
"CLM_LINE_LIS_AMT": str(rx_line.get("CLM_LINE_LIS_AMT", "")).strip(),
95+
"CLM_LINE_TROOP_TOT_AMT": str(rx_line.get("CLM_LINE_TROOP_TOT_AMT", "")).strip(),
96+
"CLM_LINE_PLRO_AMT": str(rx_line.get("CLM_LINE_PLRO_AMT", "")).strip(),
97+
"CLM_RPTD_MFTR_DSCNT_AMT": str(rx_line.get("CLM_RPTD_MFTR_DSCNT_AMT", "")).strip(),
98+
"CLM_LINE_INGRDNT_CST_AMT": str(rx_line.get("CLM_LINE_INGRDNT_CST_AMT", "")).strip(),
99+
"CLM_LINE_SRVC_CST_AMT": str(rx_line.get("CLM_LINE_SRVC_CST_AMT", "")).strip(),
100+
"CLM_LINE_SLS_TAX_AMT": str(rx_line.get("CLM_LINE_SLS_TAX_AMT", "")).strip(),
101+
"CLM_LINE_VCCN_ADMIN_FEE_AMT": str(rx_line.get("CLM_LINE_VCCN_ADMIN_FEE_AMT", ""))
102+
.strip(),
103+
"CLM_PRCNG_EXCPTN_CD": str(rx_line.get("CLM_PRCNG_EXCPTN_CD", "")).strip(),
104+
"CLM_LINE_BENE_PMT_AMT": str(clm_line.get("CLM_LINE_BENE_PMT_AMT", "")).strip(),
105+
"CLM_CMS_CALCD_MFTR_DSCNT_AMT": str(rx_line.get(
106+
"CLM_CMS_CALCD_MFTR_DSCNT_AMT", "")).strip(),
107+
"CLM_LINE_GRS_CVRD_CST_TOT_AMT": str(rx_line.get(
108+
"CLM_LINE_GRS_CVRD_CST_TOT_AMT", "")).strip(),
109+
"CLM_LINE_REBT_PASSTHRU_POS_AMT": str(rx_line.get(
110+
"CLM_LINE_REBT_PASSTHRU_POS_AMT", "")).strip(),
111+
"CLM_PHRMCY_PRICE_DSCNT_AT_POS_AMT": str(rx_line.get(
112+
"CLM_PHRMCY_PRICE_DSCNT_AT_POS_AMT", "")).strip(),
113+
"CLM_LINE_OTHR_TP_PD_AMT": str(clm_line.get(
114+
"CLM_LINE_OTHR_TP_PD_AMT", "")).strip(),
115+
"CLM_LINE_NCVRD_PD_AMT": str(clm_line.get(
116+
"CLM_LINE_NCVRD_PD_AMT", "")).strip(),
117+
"CLM_LINE_RPTD_GAP_DSCNT_AMT": str(rx_line.get(
118+
"CLM_LINE_RPTD_GAP_DSCNT_AMT", "")).strip(),
119+
"CLM_LINE_AUTHRZD_FILL_NUM": str(rx_line.get(
120+
"CLM_LINE_AUTHRZD_FILL_NUM", "")).strip(),
121+
"CLM_PHRMCY_SRVC_TYPE_CD": str(rx_line.get(
122+
"CLM_PHRMCY_SRVC_TYPE_CD", "")).strip(),
123+
"CLM_LINE_RX_ORGN_CD": str(rx_line.get(
124+
"CLM_LINE_RX_ORGN_CD", "")).strip(),
125+
"CLM_BRND_GNRC_CD": str(rx_line.get(
126+
"CLM_BRND_GNRC_CD", "")).strip(),
127+
"CLM_PTNT_RSDNC_CD": str(rx_line.get(
128+
"CLM_PTNT_RSDNC_CD", "")).strip(),
129+
"CLM_LTC_DSPNSNG_MTHD_CD": str(rx_line.get(
130+
"CLM_LTC_DSPNSNG_MTHD_CD", "")).strip(),
131+
"CLM_CMPND_CD": str(rx_line.get("CLM_CMPND_CD", "")).strip(),
132+
"CLM_LINE_DAYS_SUPLY_QTY": str(rx_line.get("CLM_LINE_DAYS_SUPLY_QTY", "")).strip(),
133+
"CLM_LINE_RX_FILL_NUM": str(rx_line.get("CLM_LINE_RX_FILL_NUM", "")).strip(),
134+
"CLM_DAW_PROD_SLCTN_CD": str(rx_line.get("CLM_DAW_PROD_SLCTN_CD", "")).strip(),
135+
"CLM_DRUG_CVRG_STUS_CD": str(rx_line.get("CLM_DRUG_CVRG_STUS_CD", "")).strip(),
136+
"CLM_CTSTRPHC_CVRG_IND_CD": str(rx_line.get("CLM_CTSTRPHC_CVRG_IND_CD", ""))
137+
.strip(),
138+
"CLM_LINE_RX_NUM": str(clm_line.get(
139+
"CLM_LINE_RX_NUM", "")).strip(),
140+
"CLM_DSPNSNG_STUS_CD": str(rx_line.get("CLM_DSPNSNG_STUS_CD", "")).strip(),
141+
}
142+
],
143+
"CLM_CMS_PROC_DT": str(clm_sig_row.get("CLM_CMS_PROC_DT", "")).strip(),
144+
"CLM_IDR_LD_DT ": str(claim_row.get("CLM_IDR_LD_DT", "")).strip(),
145+
"CLM_ADJSTMT_TYPE_CD": str(claim_row.get("CLM_ADJSTMT_TYPE_CD", "")).strip(),
146+
"CLM_SBMT_FRMT_CD": str(claim_row.get("CLM_SBMT_FRMT_CD", "")).strip(),
147+
"CLM_SBMTR_CNTRCT_NUM": str(claim_row.get("CLM_SBMTR_CNTRCT_NUM", "")).strip(),
148+
"CLM_SBMTR_CNTRCT_PBP_NUM": str(claim_row.get("CLM_SBMTR_CNTRCT_PBP_NUM", "")).strip(),
149+
"CLM_DT_SGNTR_SK": str(clm_sig_row.get("CLM_DT_SGNTR_SK", "")).strip(),
150+
}
151+
152+
result = Result()
153+
result.result_json = output_json
154+
result.output_file = "sample-data/EOB-Pharmacy-Sample.json"
155+
return result
156+
157+
158+
def read_clm(clm_uniq_id: Any) -> Any:
159+
eob_path = "out/SYNTHETIC_CLM.csv"
160+
if not Path(eob_path).exists():
161+
print("EOB file not found. Run the generator or this will not go well.")
162+
sys.exit(1)
163+
164+
claims_found = pd.read_csv(eob_path, dtype=str, keep_default_na=False)
165+
166+
clm_matches = claims_found[claims_found["CLM_UNIQ_ID"] == clm_uniq_id]
167+
168+
if clm_matches.empty:
169+
print(f"No claims found for claim unique ID: {clm_uniq_id}")
170+
sys.exit(1)
171+
172+
return clm_matches.iloc[0]
173+
174+
def read_provider(provider_npi: Any) -> Any:
175+
provider_path = "out/SYNTHETIC_PRVDR_HSTRY.csv"
176+
177+
if not Path(provider_path).exists():
178+
print("Provider file not found. Run the generator or this will not go well.")
179+
sys.exit(1)
180+
181+
provs_found = pd.read_csv(provider_path, dtype=str, keep_default_na=False)
182+
183+
prov_matches = provs_found[provs_found["PRVDR_NPI_NUM"] == provider_npi]
184+
185+
return {} if prov_matches.empty else prov_matches.iloc[0]
186+
187+
def read_sig_line(clm_dt_sgntr_sk: Any) -> Any:
188+
clm_sig_path = "out/SYNTHETIC_CLM_DT_SGNTR.csv"
189+
190+
if not Path(clm_sig_path).exists():
191+
print("Claim signature file not found. Run the generator or this will not go well.")
192+
sys.exit(1)
193+
194+
clm_sig_found = pd.read_csv(clm_sig_path, dtype=str, keep_default_na=False)
195+
196+
clm_sig_matches = clm_sig_found[clm_sig_found["CLM_DT_SGNTR_SK"] == clm_dt_sgntr_sk]
197+
198+
return {} if clm_sig_matches.empty else clm_sig_matches.iloc[0]
199+
200+
def read_pmp(clm_sbmtr_cntrct_num:Any,clm_sbmtr_cntrct_pbp_num:Any) -> Any:
201+
ctr_pmp_path = "out/SYNTHETIC_CNTRCT_PBP_NUM.csv"
202+
203+
if not Path(ctr_pmp_path).exists():
204+
print("Provider file not found. Run the generator or this will not go well.")
205+
sys.exit(1)
206+
207+
ctr_pmp_found = pd.read_csv(ctr_pmp_path, dtype=str, keep_default_na=False)
208+
209+
ctr_pmp_matches = ctr_pmp_found[
210+
(ctr_pmp_found["CNTRCT_NUM"] == clm_sbmtr_cntrct_num)
211+
& (ctr_pmp_found["CNTRCT_PBP_NUM"] == clm_sbmtr_cntrct_pbp_num)
212+
]
213+
214+
return {} if ctr_pmp_matches.empty else ctr_pmp_matches.iloc[0]
215+
216+
def read_line(clm_line:Any) -> Any:
217+
line_path = "out/SYNTHETIC_CLM_LINE.csv"
218+
219+
if not Path(line_path).exists():
220+
print("Claim Line file not found. Run the generator or this will not go well.")
221+
sys.exit(1)
222+
223+
line_found = pd.read_csv(line_path, dtype=str, keep_default_na=False)
224+
225+
return line_found[
226+
(line_found["GEO_BENE_SK"] == clm_line["GEO_BENE_SK"])
227+
& (line_found["CLM_DT_SGNTR_SK"] == clm_line["CLM_DT_SGNTR_SK"])
228+
& (line_found["CLM_TYPE_CD"] == clm_line["CLM_TYPE_CD"])
229+
& (line_found["CLM_NUM_SK"] == clm_line["CLM_NUM_SK"])
230+
]
231+
232+
def read_rx_line(clm_line:Any) -> Any:
233+
line_rx_path = "out/SYNTHETIC_CLM_LINE_RX.csv"
234+
235+
if not Path(line_rx_path).exists():
236+
print("Claim RX Line file not found. Run the generator or this will not go well.")
237+
sys.exit(1)
238+
239+
line_rx_found = pd.read_csv(line_rx_path, dtype=str, keep_default_na=False)
240+
241+
line_rx_matches = line_rx_found[
242+
(line_rx_found["GEO_BENE_SK"] == clm_line["GEO_BENE_SK"])
243+
& (line_rx_found["CLM_DT_SGNTR_SK"] == clm_line["CLM_DT_SGNTR_SK"])
244+
& (line_rx_found["CLM_TYPE_CD"] == clm_line["CLM_TYPE_CD"])
245+
& (line_rx_found["CLM_NUM_SK"] == clm_line["CLM_NUM_SK"])
246+
]
247+
248+
return {} if line_rx_matches.empty else line_rx_matches.iloc[0]
249+
250+
251+
252+
if __name__ == "__main__":
253+
main()

0 commit comments

Comments
 (0)