medicafe 0.250811.3__tar.gz → 0.250811.4__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.
Files changed (76) hide show
  1. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/api_core.py +28 -9
  2. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_837p_encoder_library.py +2 -2
  3. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Down.py +10 -7
  4. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Gmail.py +6 -4
  5. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_PatientProcessor.py +17 -4
  6. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_UI.py +5 -4
  7. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Up.py +42 -8
  8. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_main.py +8 -3
  9. {medicafe-0.250811.3 → medicafe-0.250811.4}/PKG-INFO +1 -1
  10. {medicafe-0.250811.3 → medicafe-0.250811.4}/medicafe.egg-info/PKG-INFO +1 -1
  11. {medicafe-0.250811.3 → medicafe-0.250811.4}/setup.py +1 -1
  12. {medicafe-0.250811.3 → medicafe-0.250811.4}/LICENSE +0 -0
  13. {medicafe-0.250811.3 → medicafe-0.250811.4}/MANIFEST.in +0 -0
  14. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot.bat +0 -0
  15. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot.py +0 -0
  16. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot_Charges.py +0 -0
  17. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot_Crosswalk_Library.py +0 -0
  18. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot_Crosswalk_Utils.py +0 -0
  19. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot_Post.py +0 -0
  20. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot_Preprocessor.py +0 -0
  21. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot_Preprocessor_lib.py +0 -0
  22. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot_UI.py +0 -0
  23. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot_dataformat_library.py +0 -0
  24. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot_docx_decoder.py +0 -0
  25. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/MediBot_smart_import.py +0 -0
  26. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/__init__.py +0 -0
  27. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/get_medicafe_version.py +0 -0
  28. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/update_json.py +0 -0
  29. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediBot/update_medicafe.py +0 -0
  30. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/MediLink_ConfigLoader.py +0 -0
  31. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/__init__.py +0 -0
  32. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/__main__.py +0 -0
  33. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/api_core_backup.py +0 -0
  34. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/api_factory.py +0 -0
  35. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/api_utils.py +0 -0
  36. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/core_utils.py +0 -0
  37. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/graphql_utils.py +0 -0
  38. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/logging_config.py +0 -0
  39. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/logging_demo.py +0 -0
  40. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/migration_helpers.py +0 -0
  41. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediCafe/smart_import.py +0 -0
  42. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_837p_cob_library.py +0 -0
  43. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_837p_encoder.py +0 -0
  44. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_837p_utilities.py +0 -0
  45. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_API_Generator.py +0 -0
  46. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Azure.py +0 -0
  47. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_ClaimStatus.py +0 -0
  48. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_DataMgmt.py +0 -0
  49. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Decoder.py +0 -0
  50. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Deductible.py +0 -0
  51. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Deductible_Validator.py +0 -0
  52. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Display_Utils.py +0 -0
  53. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Mailer.py +0 -0
  54. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Parser.py +0 -0
  55. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Scan.py +0 -0
  56. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_Scheduler.py +0 -0
  57. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_insurance_utils.py +0 -0
  58. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/MediLink_smart_import.py +0 -0
  59. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/Soumit_api.py +0 -0
  60. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/__init__.py +0 -0
  61. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/gmail_http_utils.py +0 -0
  62. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/gmail_oauth_utils.py +0 -0
  63. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/insurance_type_integration_test.py +0 -0
  64. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/openssl.cnf +0 -0
  65. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/test.py +0 -0
  66. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/test_cob_library.py +0 -0
  67. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/test_timing.py +0 -0
  68. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/test_validation.py +0 -0
  69. {medicafe-0.250811.3 → medicafe-0.250811.4}/MediLink/webapp.html +0 -0
  70. {medicafe-0.250811.3 → medicafe-0.250811.4}/medicafe.egg-info/SOURCES.txt +0 -0
  71. {medicafe-0.250811.3 → medicafe-0.250811.4}/medicafe.egg-info/dependency_links.txt +0 -0
  72. {medicafe-0.250811.3 → medicafe-0.250811.4}/medicafe.egg-info/entry_points.txt +0 -0
  73. {medicafe-0.250811.3 → medicafe-0.250811.4}/medicafe.egg-info/not-zip-safe +0 -0
  74. {medicafe-0.250811.3 → medicafe-0.250811.4}/medicafe.egg-info/requires.txt +0 -0
  75. {medicafe-0.250811.3 → medicafe-0.250811.4}/medicafe.egg-info/top_level.txt +0 -0
  76. {medicafe-0.250811.3 → medicafe-0.250811.4}/setup.cfg +0 -0
@@ -258,7 +258,9 @@ class APIClient(BaseAPIClient):
258
258
  # Validate that we actually need a token before fetching
259
259
  # Check if the endpoint configuration exists and is valid
260
260
  try:
261
- endpoint_config = self.config['MediLink_Config']['endpoints'][endpoint_name]
261
+ from MediCafe.core_utils import extract_medilink_config
262
+ medi = extract_medilink_config(self.config)
263
+ endpoint_config = medi.get('endpoints', {}).get(endpoint_name)
262
264
  if not endpoint_config:
263
265
  MediLink_ConfigLoader.log("No configuration found for endpoint: {}".format(endpoint_name), level="ERROR")
264
266
  return None
@@ -362,7 +364,11 @@ class APIClient(BaseAPIClient):
362
364
  # Add environment-specific headers automatically
363
365
  headers = self.add_environment_headers(headers, endpoint_name)
364
366
 
365
- base_url = self.config['MediLink_Config']['endpoints'][endpoint_name]['api_url']
367
+ from MediCafe.core_utils import extract_medilink_config
368
+ medi = extract_medilink_config(self.config)
369
+ base_url = medi.get('endpoints', {}).get(endpoint_name, {}).get('api_url', '')
370
+ if not base_url:
371
+ raise ValueError("Missing api_url for endpoint {}".format(endpoint_name))
366
372
  url = base_url + url_extension
367
373
 
368
374
  # VERBOSE LOGGING: Log all request details before making the call
@@ -609,7 +615,9 @@ def fetch_payer_name_from_api(client, payer_id, config, primary_endpoint='AVAILI
609
615
  primary_endpoint = 'AVAILITY'
610
616
 
611
617
  try:
612
- endpoints = config['MediLink_Config']['endpoints']
618
+ from MediCafe.core_utils import extract_medilink_config
619
+ medi = extract_medilink_config(config)
620
+ endpoints = medi.get('endpoints', {})
613
621
  except KeyError as e:
614
622
  error_message = "Configuration loading error in fetch_payer_name_from_api: Missing key {0}... Attempting to reload configuration.".format(e)
615
623
  # print(error_message)
@@ -735,7 +743,9 @@ def get_claim_summary_by_provider(client, tin, first_service_date, last_service_
735
743
  MediLink_ConfigLoader.log("=" * 80, level="INFO")
736
744
 
737
745
  endpoint_name = 'UHCAPI'
738
- url_extension = client.config['MediLink_Config']['endpoints'][endpoint_name]['additional_endpoints']['claim_summary_by_provider']
746
+ from MediCafe.core_utils import extract_medilink_config
747
+ medi = extract_medilink_config(client.config)
748
+ url_extension = medi.get('endpoints', {}).get(endpoint_name, {}).get('additional_endpoints', {}).get('claim_summary_by_provider', '')
739
749
 
740
750
  if DEBUG:
741
751
  MediLink_ConfigLoader.log("URL Extension: {}".format(url_extension), level="INFO")
@@ -762,7 +772,9 @@ def get_claim_summary_by_provider(client, tin, first_service_date, last_service_
762
772
 
763
773
  def get_eligibility(client, payer_id, provider_last_name, search_option, date_of_birth, member_id, npi):
764
774
  endpoint_name = 'UHCAPI'
765
- url_extension = client.config['MediLink_Config']['endpoints'][endpoint_name]['additional_endpoints']['eligibility']
775
+ from MediCafe.core_utils import extract_medilink_config
776
+ medi = extract_medilink_config(client.config)
777
+ url_extension = medi.get('endpoints', {}).get(endpoint_name, {}).get('additional_endpoints', {}).get('eligibility', '')
766
778
  url_extension = url_extension + '?payerID={}&providerLastName={}&searchOption={}&dateOfBirth={}&memberId={}&npi={}'.format(
767
779
  payer_id, provider_last_name, search_option, date_of_birth, member_id, npi)
768
780
  return client.make_api_call(endpoint_name, 'GET', url_extension)
@@ -784,7 +796,9 @@ def get_eligibility_v3(client, payer_id, provider_last_name, search_option, date
784
796
  raise ValueError("Invalid payer_id: {}. Must be one of: {}".format(payer_id, ", ".join(valid_payer_ids)))
785
797
 
786
798
  endpoint_name = 'UHCAPI'
787
- url_extension = client.config['MediLink_Config']['endpoints'][endpoint_name]['additional_endpoints']['eligibility_v3']
799
+ from MediCafe.core_utils import extract_medilink_config
800
+ medi = extract_medilink_config(client.config)
801
+ url_extension = medi.get('endpoints', {}).get(endpoint_name, {}).get('additional_endpoints', {}).get('eligibility_v3', '')
788
802
 
789
803
  # Construct request body
790
804
  body = {
@@ -849,7 +863,9 @@ def get_eligibility_super_connector(client, payer_id, provider_last_name, search
849
863
  url_extension = client.config['MediLink_Config']['endpoints'][endpoint_name]['additional_endpoints']['eligibility_super_connector']
850
864
 
851
865
  # Get provider TIN from config (using existing billing_provider_tin)
852
- provider_tin = client.config['MediLink_Config'].get('billing_provider_tin')
866
+ from MediCafe.core_utils import extract_medilink_config
867
+ medi = extract_medilink_config(client.config)
868
+ provider_tin = medi.get('billing_provider_tin')
853
869
  if not provider_tin:
854
870
  raise ValueError("Provider TIN not found in configuration")
855
871
 
@@ -990,8 +1006,11 @@ def submit_uhc_claim(client, x12_request_data):
990
1006
  MediLink_ConfigLoader.log("=" * 80, level="INFO")
991
1007
 
992
1008
  endpoint_name = 'UHCAPI'
993
- claim_submission_url = client.config['MediLink_Config']['endpoints'][endpoint_name]['additional_endpoints']['claim_submission']
994
- claim_details_url = client.config['MediLink_Config']['endpoints'][endpoint_name]['additional_endpoints']['claim_details']
1009
+ from MediCafe.core_utils import extract_medilink_config
1010
+ medi = extract_medilink_config(client.config)
1011
+ endpoints = medi.get('endpoints', {})
1012
+ claim_submission_url = endpoints.get(endpoint_name, {}).get('additional_endpoints', {}).get('claim_submission', '')
1013
+ claim_details_url = endpoints.get(endpoint_name, {}).get('additional_endpoints', {}).get('claim_details', '')
995
1014
 
996
1015
  MediLink_ConfigLoader.log("Claim Submission URL: {}".format(claim_submission_url), level="INFO")
997
1016
  MediLink_ConfigLoader.log("Claim Details URL: {}".format(claim_details_url), level="INFO")
@@ -164,7 +164,7 @@ def create_hl_billing_provider_segment():
164
164
 
165
165
  # Constructs the NM1 segment for billing provider and includes address and Tax ID.
166
166
  def create_nm1_billing_provider_segment(config, endpoint):
167
- endpoint_config = config['endpoints'].get(endpoint.upper(), {})
167
+ endpoint_config = config.get('endpoints', {}).get(endpoint.upper(), {})
168
168
 
169
169
  # Billing provider details
170
170
  billing_provider_entity_code = endpoint_config.get('billing_provider_entity_code', '85')
@@ -296,7 +296,7 @@ def create_1000A_submitter_name_segment(patient_data, config, endpoint):
296
296
  # Constructs the NM1 segment for the receiver (1000B).
297
297
  def create_1000B_receiver_name_segment(config, endpoint):
298
298
  # Retrieve endpoint specific configuration
299
- endpoint_config = config['endpoints'].get(endpoint.upper(), {})
299
+ endpoint_config = config.get('endpoints', {}).get(endpoint.upper(), {})
300
300
 
301
301
  # Set the entity identifier code to '40' for receiver and qualifier to '46' for EDI,
302
302
  # unless specified differently in the endpoint configuration.
@@ -11,7 +11,7 @@ if current_dir not in sys.path:
11
11
 
12
12
  # Use core utilities for imports
13
13
  try:
14
- from MediCafe.core_utils import get_shared_config_loader
14
+ from MediCafe.core_utils import get_shared_config_loader, extract_medilink_config
15
15
  MediLink_ConfigLoader = get_shared_config_loader()
16
16
  if MediLink_ConfigLoader is not None:
17
17
  log = MediLink_ConfigLoader.log
@@ -155,12 +155,13 @@ def main(desired_endpoint=None):
155
155
 
156
156
  try:
157
157
  config, _ = load_configuration()
158
- endpoint_config = config['MediLink_Config']['endpoints'].get(desired_endpoint)
158
+ medi = extract_medilink_config(config)
159
+ endpoint_config = medi.get('endpoints', {}).get(desired_endpoint)
159
160
  if not endpoint_config or 'remote_directory_down' not in endpoint_config:
160
161
  log("Configuration for endpoint '{}' is incomplete or missing 'remote_directory_down'.".format(desired_endpoint), level="ERROR")
161
162
  return None, None
162
163
 
163
- local_storage_path = config['MediLink_Config']['local_storage_path']
164
+ local_storage_path = medi.get('local_storage_path', '.')
164
165
  log("Local storage path set to {}".format(local_storage_path))
165
166
 
166
167
  downloaded_files = operate_winscp("download", None, endpoint_config, local_storage_path, config)
@@ -201,11 +202,12 @@ def check_for_new_remittances(config=None):
201
202
  if config is None:
202
203
  config, _ = load_configuration()
203
204
 
204
- if not config or 'MediLink_Config' not in config or 'endpoints' not in config['MediLink_Config']:
205
+ medi = extract_medilink_config(config)
206
+ if not medi or 'endpoints' not in medi:
205
207
  log("Error: Config is missing necessary sections. Aborting...", level="ERROR")
206
208
  return
207
209
 
208
- endpoints = config['MediLink_Config'].get('endpoints')
210
+ endpoints = medi.get('endpoints')
209
211
  if not isinstance(endpoints, dict):
210
212
  log("Error: 'endpoints' is not a dictionary. Aborting...", level="ERROR")
211
213
  return
@@ -237,7 +239,7 @@ def check_for_new_remittances(config=None):
237
239
  # Step 3: After processing all endpoints, handle the accumulated results
238
240
  if all_consolidated_records:
239
241
  display_consolidated_records(all_consolidated_records) # Ensure this is called only once
240
- prompt_csv_export(all_consolidated_records, config['MediLink_Config']['local_storage_path'])
242
+ prompt_csv_export(all_consolidated_records, medi.get('local_storage_path', '.'))
241
243
  else:
242
244
  log("No records to display after processing all endpoints.", level="WARNING")
243
245
  print("No records to display after processing all endpoints.")
@@ -250,7 +252,8 @@ def process_endpoint(endpoint_key, endpoint_info, config):
250
252
  """
251
253
  try:
252
254
  # Process the files for the given endpoint
253
- local_storage_path = config['MediLink_Config']['local_storage_path']
255
+ medi = extract_medilink_config(config)
256
+ local_storage_path = medi.get('local_storage_path', '.')
254
257
  log("[Process Endpoint] Local storage path set to {}".format(local_storage_path))
255
258
  downloaded_files = operate_winscp("download", None, endpoint_info, local_storage_path, config)
256
259
 
@@ -14,7 +14,7 @@ def setup_python_path():
14
14
  # Set up paths before importing MediCafe
15
15
  setup_python_path()
16
16
 
17
- from MediCafe.core_utils import get_shared_config_loader
17
+ from MediCafe.core_utils import get_shared_config_loader, extract_medilink_config
18
18
 
19
19
  # New helpers
20
20
  from MediLink.gmail_oauth_utils import (
@@ -47,7 +47,8 @@ import platform
47
47
  import ctypes
48
48
 
49
49
  config, _ = load_configuration()
50
- local_storage_path = config['MediLink_Config']['local_storage_path']
50
+ medi = extract_medilink_config(config)
51
+ local_storage_path = medi.get('local_storage_path', '.')
51
52
  downloaded_emails_file = os.path.join(local_storage_path, 'downloaded_emails.txt')
52
53
 
53
54
  server_port = 8000
@@ -379,10 +380,11 @@ def open_browser_with_executable(url, browser_path=None):
379
380
 
380
381
  def initiate_link_retrieval(config):
381
382
  log("Initiating browser via implicit GET.")
382
- url_get = "https://script.google.com/macros/s/{}/exec?action=get_link".format(config['MediLink_Config']['webapp_deployment_id'])
383
+ medi = extract_medilink_config(config)
384
+ url_get = "https://script.google.com/macros/s/{}/exec?action=get_link".format(medi.get('webapp_deployment_id', ''))
383
385
  open_browser_with_executable(url_get)
384
386
  log("Preparing POST call.")
385
- url = "https://script.google.com/macros/s/{}/exec".format(config['MediLink_Config']['webapp_deployment_id'])
387
+ url = "https://script.google.com/macros/s/{}/exec".format(medi.get('webapp_deployment_id', ''))
386
388
  downloaded_emails = list(load_downloaded_emails())
387
389
  payload = {"downloadedEmails": downloaded_emails}
388
390
  access_token = get_access_token()
@@ -5,7 +5,7 @@
5
5
  import os, sys
6
6
 
7
7
  # Use core utilities for standardized imports
8
- from MediCafe.core_utils import get_shared_config_loader, import_medibot_module
8
+ from MediCafe.core_utils import get_shared_config_loader, import_medibot_module, extract_medilink_config
9
9
  MediLink_ConfigLoader = get_shared_config_loader()
10
10
 
11
11
  import MediLink_DataMgmt
@@ -86,7 +86,11 @@ def collect_detailed_patient_data(selected_files, config, crosswalk):
86
86
  detailed_patient_data = []
87
87
 
88
88
  # Retrieve insurance options with codes and descriptions
89
- insurance_options = config['MediLink_Config'].get('insurance_options')
89
+ try:
90
+ medi = extract_medilink_config(config)
91
+ insurance_options = medi.get('insurance_options')
92
+ except Exception:
93
+ insurance_options = None
90
94
 
91
95
  for file_path in selected_files:
92
96
  # IMPORTANT: extract_and_suggest_endpoint creates data with 'patient_id' field
@@ -235,7 +239,11 @@ def extract_and_suggest_endpoint(file_path, config, crosswalk):
235
239
 
236
240
  for personal_info, insurance_info, service_info, service_info_2, service_info_3 in MediLink_DataMgmt.read_fixed_width_data(file_path):
237
241
  # Parse reserved 5-line record: 3 active lines + 2 reserved for future expansion
238
- parsed_data = MediLink_DataMgmt.parse_fixed_width_data(personal_info, insurance_info, service_info, service_info_2, service_info_3, config.get('MediLink_Config', config))
242
+ try:
243
+ cfg_for_parse = extract_medilink_config(config)
244
+ except Exception:
245
+ cfg_for_parse = config
246
+ parsed_data = MediLink_DataMgmt.parse_fixed_width_data(personal_info, insurance_info, service_info, service_info_2, service_info_3, cfg_for_parse)
239
247
 
240
248
  primary_insurance = parsed_data.get('INAME')
241
249
 
@@ -264,7 +272,12 @@ def extract_and_suggest_endpoint(file_path, config, crosswalk):
264
272
  MediLink_ConfigLoader.log("Suggested endpoint for payer ID '{}': {}".format(payer_id, suggested_endpoint))
265
273
 
266
274
  # Validate suggested endpoint against the config
267
- if suggested_endpoint not in config['MediLink_Config'].get('endpoints', {}):
275
+ try:
276
+ medi = extract_medilink_config(config)
277
+ endpoints = medi.get('endpoints', {})
278
+ except Exception:
279
+ endpoints = {}
280
+ if suggested_endpoint not in endpoints:
268
281
  MediLink_ConfigLoader.log("Warning: Suggested endpoint '{}' is not defined in the configuration. Please Run MediBot. If this persists, check the crosswalk and config file.".format(suggested_endpoint), level="ERROR")
269
282
  raise ValueError("Invalid suggested endpoint: '{}' for payer ID '{}'. Please correct the configuration.".format(suggested_endpoint, payer_id))
270
283
  else:
@@ -6,7 +6,7 @@ import os, sys
6
6
  from MediCafe.core_utils import setup_module_paths
7
7
  setup_module_paths(__file__)
8
8
 
9
- from MediCafe.core_utils import get_shared_config_loader
9
+ from MediCafe.core_utils import get_shared_config_loader, extract_medilink_config
10
10
  MediLink_ConfigLoader = get_shared_config_loader()
11
11
  import MediLink_DataMgmt
12
12
  import MediLink_PatientProcessor
@@ -177,7 +177,8 @@ def select_and_adjust_files(detailed_patient_data, config, crosswalk):
177
177
  selected_indices = get_selected_indices(len(detailed_patient_data))
178
178
 
179
179
  # Get an ordered list of endpoint keys
180
- endpoint_keys = list(config['MediLink_Config']['endpoints'].keys())
180
+ medi = extract_medilink_config(config)
181
+ endpoint_keys = list(medi.get('endpoints', {}).keys())
181
182
 
182
183
  # Iterate over each selected index and process endpoint changes
183
184
  for i in selected_indices:
@@ -187,12 +188,12 @@ def select_and_adjust_files(detailed_patient_data, config, crosswalk):
187
188
 
188
189
  endpoint_change = get_endpoint_decision()
189
190
  if endpoint_change == 'y':
190
- display_endpoint_options(config['MediLink_Config']['endpoints'])
191
+ display_endpoint_options(medi.get('endpoints', {}))
191
192
  endpoint_index = get_new_endpoint_choice() - 1 # Adjusting for zero-based index
192
193
 
193
194
  if 0 <= endpoint_index < len(endpoint_keys):
194
195
  selected_endpoint_key = endpoint_keys[endpoint_index]
195
- print("Endpoint changed to {0} for patient {1}.".format(config['MediLink_Config']['endpoints'][selected_endpoint_key]['name'], data['patient_name']))
196
+ print("Endpoint changed to {0} for patient {1}.".format(medi.get('endpoints', {}).get(selected_endpoint_key, {}).get('name', selected_endpoint_key), data['patient_name']))
196
197
 
197
198
  # Use the new endpoint management system
198
199
  updated_crosswalk = MediLink_DataMgmt.update_suggested_endpoint_with_user_preference(
@@ -73,7 +73,15 @@ def submit_claims(detailed_patient_data_grouped_by_endpoint, config, crosswalk):
73
73
  config, _ = load_configuration()
74
74
  except Exception:
75
75
  config = {}
76
- cfg = config.get('MediLink_Config', config) if isinstance(config, dict) else {}
76
+ # Ensure cfg is always a dict to avoid NoneType.get errors
77
+ if isinstance(config, dict):
78
+ cfg_candidate = config.get('MediLink_Config')
79
+ if isinstance(cfg_candidate, dict):
80
+ cfg = cfg_candidate
81
+ else:
82
+ cfg = config
83
+ else:
84
+ cfg = {}
77
85
 
78
86
  # Accumulate submission results
79
87
  submission_results = {}
@@ -88,7 +96,11 @@ def submit_claims(detailed_patient_data_grouped_by_endpoint, config, crosswalk):
88
96
  continue
89
97
 
90
98
  # Determine the submission method (e.g., "winscp" or "api")
91
- method = cfg.get('endpoints', {}).get(endpoint, {}).get('submission_method', 'winscp')
99
+ try:
100
+ method = cfg.get('endpoints', {}).get(endpoint, {}).get('submission_method', 'winscp')
101
+ except Exception:
102
+ # Absolute fallback if cfg was unexpectedly not a dict
103
+ method = 'winscp'
92
104
 
93
105
  # Attempt submission to each endpoint
94
106
  if True: #confirm_transmission({endpoint: patients_data}): # Confirm transmission to each endpoint with detailed overview
@@ -192,7 +204,15 @@ def handle_transmission_result(transmission_result, config, operation_type, meth
192
204
  # - On some XP setups, WinSCP writes logs to a different directory than where files are uploaded or downloaded.
193
205
  # - To avoid brittle assumptions, allow an explicit 'winscp_log_dir' override while preserving legacy default.
194
206
  # - Fallback remains 'local_claims_path' to preserve current behavior.
195
- cfg = config.get('MediLink_Config', config) if isinstance(config, dict) else {}
207
+ # Ensure cfg is a dict for safe access
208
+ if isinstance(config, dict):
209
+ _cfg_candidate = config.get('MediLink_Config')
210
+ if isinstance(_cfg_candidate, dict):
211
+ cfg = _cfg_candidate
212
+ else:
213
+ cfg = config
214
+ else:
215
+ cfg = {}
196
216
  winscp_log_dir = (
197
217
  cfg.get('winscp_log_dir')
198
218
  or cfg.get('local_claims_path')
@@ -240,10 +260,16 @@ def handle_transmission_result(transmission_result, config, operation_type, meth
240
260
  # Process each API response to determine the success status
241
261
  for file_path, response in transmission_result:
242
262
  try:
243
- # Check if the API response indicates a successful submission
244
- success = response.get('message') in ["Claim validated and sent for further processing", "Acknowledgement pending"]
245
- # Record the API message.
246
- message = response.get('message', 'No message provided')
263
+ # Handle responses that may be None or non-dict safely
264
+ if isinstance(response, dict):
265
+ message = response.get('message', 'No message provided')
266
+ success = message in [
267
+ "Claim validated and sent for further processing",
268
+ "Acknowledgement pending"
269
+ ]
270
+ else:
271
+ message = str(response) if response is not None else 'No response received'
272
+ success = False
247
273
  success_dict[file_path] = (success, message)
248
274
  except Exception as e:
249
275
  # Handle API exception
@@ -473,7 +499,15 @@ def save_receipt_to_file(receipt_content, config):
473
499
  """
474
500
  try:
475
501
  file_name = "Receipt_{0}.txt".format(datetime.now().strftime('%Y%m%d_%H%M%S'))
476
- cfg = config.get('MediLink_Config', config) if isinstance(config, dict) else {}
502
+ # Ensure cfg is a dict for safe path resolution
503
+ if isinstance(config, dict):
504
+ cfg_candidate = config.get('MediLink_Config')
505
+ if isinstance(cfg_candidate, dict):
506
+ cfg = cfg_candidate
507
+ else:
508
+ cfg = config
509
+ else:
510
+ cfg = {}
477
511
  file_path = os.path.join(cfg.get('local_claims_path', '.'), file_name)
478
512
 
479
513
  with open(file_path, 'w') as file:
@@ -21,7 +21,7 @@ if PERFORMANCE_LOGGING:
21
21
 
22
22
 
23
23
  # Now import core utilities after path setup
24
- from MediCafe.core_utils import get_shared_config_loader, setup_module_paths
24
+ from MediCafe.core_utils import get_shared_config_loader, setup_module_paths, extract_medilink_config
25
25
  setup_module_paths(__file__)
26
26
 
27
27
  # Import modules after path setup
@@ -116,7 +116,11 @@ def main_menu():
116
116
 
117
117
  # Normalize the directory path for file operations.
118
118
  path_norm_start = time.time()
119
- directory_path = os.path.normpath(config['MediLink_Config']['inputFilePath'])
119
+ medi = extract_medilink_config(config)
120
+ input_file_path = medi.get('inputFilePath')
121
+ if not input_file_path:
122
+ raise ValueError("Configuration error: 'inputFilePath' missing in MediLink_Config")
123
+ directory_path = os.path.normpath(input_file_path)
120
124
  path_norm_end = time.time()
121
125
  if PERFORMANCE_LOGGING:
122
126
  print("Path normalization completed in {:.2f} seconds".format(path_norm_end - path_norm_start))
@@ -206,7 +210,8 @@ def handle_submission(detailed_patient_data, config, crosswalk):
206
210
  insurance_edited = True # User chose to edit insurance types
207
211
 
208
212
  # Get insurance options from config
209
- insurance_options = config['MediLink_Config'].get('insurance_options', {})
213
+ medi = extract_medilink_config(config)
214
+ insurance_options = medi.get('insurance_options', {})
210
215
 
211
216
  while True:
212
217
  # Bulk edit insurance types
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: medicafe
3
- Version: 0.250811.3
3
+ Version: 0.250811.4
4
4
  Summary: MediCafe
5
5
  Home-page: https://github.com/katanada2/MediCafe
6
6
  Author: Daniel Vidaud
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: medicafe
3
- Version: 0.250811.3
3
+ Version: 0.250811.4
4
4
  Summary: MediCafe
5
5
  Home-page: https://github.com/katanada2/MediCafe
6
6
  Author: Daniel Vidaud
@@ -54,7 +54,7 @@ if long_description_text is None:
54
54
 
55
55
  setup(
56
56
  name='medicafe',
57
- version="0.250811.3",
57
+ version="0.250811.4",
58
58
  description='MediCafe',
59
59
  long_description=long_description_text,
60
60
  long_description_content_type='text/markdown',
File without changes
File without changes
File without changes