medicafe 0.250711.0__py3-none-any.whl → 0.250720.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.
- MediBot/MediBot_Crosswalk_Library.py +109 -1
- MediLink/MediLink_837p_cob_library.py +862 -0
- MediLink/MediLink_837p_encoder.py +40 -0
- MediLink/MediLink_837p_encoder_library.py +54 -6
- MediLink/MediLink_API_v3.py +24 -5
- MediLink/MediLink_ClaimStatus.py +4 -3
- MediLink/MediLink_Deductible.py +354 -118
- MediLink/MediLink_Deductible_Validator.py +440 -0
- MediLink/MediLink_GraphQL.py +40 -4
- MediLink/test_cob_library.py +436 -0
- MediLink/test_validation.py +127 -0
- {medicafe-0.250711.0.dist-info → medicafe-0.250720.0.dist-info}/METADATA +1 -1
- {medicafe-0.250711.0.dist-info → medicafe-0.250720.0.dist-info}/RECORD +16 -12
- {medicafe-0.250711.0.dist-info → medicafe-0.250720.0.dist-info}/LICENSE +0 -0
- {medicafe-0.250711.0.dist-info → medicafe-0.250720.0.dist-info}/WHEEL +0 -0
- {medicafe-0.250711.0.dist-info → medicafe-0.250720.0.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import json, sys, os
|
|
1
|
+
import json, sys, os, threading
|
|
2
2
|
|
|
3
3
|
# Set the project directory to the parent directory of the current file
|
|
4
4
|
project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
@@ -269,6 +269,107 @@ def load_and_parse_z_data(config):
|
|
|
269
269
|
MediLink_ConfigLoader.log("Error loading and parsing Z data: {}".format(e), config, level="ERROR")
|
|
270
270
|
return {}
|
|
271
271
|
|
|
272
|
+
def check_crosswalk_health(crosswalk):
|
|
273
|
+
"""
|
|
274
|
+
Simple health check for crosswalk - checks if payers have names and at least one medisoft ID.
|
|
275
|
+
A payer is considered healthy if it has a name (not "Unknown") and at least one medisoft ID,
|
|
276
|
+
which can exist in either 'medisoft_id' OR 'medisoft_medicare_id'. It is NOT required to have both.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
crosswalk (dict): The crosswalk dictionary to check.
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
tuple: (is_healthy, missing_names_count, missing_medisoft_ids_count)
|
|
283
|
+
"""
|
|
284
|
+
if 'payer_id' not in crosswalk or not crosswalk['payer_id']:
|
|
285
|
+
return False, 0, 0
|
|
286
|
+
|
|
287
|
+
missing_names = 0
|
|
288
|
+
missing_medisoft_ids = 0
|
|
289
|
+
|
|
290
|
+
for payer_id, details in crosswalk['payer_id'].items():
|
|
291
|
+
# Check if name is missing or "Unknown"
|
|
292
|
+
name = details.get('name', '')
|
|
293
|
+
if not name or name == 'Unknown':
|
|
294
|
+
missing_names += 1
|
|
295
|
+
|
|
296
|
+
# Check if at least one medisoft ID exists in either field
|
|
297
|
+
medisoft_id = details.get('medisoft_id', [])
|
|
298
|
+
medisoft_medicare_id = details.get('medisoft_medicare_id', [])
|
|
299
|
+
|
|
300
|
+
# Convert to list if it's a set (for compatibility)
|
|
301
|
+
if isinstance(medisoft_id, set):
|
|
302
|
+
medisoft_id = list(medisoft_id)
|
|
303
|
+
if isinstance(medisoft_medicare_id, set):
|
|
304
|
+
medisoft_medicare_id = list(medisoft_medicare_id)
|
|
305
|
+
|
|
306
|
+
# If both are empty, count as missing; if either has at least one, it's healthy
|
|
307
|
+
if not medisoft_id and not medisoft_medicare_id:
|
|
308
|
+
missing_medisoft_ids += 1
|
|
309
|
+
|
|
310
|
+
# Consider healthy if no missing names and no missing medisoft IDs
|
|
311
|
+
is_healthy = (missing_names == 0 and missing_medisoft_ids == 0)
|
|
312
|
+
return is_healthy, missing_names, missing_medisoft_ids
|
|
313
|
+
|
|
314
|
+
def prompt_user_for_api_calls(crosswalk, config):
|
|
315
|
+
"""
|
|
316
|
+
Prompts user with a 3-second timeout to skip API calls if crosswalk looks healthy.
|
|
317
|
+
Windows XP compatible version using threading instead of select.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
crosswalk (dict): The crosswalk dictionary to check.
|
|
321
|
+
config (dict): Configuration settings for logging.
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
bool: True if should proceed with API calls, False if should skip
|
|
325
|
+
"""
|
|
326
|
+
|
|
327
|
+
is_healthy, missing_names, missing_medisoft_ids = check_crosswalk_health(crosswalk)
|
|
328
|
+
total_payers = len(crosswalk.get('payer_id', {}))
|
|
329
|
+
|
|
330
|
+
if is_healthy:
|
|
331
|
+
print("\nCrosswalk appears healthy:")
|
|
332
|
+
print(" - {} payers found".format(total_payers))
|
|
333
|
+
print(" - All payers have names")
|
|
334
|
+
print(" - All payers have medisoft IDs")
|
|
335
|
+
print("\nPress ENTER to run API validation, or wait 3 seconds to skip...")
|
|
336
|
+
|
|
337
|
+
# Use threading for timeout on Windows
|
|
338
|
+
user_input = [None] # Use list to store result from thread
|
|
339
|
+
|
|
340
|
+
def get_input():
|
|
341
|
+
try:
|
|
342
|
+
user_input[0] = input()
|
|
343
|
+
except (EOFError, KeyboardInterrupt):
|
|
344
|
+
user_input[0] = ""
|
|
345
|
+
|
|
346
|
+
# Start input thread
|
|
347
|
+
input_thread = threading.Thread(target=get_input)
|
|
348
|
+
input_thread.daemon = True
|
|
349
|
+
input_thread.start()
|
|
350
|
+
|
|
351
|
+
# Wait for 3 seconds or until input is received
|
|
352
|
+
input_thread.join(timeout=3.0)
|
|
353
|
+
|
|
354
|
+
if user_input[0] is not None:
|
|
355
|
+
print("Running API validation calls...")
|
|
356
|
+
MediLink_ConfigLoader.log("User pressed ENTER - proceeding with API calls", config, level="INFO")
|
|
357
|
+
return True
|
|
358
|
+
else:
|
|
359
|
+
print("Timed out - skipping API calls")
|
|
360
|
+
MediLink_ConfigLoader.log("Timeout - skipping API calls", config, level="INFO")
|
|
361
|
+
return False
|
|
362
|
+
else:
|
|
363
|
+
print("\nCrosswalk needs attention:")
|
|
364
|
+
print(" - {} payers found".format(total_payers))
|
|
365
|
+
if missing_names > 0:
|
|
366
|
+
print(" - {} payers missing names".format(missing_names))
|
|
367
|
+
if missing_medisoft_ids > 0:
|
|
368
|
+
print(" - {} payers missing medisoft IDs".format(missing_medisoft_ids))
|
|
369
|
+
print("Proceeding with API validation calls...")
|
|
370
|
+
MediLink_ConfigLoader.log("Crosswalk unhealthy - proceeding with API calls", config, level="INFO")
|
|
371
|
+
return True
|
|
372
|
+
|
|
272
373
|
def crosswalk_update(client, config, crosswalk, skip_known_payers=True): # Upstream of this is only MediBot_Preprocessor.py and MediBot.py
|
|
273
374
|
"""
|
|
274
375
|
Updates the crosswalk with insurance data and historical mappings.
|
|
@@ -326,6 +427,13 @@ def crosswalk_update(client, config, crosswalk, skip_known_payers=True): # Upstr
|
|
|
326
427
|
MediLink_ConfigLoader.log("User opted not to initialize the crosswalk.", config, level="WARNING")
|
|
327
428
|
return False # Indicate that the update was not completed
|
|
328
429
|
|
|
430
|
+
# NEW: Check if we should skip API calls based on crosswalk health
|
|
431
|
+
if not prompt_user_for_api_calls(crosswalk, config):
|
|
432
|
+
print("Skipping crosswalk API validation - using existing data")
|
|
433
|
+
MediLink_ConfigLoader.log("Skipped crosswalk API validation per user choice", config, level="INFO")
|
|
434
|
+
return True
|
|
435
|
+
|
|
436
|
+
# Continue with existing crosswalk update logic...
|
|
329
437
|
# Update the crosswalk with new payer IDs and insurance IDs
|
|
330
438
|
for patient_id, payer_id in patient_id_to_payer_id.items():
|
|
331
439
|
""" TODO this needs to be implemented at some point so we can skip known entities.
|