medicafe 0.250708.0__py3-none-any.whl → 0.250711.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of medicafe might be problematic. Click here for more details.
- MediLink/MediLink_API_v3.py +1 -0
- MediLink/MediLink_Deductible.py +179 -30
- {medicafe-0.250708.0.dist-info → medicafe-0.250711.0.dist-info}/METADATA +1 -1
- {medicafe-0.250708.0.dist-info → medicafe-0.250711.0.dist-info}/RECORD +7 -7
- {medicafe-0.250708.0.dist-info → medicafe-0.250711.0.dist-info}/LICENSE +0 -0
- {medicafe-0.250708.0.dist-info → medicafe-0.250711.0.dist-info}/WHEEL +0 -0
- {medicafe-0.250708.0.dist-info → medicafe-0.250711.0.dist-info}/top_level.txt +0 -0
MediLink/MediLink_API_v3.py
CHANGED
|
@@ -73,6 +73,7 @@ class TokenCache:
|
|
|
73
73
|
return token_info['access_token']
|
|
74
74
|
|
|
75
75
|
# Log cache miss
|
|
76
|
+
# BUG In the future, check the token refresh flow here to make sure we're not picking up unnecessary tokens.
|
|
76
77
|
log_message = "No valid token found for {}".format(endpoint_name)
|
|
77
78
|
MediLink_ConfigLoader.log(log_message, level="INFO")
|
|
78
79
|
|
MediLink/MediLink_Deductible.py
CHANGED
|
@@ -212,47 +212,196 @@ def get_eligibility_info(client, payer_id, provider_last_name, date_of_birth, me
|
|
|
212
212
|
MediLink_ConfigLoader.log("Error: {}".format(e), level="ERROR")
|
|
213
213
|
return None
|
|
214
214
|
|
|
215
|
-
#
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
215
|
+
# Helper functions to extract data from different API response formats
|
|
216
|
+
# BUG the API response is coming through correctly but the parsers below are not correctly extracting the super_connector variables.
|
|
217
|
+
|
|
218
|
+
def extract_legacy_patient_info(policy):
|
|
219
|
+
"""Extract patient information from legacy API response format"""
|
|
220
|
+
patient_info = policy.get("patientInfo", [{}])[0]
|
|
221
|
+
return {
|
|
222
|
+
'lastName': patient_info.get("lastName", ""),
|
|
223
|
+
'firstName': patient_info.get("firstName", ""),
|
|
224
|
+
'middleName': patient_info.get("middleName", "")
|
|
225
|
+
}
|
|
219
226
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
227
|
+
def extract_super_connector_patient_info(eligibility_data):
|
|
228
|
+
"""Extract patient information from Super Connector API response format"""
|
|
229
|
+
if not eligibility_data:
|
|
230
|
+
return {'lastName': '', 'firstName': '', 'middleName': ''}
|
|
231
|
+
|
|
232
|
+
# The response structure is flat at the top level
|
|
233
|
+
return {
|
|
234
|
+
'lastName': eligibility_data.get("lastName", ""),
|
|
235
|
+
'firstName': eligibility_data.get("firstName", ""),
|
|
236
|
+
'middleName': eligibility_data.get("middleName", "")
|
|
237
|
+
}
|
|
224
238
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
deductible_info
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
239
|
+
def extract_legacy_remaining_amount(policy):
|
|
240
|
+
"""Extract remaining amount from legacy API response format"""
|
|
241
|
+
deductible_info = policy.get("deductibleInfo", {})
|
|
242
|
+
if 'individual' in deductible_info:
|
|
243
|
+
return deductible_info['individual']['inNetwork'].get("remainingAmount", "")
|
|
244
|
+
elif 'family' in deductible_info:
|
|
245
|
+
return deductible_info['family']['inNetwork'].get("remainingAmount", "")
|
|
246
|
+
else:
|
|
247
|
+
return ""
|
|
248
|
+
|
|
249
|
+
def extract_super_connector_remaining_amount(eligibility_data):
|
|
250
|
+
"""Extract remaining amount from Super Connector API response format"""
|
|
251
|
+
if not eligibility_data:
|
|
252
|
+
return ""
|
|
253
|
+
|
|
254
|
+
# First, check top-level metYearToDateAmount which might indicate deductible met
|
|
255
|
+
met_amount = eligibility_data.get('metYearToDateAmount')
|
|
256
|
+
if met_amount is not None:
|
|
257
|
+
return str(met_amount)
|
|
258
|
+
|
|
259
|
+
# Navigate to the rawGraphQLResponse structure
|
|
260
|
+
raw_response = eligibility_data.get('rawGraphQLResponse', {})
|
|
261
|
+
if not raw_response:
|
|
262
|
+
return ""
|
|
263
|
+
|
|
264
|
+
data = raw_response.get('data', {})
|
|
265
|
+
check_eligibility = data.get('checkEligibility', {})
|
|
266
|
+
eligibility_list = check_eligibility.get('eligibility', [])
|
|
267
|
+
|
|
268
|
+
if not eligibility_list:
|
|
269
|
+
return ""
|
|
270
|
+
|
|
271
|
+
first_eligibility = eligibility_list[0]
|
|
272
|
+
service_levels = first_eligibility.get('serviceLevels', [])
|
|
273
|
+
|
|
274
|
+
# Look for deductible information in service levels
|
|
275
|
+
for service_level in service_levels:
|
|
276
|
+
individual_services = service_level.get('individual', [])
|
|
277
|
+
for individual in individual_services:
|
|
278
|
+
services = individual.get('services', [])
|
|
279
|
+
for service in services:
|
|
280
|
+
# Look for deductible-related information
|
|
281
|
+
if service.get('service') == 'deductible' or 'deductible' in service.get('text', '').lower():
|
|
282
|
+
return service.get('remainingAmount', "")
|
|
283
|
+
|
|
284
|
+
# Check the message.deductible.text field for deductible information
|
|
285
|
+
message = service.get('message', {})
|
|
286
|
+
deductible_msg = message.get('deductible', {})
|
|
287
|
+
if deductible_msg and deductible_msg.get('text'):
|
|
288
|
+
return deductible_msg.get('text', "")
|
|
289
|
+
|
|
290
|
+
# If no specific deductible found, try to get from plan levels
|
|
291
|
+
plan_levels = first_eligibility.get('eligibilityInfo', {}).get('planLevels', [])
|
|
292
|
+
for plan_level in plan_levels:
|
|
293
|
+
if plan_level.get('level') == 'deductibleInfo/outOfPocket/coPayMax':
|
|
294
|
+
individual_levels = plan_level.get('individual', [])
|
|
295
|
+
if individual_levels:
|
|
296
|
+
return individual_levels[0].get('remainingAmount', "")
|
|
297
|
+
|
|
298
|
+
return ""
|
|
299
|
+
|
|
300
|
+
def extract_legacy_insurance_info(policy):
|
|
301
|
+
"""Extract insurance information from legacy API response format"""
|
|
302
|
+
insurance_info = policy.get("insuranceInfo", {})
|
|
303
|
+
return {
|
|
304
|
+
'insuranceType': insurance_info.get("insuranceType", ""),
|
|
305
|
+
'insuranceTypeCode': insurance_info.get("insuranceTypeCode", ""),
|
|
306
|
+
'memberId': insurance_info.get("memberId", ""),
|
|
307
|
+
'payerId': insurance_info.get("payerId", "")
|
|
308
|
+
}
|
|
238
309
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
310
|
+
def extract_super_connector_insurance_info(eligibility_data):
|
|
311
|
+
"""Extract insurance information from Super Connector API response format"""
|
|
312
|
+
if not eligibility_data:
|
|
313
|
+
return {'insuranceType': '', 'insuranceTypeCode': '', 'memberId': '', 'payerId': ''}
|
|
314
|
+
|
|
315
|
+
# Get coverage type from coverageTypes array at the top level
|
|
316
|
+
coverage_types = eligibility_data.get('coverageTypes', [])
|
|
317
|
+
insurance_type = ""
|
|
318
|
+
if coverage_types:
|
|
319
|
+
insurance_type = coverage_types[0].get('description', '')
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
'insuranceType': insurance_type,
|
|
323
|
+
'insuranceTypeCode': eligibility_data.get("productServiceCode", ""),
|
|
324
|
+
'memberId': eligibility_data.get("subscriberId", ""),
|
|
325
|
+
'payerId': eligibility_data.get("legalEntityCode", "")
|
|
326
|
+
}
|
|
244
327
|
|
|
245
|
-
|
|
246
|
-
|
|
328
|
+
def extract_legacy_policy_status(policy):
|
|
329
|
+
"""Extract policy status from legacy API response format"""
|
|
330
|
+
policy_info = policy.get("policyInfo", {})
|
|
331
|
+
return policy_info.get("policyStatus", "")
|
|
247
332
|
|
|
248
|
-
|
|
333
|
+
def extract_super_connector_policy_status(eligibility_data):
|
|
334
|
+
"""Extract policy status from Super Connector API response format"""
|
|
335
|
+
if not eligibility_data:
|
|
336
|
+
return ""
|
|
337
|
+
|
|
338
|
+
# Policy status is at the top level
|
|
339
|
+
return eligibility_data.get("policyStatus", "")
|
|
340
|
+
|
|
341
|
+
def is_legacy_response_format(data):
|
|
342
|
+
"""Determine if the response is in legacy format (has memberPolicies)"""
|
|
343
|
+
return data is not None and "memberPolicies" in data
|
|
344
|
+
|
|
345
|
+
def is_super_connector_response_format(data):
|
|
346
|
+
"""Determine if the response is in Super Connector format (has rawGraphQLResponse)"""
|
|
347
|
+
return data is not None and "rawGraphQLResponse" in data
|
|
348
|
+
|
|
349
|
+
# Function to extract required fields and display in a tabular format
|
|
350
|
+
def display_eligibility_info(data, dob, member_id, output_file):
|
|
351
|
+
if data is None:
|
|
352
|
+
return
|
|
353
|
+
|
|
354
|
+
# Determine which API response format we're dealing with
|
|
355
|
+
if is_legacy_response_format(data):
|
|
356
|
+
# Handle legacy API response format
|
|
357
|
+
for policy in data.get("memberPolicies", []):
|
|
358
|
+
# Skip non-medical policies
|
|
359
|
+
if policy.get("policyInfo", {}).get("coverageType", "") != "Medical":
|
|
360
|
+
continue
|
|
361
|
+
|
|
362
|
+
patient_info = extract_legacy_patient_info(policy)
|
|
363
|
+
remaining_amount = extract_legacy_remaining_amount(policy)
|
|
364
|
+
insurance_info = extract_legacy_insurance_info(policy)
|
|
365
|
+
policy_status = extract_legacy_policy_status(policy)
|
|
366
|
+
|
|
367
|
+
patient_name = "{} {} {}".format(
|
|
368
|
+
patient_info['firstName'],
|
|
369
|
+
patient_info['middleName'],
|
|
370
|
+
patient_info['lastName']
|
|
371
|
+
).strip()[:20]
|
|
372
|
+
|
|
373
|
+
# Display patient information in a table row format
|
|
374
|
+
table_row = "{:<20} | {:<10} | {:<40} | {:<5} | {:<14} | {:<14}".format(
|
|
375
|
+
patient_name, dob, insurance_info['insuranceType'],
|
|
376
|
+
insurance_info['payerId'], policy_status, remaining_amount)
|
|
377
|
+
output_file.write(table_row + "\n")
|
|
378
|
+
print(table_row) # Print to console for progressive display
|
|
379
|
+
|
|
380
|
+
elif is_super_connector_response_format(data):
|
|
381
|
+
# Handle Super Connector API response format
|
|
382
|
+
patient_info = extract_super_connector_patient_info(data)
|
|
383
|
+
remaining_amount = extract_super_connector_remaining_amount(data)
|
|
384
|
+
insurance_info = extract_super_connector_insurance_info(data)
|
|
385
|
+
policy_status = extract_super_connector_policy_status(data)
|
|
386
|
+
|
|
387
|
+
patient_name = "{} {} {}".format(
|
|
388
|
+
patient_info['firstName'],
|
|
389
|
+
patient_info['middleName'],
|
|
390
|
+
patient_info['lastName']
|
|
391
|
+
).strip()[:20]
|
|
249
392
|
|
|
250
393
|
# Display patient information in a table row format
|
|
251
394
|
table_row = "{:<20} | {:<10} | {:<40} | {:<5} | {:<14} | {:<14}".format(
|
|
252
|
-
patient_name, dob,
|
|
395
|
+
patient_name, dob, insurance_info['insuranceType'],
|
|
396
|
+
insurance_info['payerId'], policy_status, remaining_amount)
|
|
253
397
|
output_file.write(table_row + "\n")
|
|
254
398
|
print(table_row) # Print to console for progressive display
|
|
255
399
|
|
|
400
|
+
else:
|
|
401
|
+
# Unknown response format - log for debugging
|
|
402
|
+
MediLink_ConfigLoader.log("Unknown response format in display_eligibility_info", level="WARNING")
|
|
403
|
+
MediLink_ConfigLoader.log("Response structure: {}".format(json.dumps(data, indent=2)), level="DEBUG")
|
|
404
|
+
|
|
256
405
|
# Main Execution Flow
|
|
257
406
|
if __name__ == "__main__":
|
|
258
407
|
# Step 1: Handle Manual Deductible Lookups
|
|
@@ -19,14 +19,14 @@ MediLink/MediLink_837p_encoder.py,sha256=id2qhKUYq_raKcDr5pAY1xF0V_UR5KBC8SXDAeh
|
|
|
19
19
|
MediLink/MediLink_837p_encoder_library.py,sha256=rxame7v_LcNJe8Wdt3INQkTC5MdIbZq9ySsR90OL6Lo,49924
|
|
20
20
|
MediLink/MediLink_API_Generator.py,sha256=vBZ8moR9tvv7mb200HlZnJrk1y-bQi8E16I2r41vgVM,10345
|
|
21
21
|
MediLink/MediLink_API_v2.py,sha256=mcIgLnXPS_NaUBrkKJ8mxCUaQ0AuQUeU1vG6DoplbVY,7733
|
|
22
|
-
MediLink/MediLink_API_v3.py,sha256=
|
|
22
|
+
MediLink/MediLink_API_v3.py,sha256=VdVDvFyl4pgURqvxLxw3aJqGQiWV5NLOsM7FkNAWKVo,39735
|
|
23
23
|
MediLink/MediLink_APIs.py,sha256=jm3f9T034MJKH8A_CIootULoeuk7H8s7PazpFZRCbKI,6222
|
|
24
24
|
MediLink/MediLink_Azure.py,sha256=Ow70jctiHFIylskBExN7WUoRgrKOvBR6jNTnQMk6lJA,210
|
|
25
25
|
MediLink/MediLink_ClaimStatus.py,sha256=GNZ9mRrjxemBHJ5LiJb2DUWhKgWX2vTNY5jxoUgqv-I,9776
|
|
26
26
|
MediLink/MediLink_ConfigLoader.py,sha256=u9ecB0SIN7zuJAo8KcoQys95BtyAo-8S2n4mRd0S3XU,4356
|
|
27
27
|
MediLink/MediLink_DataMgmt.py,sha256=jrTAPSNVzs1wwYl1g0_8Mda3k2B27CbaSw8Pu2qmThw,33058
|
|
28
28
|
MediLink/MediLink_Decoder.py,sha256=Suw9CmUHgoe0ZW8sJP_pIO8URBrhO5FmxFF8RcUj9lI,13318
|
|
29
|
-
MediLink/MediLink_Deductible.py,sha256=
|
|
29
|
+
MediLink/MediLink_Deductible.py,sha256=rkSaS9n20EWs7KhHYOpv-_gehBPvrC-TdI5NYJ7TM54,20864
|
|
30
30
|
MediLink/MediLink_Down.py,sha256=hrDODhs-zRfOKCdiRGENN5Czu-AvdtwJj4Q7grcRXME,6518
|
|
31
31
|
MediLink/MediLink_ERA_decoder.py,sha256=MiOtDcXnmevPfHAahIlTLlUc14VcQWAor9Xa7clA2Ts,8710
|
|
32
32
|
MediLink/MediLink_Gmail.py,sha256=OYsASNgP4YSTaSnj9XZxPPiy0cw41JC-suLIgRyNrlQ,31439
|
|
@@ -44,8 +44,8 @@ MediLink/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
44
44
|
MediLink/openssl.cnf,sha256=76VdcGCykf0Typyiv8Wd1mMVKixrQ5RraG6HnfKFqTo,887
|
|
45
45
|
MediLink/test.py,sha256=kSvvJRL_3fWuNS3_x4hToOnUljGLoeEw6SUTHQWQRJk,3108
|
|
46
46
|
MediLink/webapp.html,sha256=JPKT559aFVBi1r42Hz7C77Jj0teZZRumPhBev8eSOLk,19806
|
|
47
|
-
medicafe-0.
|
|
48
|
-
medicafe-0.
|
|
49
|
-
medicafe-0.
|
|
50
|
-
medicafe-0.
|
|
51
|
-
medicafe-0.
|
|
47
|
+
medicafe-0.250711.0.dist-info/LICENSE,sha256=65lb-vVujdQK7uMH3RRJSMwUW-WMrMEsc5sOaUn2xUk,1096
|
|
48
|
+
medicafe-0.250711.0.dist-info/METADATA,sha256=Z-zv1ZzWjxnTHDcXiZevjMfpjQqqkn9x2xJFMZwcvNg,5501
|
|
49
|
+
medicafe-0.250711.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
50
|
+
medicafe-0.250711.0.dist-info/top_level.txt,sha256=3uOwR4q_SP8Gufk2uCHoKngAgbtdOwQC6Qjl7ViBa_c,17
|
|
51
|
+
medicafe-0.250711.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|