1212from pathlib import Path
1313from dateutil .parser import parse
1414from datetime import date , datetime , timedelta
15+ from faker import Faker
1516
1617generator = GeneratorUtil ()
18+ faker = Faker ()
1719
1820def save_output_files (clm ,clm_line ,clm_val ,clm_dt_sgntr ,clm_prod ,clm_instnl ,clm_line_instnl ,clm_dcmtn ,clm_fiss ):
1921 Path ("out" ).mkdir (exist_ok = True )
@@ -172,8 +174,6 @@ def add_diagnoses(clm_type_cd=-1):
172174 'CLM_PROD_TYPE_CD' :'D' }
173175 diagnosis_list .append (diagnosis )
174176
175- for diagnosis in diagnosis_list :
176- add_meta_timestamps (diagnosis )
177177 return diagnosis_list
178178
179179
@@ -182,15 +182,13 @@ def gen_procedure_icd10pcs():
182182 procedure ['CLM_PROD_TYPE_CD' ] = 'S'
183183 procedure ['CLM_PRCDR_CD' ] = random .choice (available_procedure_codes_icd10_pcs )
184184 procedure ['CLM_DGNS_PRCDR_ICD_IND' ] = '0'
185- add_meta_timestamps (procedure )
186185 return procedure
187186
188187
189- def gen_claim (bene_sk = '-1' , minDate = '2018-01-01' , maxDate = str (date .today ())):
188+ def gen_claim (bene_sk = '-1' , min_date = '2018-01-01' , max_date = str (date .today ())):
190189 claim = {'CLM' :{},'CLM_LINE' :[],'CLM_DT_SGNTR' :{},'CLM_LINE_INSTNL' :[], 'CLM_DCMTN' :{}}
191190 clm_dt_sgntr = {}
192191 clm_dt_sgntr ['CLM_DT_SGNTR_SK' ] = '' .join (random .choices (string .digits , k = 12 ))
193- add_meta_timestamps (clm_dt_sgntr )
194192 claim ['CLM' ]['CLM_DT_SGNTR_SK' ] = clm_dt_sgntr ['CLM_DT_SGNTR_SK' ]
195193 claim ['CLM' ]['CLM_UNIQ_ID' ] = '' .join (random .choices (string .digits , k = 13 ))
196194 #clm_type_cd = 60
@@ -203,7 +201,7 @@ def gen_claim(bene_sk = '-1', minDate = '2018-01-01', maxDate = str(date.today()
203201 elif (clm_type_cd in fiss_clm_type_cds ):
204202 clm_src_id = 21000
205203 claim ['CLM' ]['CLM_SRC_ID' ] = clm_src_id
206- claim ['CLM' ]['CLM_FROM_DT' ] = random_date (minDate , maxDate )
204+ claim ['CLM' ]['CLM_FROM_DT' ] = random_date (min_date , max_date )
207205 claim ['CLM' ]['CLM_THRU_DT' ] = gen_thru_dt (claim ['CLM' ]['CLM_FROM_DT' ])
208206
209207
@@ -216,7 +214,7 @@ def gen_claim(bene_sk = '-1', minDate = '2018-01-01', maxDate = str(date.today()
216214
217215 claim ['CLM' ]['CLM_NUM_SK' ] = 1
218216 claim ['CLM' ]['CLM_EFCTV_DT' ] = str (date .today ())
219- claim ['CLM' ]['CLM_IDR_LD_DT' ] = str ( date . today () )
217+ claim ['CLM' ]['CLM_IDR_LD_DT' ] = random_date ( claim [ 'CLM' ][ 'CLM_FROM_DT' ], max_date )
220218 claim ['CLM' ]['CLM_OBSLT_DT' ] = '9999-12-31'
221219 claim ['CLM' ]['GEO_BENE_SK' ] = '' .join (random .choices (string .digits , k = 5 ))
222220 claim ['CLM' ]['BENE_SK' ] = bene_sk
@@ -231,7 +229,8 @@ def gen_claim(bene_sk = '-1', minDate = '2018-01-01', maxDate = str(date.today()
231229 claim ['CLM' ]['CLM_CNTRCTR_NUM' ] = random .choice (generator .code_systems ['CLM_CNTRCTR_NUM' ])
232230 claim ['CLM' ]['CLM_NCH_PRMRY_PYR_CD' ] = random .choice (generator .code_systems ['CLM_NCH_PRMRY_PYR_CD' ])
233231
234- add_meta_timestamps (claim ['CLM' ])
232+ add_meta_timestamps (claim ['CLM' ], claim ['CLM' ], max_date )
233+ add_meta_timestamps (clm_dt_sgntr , claim ['CLM' ], max_date )
235234
236235 clm_finl_actn_ind = 'N'
237236 if (clm_type_cd in (10 ,20 ,30 ,40 ,50 ,60 ,61 ,62 ,63 ,71 ,72 ,81 ,82 )):
@@ -267,7 +266,7 @@ def gen_claim(bene_sk = '-1', minDate = '2018-01-01', maxDate = str(date.today()
267266 claim ['CLM_DCMTN' ]['CLM_NUM_SK' ] = claim ['CLM' ]['CLM_NUM_SK' ]
268267 claim ['CLM_DCMTN' ]['GEO_BENE_SK' ] = claim ['CLM' ]['GEO_BENE_SK' ]
269268 claim ['CLM_DCMTN' ]['CLM_TYPE_CD' ] = claim ['CLM' ]['CLM_TYPE_CD' ]
270- add_meta_timestamps (claim ['CLM_DCMTN' ])
269+ add_meta_timestamps (claim ['CLM_DCMTN' ], claim [ 'CLM' ], max_date )
271270
272271 #provider elements:
273272 if ((clm_type_cd < 65 and clm_type_cd >= 10 ) or clm_type_cd in fiss_clm_type_cds ):
@@ -311,7 +310,7 @@ def gen_claim(bene_sk = '-1', minDate = '2018-01-01', maxDate = str(date.today()
311310 'CLM_VAL_SQNC_NUM' :3 }
312311 claim ['CLM_VAL' ].append (clm_val_ime )
313312 for clm_val in claim ['CLM_VAL' ]:
314- add_meta_timestamps (clm_val )
313+ add_meta_timestamps (clm_val , claim [ 'CLM' ], max_date )
315314
316315 #Add procedures
317316 claim ['CLM_PROD' ] = []
@@ -325,6 +324,7 @@ def gen_claim(bene_sk = '-1', minDate = '2018-01-01', maxDate = str(date.today()
325324 procedure ['CLM_NUM_SK' ] = claim ['CLM' ]['CLM_NUM_SK' ]
326325 procedure ['GEO_BENE_SK' ] = claim ['CLM' ]['GEO_BENE_SK' ]
327326 procedure ['CLM_TYPE_CD' ] = claim ['CLM' ]['CLM_TYPE_CD' ]
327+ add_meta_timestamps (procedure , claim ['CLM' ], max_date )
328328 claim ['CLM_PROD' ].append (procedure )
329329
330330 #add diagnoses
@@ -335,6 +335,7 @@ def gen_claim(bene_sk = '-1', minDate = '2018-01-01', maxDate = str(date.today()
335335 diagnosis ['GEO_BENE_SK' ] = claim ['CLM' ]['GEO_BENE_SK' ]
336336 diagnosis ['CLM_TYPE_CD' ] = claim ['CLM' ]['CLM_TYPE_CD' ]
337337 claim ['CLM_PROD' ].append (diagnosis )
338+ add_meta_timestamps (diagnosis , claim ['CLM' ], max_date )
338339
339340 #clm_dt_sgntr info
340341 if (clm_type_cd in (10 ,20 ,30 ,50 ,60 ,61 ,62 ,63 ,64 )):
@@ -397,7 +398,7 @@ def gen_claim(bene_sk = '-1', minDate = '2018-01-01', maxDate = str(date.today()
397398 institutional_parts ['CLM_MDCR_IP_PPS_CPTL_TOT_AMT' ] = round (random .uniform (0 ,25 ),2 )
398399 institutional_parts ['CLM_MDCR_IP_BENE_DDCTBL_AMT' ] = round (random .uniform (0 ,25 ),2 )
399400 institutional_parts ['CLM_PPS_IND_CD' ] = random .choice (['' ,'2' ])
400- add_meta_timestamps (institutional_parts )
401+ add_meta_timestamps (institutional_parts , claim [ 'CLM' ], max_date )
401402
402403 if (clm_type_cd == 10 ):
403404 if (random .choice ([0 ,1 ])):
@@ -459,7 +460,7 @@ def gen_claim(bene_sk = '-1', minDate = '2018-01-01', maxDate = str(date.today()
459460 claim_line ['CLM_LINE_PRVDR_PMT_AMT' ] = round (random .uniform (0 ,1500 ),2 )
460461 claim_line ['CLM_LINE_NCVRD_CHRG_AMT' ] = round (random .uniform (0 ,1500 ),2 )
461462
462- add_meta_timestamps (claim_line )
463+ add_meta_timestamps (claim_line , claim [ 'CLM' ], max_date )
463464
464465 claim_line_inst ['CLM_LINE_INSTNL_ADJSTD_AMT' ] = round (random .uniform (0 ,1500 ),2 )
465466 claim_line_inst ['CLM_LINE_INSTNL_RDCD_AMT' ] = round (random .uniform (0 ,1500 ),2 )
@@ -476,7 +477,7 @@ def gen_claim(bene_sk = '-1', minDate = '2018-01-01', maxDate = str(date.today()
476477 claim_line_inst ['CLM_REV_PMT_MTHD_CD' ] = random .choice (generator .code_systems ['CLM_REV_PMT_MTHD_CD' ])
477478 claim_line_inst ['CLM_REV_CNTR_STUS_CD' ] = random .choice (generator .code_systems ['CLM_REV_CNTR_STUS_CD' ])
478479 claim_line_inst ['CLM_ANSI_SGNTR_SK' ] = random .choice (['8585' ,'1' ,'4365' ,'1508' ,'5555' ,'9204' ,'6857' ,'5816' ,'11978' ])
479- add_meta_timestamps (claim_line_inst )
480+ add_meta_timestamps (claim_line_inst , claim [ 'CLM' ], max_date )
480481
481482 claim_line ['CLM_UNIQ_ID' ] = claim ['CLM' ]['CLM_UNIQ_ID' ]
482483 claim_line ['CLM_LINE_NUM' ] = line
@@ -489,7 +490,7 @@ def gen_claim(bene_sk = '-1', minDate = '2018-01-01', maxDate = str(date.today()
489490
490491
491492
492- def gen_pac_version_of_claim (claim ):
493+ def gen_pac_version_of_claim (claim , max_date ):
493494 #note the fields to delete
494495 '''
495496 Generating a Synthetic PAC claim is done in a rather naive way.
@@ -514,7 +515,7 @@ def gen_pac_version_of_claim(claim):
514515 pac_claim ['CLM_FISS' ]['CLM_NUM_SK' ] = pac_claim ['CLM' ]['CLM_NUM_SK' ]
515516 pac_claim ['CLM_FISS' ]['CLM_TYPE_CD' ] = pac_claim ['CLM' ]['CLM_TYPE_CD' ]
516517 pac_claim ['CLM_FISS' ]['CLM_CRNT_STUS_CD' ] = random .choice (['A' ,'F' ,'I' ,'S' ,'M' ,'P' ,'R' ,'D' ,'T' ,'U' ])
517- add_meta_timestamps (pac_claim ['CLM_FISS' ])
518+ add_meta_timestamps (pac_claim ['CLM_FISS' ], claim [ 'CLM' ], max_date )
518519
519520
520521 for i in range (len (pac_claim ['CLM_LINE' ])):
@@ -588,10 +589,13 @@ def gen_pac_version_of_claim(claim):
588589
589590 return pac_claim
590591
591- def add_meta_timestamps (obj ):
592- has_insrt_ts = random .random () > 0.2
593- obj ['IDR_INSRT_TS' ] = datetime .today () if has_insrt_ts else None
594- obj ['IDR_UPDT_TS' ] = datetime .today () if has_insrt_ts and random .random () > 0.8 else None
592+ def add_meta_timestamps (obj , clm , max_date ):
593+ if date .fromisoformat (clm ['CLM_IDR_LD_DT' ]) < date (2021 , 4 , 19 ):
594+ has_insrt_ts = random .random () > 0.5
595+ else :
596+ has_insrt_ts = True
597+ obj ['IDR_INSRT_TS' ] = faker .date_time_between_dates (datetime .fromisoformat (clm ['CLM_IDR_LD_DT' ]), datetime .fromisoformat (max_date )) if has_insrt_ts else None
598+ obj ['IDR_UPDT_TS' ] = faker .date_time_between_dates (obj ['IDR_INSRT_TS' ], datetime .fromisoformat (max_date )) if has_insrt_ts and random .random () > 0.8 else None
595599
596600'''
597601def pull_code_systems():
@@ -646,12 +650,13 @@ def main():
646650 CLM_DCMTN = []
647651 CLM_FISS = []
648652 pt_complete = 0
653+ max_date = str (date .today ())
649654 for pt_bene_sk in bene_sk_list :
650655 if ((pt_complete )% 1000 == 0 and pt_complete > 0 ):
651656 print (f"Completed { pt_complete } patients with { claims_to_generate_per_person } claims per patient." )
652657 for i in range (claims_to_generate_per_person ):
653658 clm_from_dt_min = '2018-01-01'
654- claim = gen_claim (bene_sk = pt_bene_sk ,minDate = clm_from_dt_min )
659+ claim = gen_claim (bene_sk = pt_bene_sk , min_date = clm_from_dt_min , max_date = max_date )
655660 CLM .append (claim ['CLM' ])
656661 for line in claim ['CLM_LINE' ]:
657662 CLM_LINE .append (line )
@@ -665,7 +670,7 @@ def main():
665670 CLM_LINE_INSTNL .append (line )
666671 CLM_DCMTN .append (claim ['CLM_DCMTN' ])
667672 if (random .choice ([0 ,1 ])):
668- pac_claim = gen_pac_version_of_claim (claim )
673+ pac_claim = gen_pac_version_of_claim (claim , max_date )
669674 CLM .append (pac_claim ['CLM' ])
670675 for line in pac_claim ['CLM_LINE' ]:
671676 CLM_LINE .append (line )
0 commit comments