medicafe 0.251015.0__tar.gz → 0.251016.0__tar.gz
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.
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/__init__.py +1 -1
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/__init__.py +1 -1
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Deductible.py +89 -13
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/__init__.py +1 -1
- {medicafe-0.251015.0/medicafe.egg-info → medicafe-0.251016.0}/PKG-INFO +1 -1
- {medicafe-0.251015.0 → medicafe-0.251016.0/medicafe.egg-info}/PKG-INFO +1 -1
- {medicafe-0.251015.0 → medicafe-0.251016.0}/setup.py +1 -1
- {medicafe-0.251015.0 → medicafe-0.251016.0}/LICENSE +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MANIFEST.in +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot.bat +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_Charges.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_Crosswalk_Library.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_Crosswalk_Utils.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_Notepad_Utils.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_Post.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_Preprocessor.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_Preprocessor_lib.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_UI.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_dataformat_library.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_debug.bat +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_docx_decoder.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/MediBot_smart_import.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/clear_cache.bat +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/crash_diagnostic.bat +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/f_drive_diagnostic.bat +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/full_debug_suite.bat +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/get_medicafe_version.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/process_csvs.bat +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/update_json.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediBot/update_medicafe.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/MediLink_ConfigLoader.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/__main__.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/api_core.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/api_factory.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/api_utils.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/core_utils.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/deductible_utils.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/error_reporter.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/graphql_utils.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/logging_config.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/logging_demo.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/migration_helpers.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/smart_import.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediCafe/submission_index.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/InsuranceTypeService.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_837p_cob_library.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_837p_encoder.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_837p_encoder_library.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_837p_utilities.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_API_Generator.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Azure.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Charges.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_ClaimStatus.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_DataMgmt.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Decoder.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Deductible_Validator.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Display_Utils.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Down.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Gmail.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Mailer.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Parser.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_PatientProcessor.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Scan.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Scheduler.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_UI.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_Up.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_insurance_utils.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_main.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/MediLink_smart_import.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/Soumit_api.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/gmail_http_utils.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/gmail_oauth_utils.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/openssl.cnf +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/test.py +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/MediLink/webapp.html +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/README.md +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/medicafe.egg-info/SOURCES.txt +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/medicafe.egg-info/dependency_links.txt +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/medicafe.egg-info/entry_points.txt +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/medicafe.egg-info/not-zip-safe +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/medicafe.egg-info/requires.txt +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/medicafe.egg-info/top_level.txt +0 -0
- {medicafe-0.251015.0 → medicafe-0.251016.0}/setup.cfg +0 -0
|
@@ -375,12 +375,16 @@ def manual_deductible_lookup():
|
|
|
375
375
|
|
|
376
376
|
# Fetch eligibility data
|
|
377
377
|
found_data = False
|
|
378
|
+
printed_messages = set()
|
|
378
379
|
for i, payer_id in enumerate(payer_ids, 1):
|
|
379
380
|
print("Checking Payer ID {} ({}/{}): {}".format(payer_id, i, len(payer_ids), payer_id))
|
|
380
381
|
|
|
381
382
|
# Use the current mode setting for validation
|
|
382
383
|
run_validation = DEBUG_MODE
|
|
383
|
-
eligibility_data = get_eligibility_info(
|
|
384
|
+
eligibility_data = get_eligibility_info(
|
|
385
|
+
client, payer_id, provider_last_name, formatted_dob, member_id, npi,
|
|
386
|
+
run_validation=run_validation, is_manual_lookup=True, printed_messages=printed_messages
|
|
387
|
+
)
|
|
384
388
|
if eligibility_data:
|
|
385
389
|
found_data = True
|
|
386
390
|
|
|
@@ -484,13 +488,28 @@ def manual_deductible_lookup():
|
|
|
484
488
|
enhanced_result['policy_status'][:14],
|
|
485
489
|
enhanced_result['remaining_amount'][:14])
|
|
486
490
|
output_file.write(table_row + "\n")
|
|
491
|
+
|
|
492
|
+
# Persist per-row error diagnostics in a user-friendly way
|
|
493
|
+
try:
|
|
494
|
+
row_reason = _compute_error_reason(enhanced_result)
|
|
495
|
+
row_messages = enhanced_result.get('error_messages', []) or []
|
|
496
|
+
if row_reason or row_messages:
|
|
497
|
+
output_file.write(" >> Errors:" + "\n")
|
|
498
|
+
if row_reason:
|
|
499
|
+
output_file.write(" >> - {}\n".format(row_reason))
|
|
500
|
+
for msg in row_messages:
|
|
501
|
+
# Avoid duplicating the reason message if identical
|
|
502
|
+
if not row_reason or msg.strip() != row_reason.strip():
|
|
503
|
+
output_file.write(" >> - {}\n".format(str(msg)))
|
|
504
|
+
except Exception:
|
|
505
|
+
pass
|
|
487
506
|
else:
|
|
488
507
|
display_eligibility_info(eligibility_data, formatted_dob, member_id, output_file)
|
|
489
508
|
|
|
490
509
|
# Ask if user wants to open the report
|
|
491
510
|
open_report = input("\nEligibility data found! Open the report? (Y/N): ").strip().lower()
|
|
492
511
|
if open_report in ['y', 'yes']:
|
|
493
|
-
os.
|
|
512
|
+
os.startfile(output_file_path)
|
|
494
513
|
print("Manual eligibility report generated: {}\n".format(output_file_path))
|
|
495
514
|
break # Assuming one payer ID per manual lookup
|
|
496
515
|
else:
|
|
@@ -523,6 +542,8 @@ def get_eligibility_info(client, payer_id, provider_last_name, date_of_birth, me
|
|
|
523
542
|
if run_validation:
|
|
524
543
|
# Debug mode: Call both APIs and run validation
|
|
525
544
|
MediLink_ConfigLoader.log("Running in DEBUG MODE - calling both APIs", level="INFO")
|
|
545
|
+
# Always initialize row-level error messages for diagnostics
|
|
546
|
+
error_messages_for_row = []
|
|
526
547
|
|
|
527
548
|
# Get legacy response
|
|
528
549
|
MediLink_ConfigLoader.log("Getting legacy get_eligibility_v3 API response", level="INFO")
|
|
@@ -596,6 +617,11 @@ def get_eligibility_info(client, payer_id, provider_last_name, date_of_birth, me
|
|
|
596
617
|
if detail_msg not in printed_messages:
|
|
597
618
|
print(detail_msg)
|
|
598
619
|
printed_messages.add(detail_msg)
|
|
620
|
+
# Accumulate per-row messages for persistence in reports
|
|
621
|
+
try:
|
|
622
|
+
error_messages_for_row.append("{} - {}".format(error_code, error_desc))
|
|
623
|
+
except Exception:
|
|
624
|
+
pass
|
|
599
625
|
|
|
600
626
|
# Check for data in error extensions (some APIs return data here)
|
|
601
627
|
extensions = error.get('extensions', {})
|
|
@@ -607,20 +633,25 @@ def get_eligibility_info(client, payer_id, provider_last_name, date_of_birth, me
|
|
|
607
633
|
if details:
|
|
608
634
|
first_detail = details[0]
|
|
609
635
|
print(" First detail: {}".format(first_detail))
|
|
636
|
+
# Persist a brief extension note without dumping raw objects
|
|
637
|
+
try:
|
|
638
|
+
error_messages_for_row.append("Extensions include {} detail record(s)".format(len(details)))
|
|
639
|
+
except Exception:
|
|
640
|
+
pass
|
|
610
641
|
|
|
611
642
|
# Check status code
|
|
612
643
|
if super_connector_eligibility:
|
|
613
644
|
status_code = super_connector_eligibility.get('statuscode')
|
|
614
|
-
if status_code and status_code != '200':
|
|
645
|
+
if status_code is not None and str(status_code).strip() != '200':
|
|
615
646
|
print("Super Connector API status code: {} (non-200 indicates errors)".format(status_code))
|
|
647
|
+
# Record status code for the row diagnostics
|
|
648
|
+
error_messages_for_row.append("Status code {} from Super Connector".format(status_code))
|
|
616
649
|
|
|
617
650
|
# Open validation report in Notepad (only for manual lookups, not batch processing)
|
|
618
651
|
if validation_file_path and os.path.exists(validation_file_path):
|
|
619
652
|
# Only open in manual mode - batch processing will handle this separately
|
|
620
653
|
if is_manual_lookup: # Check if we're in manual lookup mode
|
|
621
|
-
|
|
622
|
-
if ret != 0:
|
|
623
|
-
print("Failed to open Notepad (exit code: {}). Please open manually: {}".format(ret, validation_file_path))
|
|
654
|
+
os.startfile(validation_file_path)
|
|
624
655
|
elif validation_file_path:
|
|
625
656
|
print("\nValidation report file was not created: {}".format(validation_file_path))
|
|
626
657
|
except Exception as e:
|
|
@@ -628,7 +659,17 @@ def get_eligibility_info(client, payer_id, provider_last_name, date_of_birth, me
|
|
|
628
659
|
|
|
629
660
|
# After validation, merge responses
|
|
630
661
|
try:
|
|
631
|
-
|
|
662
|
+
if merge_responses is not None:
|
|
663
|
+
merged_data = merge_responses(super_connector_eligibility, legacy_eligibility, date_of_birth, member_id)
|
|
664
|
+
else:
|
|
665
|
+
MediLink_ConfigLoader.log("merge_responses utility not available; returning raw API response", level="WARNING")
|
|
666
|
+
merged_data = super_connector_eligibility or legacy_eligibility or {}
|
|
667
|
+
# Attach accumulated row-level messages for downstream display/persistence
|
|
668
|
+
try:
|
|
669
|
+
if isinstance(merged_data, dict) and error_messages_for_row:
|
|
670
|
+
merged_data['error_messages'] = error_messages_for_row
|
|
671
|
+
except Exception:
|
|
672
|
+
pass
|
|
632
673
|
return merged_data
|
|
633
674
|
except Exception as e:
|
|
634
675
|
MediLink_ConfigLoader.log("Error in merge_responses: {}".format(e), level="ERROR")
|
|
@@ -713,8 +754,10 @@ def display_eligibility_info(data, dob, member_id, output_file, patient_id="", s
|
|
|
713
754
|
if data is None:
|
|
714
755
|
return
|
|
715
756
|
|
|
716
|
-
# Convert to enhanced format
|
|
717
|
-
enhanced_data =
|
|
757
|
+
# Convert to enhanced format (guard if utility missing)
|
|
758
|
+
enhanced_data = None
|
|
759
|
+
if convert_eligibility_to_enhanced_format is not None:
|
|
760
|
+
enhanced_data = convert_eligibility_to_enhanced_format(data, dob, member_id, patient_id, service_date)
|
|
718
761
|
if enhanced_data:
|
|
719
762
|
# Write to output file in legacy format for compatibility
|
|
720
763
|
table_row = "{:<20} | {:<10} | {:<40} | {:<5} | {:<14} | {:<14}".format(
|
|
@@ -727,6 +770,27 @@ def display_eligibility_info(data, dob, member_id, output_file, patient_id="", s
|
|
|
727
770
|
output_file.write(table_row + "\n")
|
|
728
771
|
print(table_row) # Print to console for progressive display
|
|
729
772
|
|
|
773
|
+
# Helper to compute a user-friendly error explanation for a result row
|
|
774
|
+
def _compute_error_reason(record):
|
|
775
|
+
try:
|
|
776
|
+
if not isinstance(record, dict):
|
|
777
|
+
return ""
|
|
778
|
+
reason = str(record.get('error_reason', '')).strip()
|
|
779
|
+
name_unknown = (not str(record.get('patient_name', '')).strip()) or (record.get('patient_name') == 'Unknown Patient')
|
|
780
|
+
has_error = (str(record.get('status', '')) == 'Error') or (str(record.get('data_source', '')) in ['None', 'Error'])
|
|
781
|
+
amount_missing = (str(record.get('remaining_amount', '')) == 'Not Found')
|
|
782
|
+
|
|
783
|
+
if not reason:
|
|
784
|
+
if name_unknown:
|
|
785
|
+
reason = 'Patient name could not be determined from API responses or CSV backfill'
|
|
786
|
+
elif amount_missing:
|
|
787
|
+
reason = 'Deductible remaining amount not found in eligibility response'
|
|
788
|
+
elif has_error:
|
|
789
|
+
reason = 'Eligibility lookup encountered an error; see logs for details'
|
|
790
|
+
return reason
|
|
791
|
+
except Exception:
|
|
792
|
+
return ""
|
|
793
|
+
|
|
730
794
|
# Global mode flags (will be set in main)
|
|
731
795
|
LEGACY_MODE = False
|
|
732
796
|
DEBUG_MODE = False
|
|
@@ -1042,6 +1106,20 @@ if __name__ == "__main__":
|
|
|
1042
1106
|
result['remaining_amount'][:14])
|
|
1043
1107
|
output_file.write(table_row + "\n")
|
|
1044
1108
|
|
|
1109
|
+
# Persist per-row error diagnostics in a user-friendly way
|
|
1110
|
+
try:
|
|
1111
|
+
row_reason = _compute_error_reason(result)
|
|
1112
|
+
row_messages = result.get('error_messages', []) or []
|
|
1113
|
+
if row_reason or row_messages:
|
|
1114
|
+
output_file.write(" >> Errors:" + "\n")
|
|
1115
|
+
if row_reason:
|
|
1116
|
+
output_file.write(" >> - {}\n".format(row_reason))
|
|
1117
|
+
for msg in row_messages:
|
|
1118
|
+
if not row_reason or msg.strip() != row_reason.strip():
|
|
1119
|
+
output_file.write(" >> - {}\n".format(str(msg)))
|
|
1120
|
+
except Exception:
|
|
1121
|
+
pass
|
|
1122
|
+
|
|
1045
1123
|
# Write enhanced error summary to file
|
|
1046
1124
|
if errors:
|
|
1047
1125
|
error_msg = "\nErrors encountered during API calls:\n"
|
|
@@ -1053,7 +1131,7 @@ if __name__ == "__main__":
|
|
|
1053
1131
|
# Ask if user wants to open the report
|
|
1054
1132
|
open_report = input("\nBatch processing complete! Open the eligibility report? (Y/N): ").strip().lower()
|
|
1055
1133
|
if open_report in ['y', 'yes']:
|
|
1056
|
-
os.
|
|
1134
|
+
os.startfile(output_file_path)
|
|
1057
1135
|
|
|
1058
1136
|
# Print summary of validation reports only in debug mode
|
|
1059
1137
|
if DEBUG_MODE:
|
|
@@ -1072,9 +1150,7 @@ if __name__ == "__main__":
|
|
|
1072
1150
|
if open_validation in ['y', 'yes']:
|
|
1073
1151
|
for file_path in validation_files_created:
|
|
1074
1152
|
print("Opening: {}".format(os.path.basename(file_path)))
|
|
1075
|
-
|
|
1076
|
-
if ret != 0:
|
|
1077
|
-
print("Failed to open Notepad for: {}".format(os.path.basename(file_path)))
|
|
1153
|
+
os.startfile(file_path)
|
|
1078
1154
|
else:
|
|
1079
1155
|
print("No validation reports were generated.")
|
|
1080
1156
|
print("This may be because:")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|