medicafe 0.240419.2__py3-none-any.whl → 0.240517.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.

@@ -0,0 +1,357 @@
1
+ from collections import OrderedDict, defaultdict
2
+ from datetime import datetime
3
+ import os
4
+ import csv
5
+ import sys
6
+
7
+ # Add parent directory of the project to the Python path
8
+ project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
9
+ sys.path.append(project_dir)
10
+
11
+ try:
12
+ import MediLink_ConfigLoader
13
+ import MediLink_DataMgmt
14
+ except ImportError:
15
+ from MediLink import MediLink_ConfigLoader
16
+ from MediLink import MediLink_DataMgmt
17
+
18
+ try:
19
+ from MediBot_UI import app_control
20
+ except ImportError:
21
+ from MediBot import MediBot_UI
22
+ app_control = MediBot_UI.app_control
23
+
24
+ """
25
+ Draft Docstring to move over from Preprocessor.
26
+
27
+ Data Integrity and Validation
28
+ Implement a mechanism to confirm the accuracy of entered data, potentially through a verification step or summary report.
29
+ Enhance CSV integrity checks to identify and report potential issues with data format, especially concerning insurance policy numbers and special character handling.
30
+
31
+ Development Roadmap for crosswalk_update()
32
+ Automation required for updating the crosswalk.json when new Medisoft insurance is discovered.
33
+ For open_csv_for_editing
34
+
35
+ Known Issues and Bugs
36
+ Address the handling of '.' and other special characters that may disrupt parsing, especially under Windows XP.
37
+
38
+ For load_csv_data
39
+
40
+ Preprocessing Enhancements
41
+ Optimize script startup and CSV loading to reduce initial latency.
42
+
43
+ Data Integrity and Validation
44
+ Conduct a thorough CSV integrity check before processing to flag potential issues upfront.
45
+
46
+ Future Work
47
+ Consolidate data from multiple sources (Provider_Notes.csv, Surgery_Schedule.csv, and Carols_CSV.csv) into a single table with Patient ID as the key, ensuring all data elements are aligned and duplicate entries are minimized.
48
+ Implement logic to verify and match Patient IDs across different files to ensure data integrity before consolidation. (Catching errors between source data)
49
+ Optimize the preprocessing of surgery dates and diagnosis codes for use in patient billing and scheduling systems.
50
+ """
51
+ class InitializationError(Exception):
52
+ def __init__(self, message):
53
+ self.message = message
54
+ super().__init__(self.message)
55
+
56
+ def initialize(config):
57
+ global AHK_EXECUTABLE, CSV_FILE_PATH, field_mapping, page_end_markers
58
+
59
+ try:
60
+ AHK_EXECUTABLE = config.get('AHK_EXECUTABLE', "")
61
+ except AttributeError:
62
+ raise InitializationError("Error: 'AHK_EXECUTABLE' not found in config.")
63
+
64
+ try:
65
+ CSV_FILE_PATH = config.get('CSV_FILE_PATH', "")
66
+ except AttributeError:
67
+ raise InitializationError("Error: 'CSV_FILE_PATH' not found in config.")
68
+
69
+ try:
70
+ field_mapping = OrderedDict(config.get('field_mapping', {}))
71
+ except AttributeError:
72
+ raise InitializationError("Error: 'field_mapping' not found in config.")
73
+
74
+ try:
75
+ page_end_markers = config.get('page_end_markers', [])
76
+ except AttributeError:
77
+ raise InitializationError("Error: 'page_end_markers' not found in config.")
78
+
79
+
80
+ def open_csv_for_editing(csv_file_path):
81
+ try:
82
+ # Open the CSV file with its associated application
83
+ os.system('start "" "{}"'.format(csv_file_path))
84
+ print("After saving the revised CSV, please re-run MediBot.")
85
+ except Exception as e:
86
+ print("Failed to open CSV file:", e)
87
+
88
+ # Function to load and process CSV data
89
+ def load_csv_data(csv_file_path):
90
+ try:
91
+ # Check if the file exists
92
+ if not os.path.exists(csv_file_path):
93
+ raise FileNotFoundError("***Error: CSV file '{}' not found.".format(csv_file_path))
94
+
95
+ with open(csv_file_path, 'r') as csvfile:
96
+ reader = csv.DictReader(csvfile)
97
+ return [row for row in reader] # Return a list of dictionaries
98
+ except FileNotFoundError as e:
99
+ print(e) # Print the informative error message
100
+ print("Hint: Check if CSV file is located in the expected directory or specify a different path in config file.")
101
+ print("Please correct the issue and re-run MediBot.")
102
+ sys.exit(1) # Halt the script
103
+ except IOError as e:
104
+ print("Error reading CSV file: {}. Please check the file path and permissions.".format(e))
105
+ sys.exit(1) # Halt the script in case of other IO errors
106
+
107
+ # CSV Pre-processor Helper functions
108
+ def add_insurance_id_column(csv_data):
109
+ for row in csv_data:
110
+ row['Ins1 Insurance ID'] = '' # Initialize the column with empty values
111
+
112
+ def filter_rows(csv_data):
113
+ csv_data[:] = [row for row in csv_data if row.get('Patient ID', '').strip()]
114
+ csv_data[:] = [row for row in csv_data if row.get('Primary Insurance', '').strip() not in ['AETNA', 'AETNA MEDICARE', 'HUMANA MED HMO']]
115
+
116
+ def convert_surgery_date(csv_data):
117
+ for row in csv_data:
118
+ try:
119
+ row['Surgery Date'] = datetime.strptime(row.get('Surgery Date', ''), '%m/%d/%Y')
120
+ except ValueError:
121
+ row['Surgery Date'] = datetime.min # Assign a minimum datetime value for sorting purposes
122
+
123
+ def sort_and_deduplicate(csv_data):
124
+ csv_data.sort(key=lambda x: (x['Surgery Date'], x.get('Patient Last', '').strip()))
125
+ unique_patients = {}
126
+ for row in csv_data:
127
+ patient_id = row.get('Patient ID')
128
+ if patient_id not in unique_patients or row['Surgery Date'] < unique_patients[patient_id]['Surgery Date']:
129
+ unique_patients[patient_id] = row
130
+ csv_data[:] = list(unique_patients.values())
131
+ csv_data.sort(key=lambda x: (x['Surgery Date'], x.get('Patient Last', '').strip()))
132
+
133
+ def combine_fields(csv_data):
134
+ for row in csv_data:
135
+ row['Surgery Date'] = row['Surgery Date'].strftime('%m/%d/%Y')
136
+ first_name = row.get('Patient First', '').strip()
137
+ middle_name = row.get('Patient Middle', '').strip()
138
+ if len(middle_name) > 1:
139
+ middle_name = middle_name[0] # Take only the first character
140
+ last_name = row.get('Patient Last', '').strip()
141
+ row['Patient Name'] = "{}, {} {}".format(last_name, first_name, middle_name).strip()
142
+ address1 = row.get('Patient Address1', '').strip()
143
+ address2 = row.get('Patient Address2', '').strip()
144
+ row['Patient Street'] = "{} {}".format(address1, address2).strip()
145
+
146
+ def apply_replacements(csv_data, crosswalk):
147
+ replacements = crosswalk.get('csv_replacements', {})
148
+ for row in csv_data:
149
+ for old_value, new_value in replacements.items():
150
+ if row.get('Patient SSN', '') == old_value:
151
+ row['Patient SSN'] = new_value
152
+ elif row.get('Primary Insurance', '') == old_value:
153
+ row['Primary Insurance'] = new_value
154
+ elif row.get('Ins1 Payer ID') == old_value:
155
+ row['Ins1 Payer ID'] = new_value
156
+
157
+ def update_insurance_ids(csv_data, crosswalk):
158
+ for row in csv_data:
159
+ ins1_payer_id = row.get('Ins1 Payer ID', '').strip()
160
+ # MediLink_ConfigLoader.log("Ins1 Payer ID '{}' associated with Patient ID {}.".format(ins1_payer_id, row.get('Patient ID', "None")))
161
+ if ins1_payer_id:
162
+ if ins1_payer_id in crosswalk.get('payer_id', {}):
163
+ medisoft_ids = crosswalk['payer_id'][ins1_payer_id].get('medisoft_id', [])
164
+ if medisoft_ids:
165
+ medisoft_ids = [int(id) for id in medisoft_ids]
166
+ # TODO Try to match OpenPM's Insurance Name to get a better match
167
+ row['Ins1 Insurance ID'] = medisoft_ids[0]
168
+ # MediLink_ConfigLoader.log("Ins1 Insurance ID '{}' used for Payer ID {} in crosswalk.".format(row.get('Ins1 Insurance ID', ''), ins1_payer_id))
169
+ else:
170
+ MediLink_ConfigLoader.log("Ins1 Payer ID '{}' not found in the crosswalk.".format(ins1_payer_id))
171
+ # Create a placeholder entry in the crosswalk, need to consider the medisoft_medicare_id handling later.
172
+ if 'payer_id' not in crosswalk:
173
+ crosswalk['payer_id'] = {}
174
+ crosswalk['payer_id'][ins1_payer_id] = {
175
+ 'medisoft_id': [],
176
+ 'medisoft_medicare_id': [],
177
+ 'endpoint': 'OPTUMEDI' # Default probably should be a flag for the crosswalk update function to deal with. BUG HARDCODE THERE ARE 3 of these defaults
178
+ }
179
+
180
+ def load_data_sources(config, crosswalk):
181
+ """Loads historical mappings from MAPAT and Carol's CSVs."""
182
+ patient_id_to_insurance_id = load_insurance_data_from_mapat(config, crosswalk)
183
+ if not patient_id_to_insurance_id:
184
+ raise ValueError("Failed to load historical Patient ID to Insurance ID mappings from MAPAT.")
185
+
186
+ payer_id_to_patient_ids = load_historical_payer_to_patient_mappings(config)
187
+ if not payer_id_to_patient_ids:
188
+ raise ValueError("Failed to load historical Carol's CSVs.")
189
+
190
+ return patient_id_to_insurance_id, payer_id_to_patient_ids
191
+
192
+ def map_payer_ids_to_insurance_ids(patient_id_to_insurance_id, payer_id_to_patient_ids):
193
+ """Maps Payer IDs to Insurance IDs based on the historical mappings."""
194
+ payer_id_to_details = {}
195
+ for payer_id, patient_ids in payer_id_to_patient_ids.items():
196
+ medisoft_ids = set()
197
+ for patient_id in patient_ids:
198
+ if patient_id in patient_id_to_insurance_id:
199
+ medisoft_id = patient_id_to_insurance_id[patient_id]
200
+ medisoft_ids.add(medisoft_id)
201
+ MediLink_ConfigLoader.log("Added Medisoft ID {} for Patient ID {} and Payer ID {}".format(medisoft_id, patient_id, payer_id))
202
+ else:
203
+ MediLink_ConfigLoader.log("No matching Insurance ID found for Patient ID {}".format(patient_id))
204
+ if medisoft_ids:
205
+ payer_id_to_details[payer_id] = {
206
+ "endpoint": "OPTUMEDI", # TODO Default, to be refined via API poll. There are 2 of these defaults!
207
+ "medisoft_id": list(medisoft_ids),
208
+ "medisoft_medicare_id": [] # Placeholder for future implementation
209
+ }
210
+ return payer_id_to_details
211
+
212
+ def load_insurance_data_from_mains(config):
213
+ """
214
+ Loads insurance data from MAINS and creates a mapping from insurance names to their respective IDs.
215
+ This mapping is critical for the crosswalk update process to correctly associate payer IDs with insurance IDs.
216
+
217
+ Args:
218
+ config (dict): Configuration object containing necessary paths and parameters.
219
+
220
+ Returns:
221
+ dict: A dictionary mapping insurance names to insurance IDs.
222
+ """
223
+ # Reset config pull to make sure its not using the MediLink config key subset
224
+ config, crosswalk = MediLink_ConfigLoader.load_configuration()
225
+
226
+ # Retrieve MAINS path and slicing information from the configuration
227
+ # TODO (Low) For secondary insurance, this needs to be pulling from the correct MAINS (there are 2)
228
+ # TODO (Low) Performance: There probably needs to be a dictionary proxy for MAINS that gets updated.
229
+ mains_path = config['MAINS_MED_PATH']
230
+ mains_slices = crosswalk['mains_mapping']['slices']
231
+
232
+ # Initialize the dictionary to hold the insurance to insurance ID mappings
233
+ insurance_to_id = {}
234
+
235
+ # Read data from MAINS using a provided function to handle fixed-width data
236
+ for record, line_number in MediLink_DataMgmt.read_general_fixed_width_data(mains_path, mains_slices):
237
+ insurance_name = record['MAINSNAME']
238
+ # Assuming line_number gives the correct insurance ID without needing adjustment
239
+ insurance_to_id[insurance_name] = line_number
240
+
241
+ return insurance_to_id
242
+
243
+ def load_insurance_data_from_mapat(config, crosswalk):
244
+ """
245
+ Loads insurance data from MAPAT and creates a mapping from patient ID to insurance ID.
246
+
247
+ Args:
248
+ config (dict): Configuration object containing necessary paths and parameters.
249
+ crosswalk ... ADD HERE.
250
+
251
+ Returns:
252
+ dict: A dictionary mapping patient IDs to insurance IDs.
253
+ """
254
+ # Retrieve MAPAT path and slicing information from the configuration
255
+ mapat_path = app_control.get_mapat_med_path()
256
+ mapat_slices = crosswalk['mapat_mapping']['slices']
257
+
258
+ # Initialize the dictionary to hold the patient ID to insurance ID mappings
259
+ patient_id_to_insurance_id = {}
260
+
261
+ # Read data from MAPAT using a provided function to handle fixed-width data
262
+ for record, _ in MediLink_DataMgmt.read_general_fixed_width_data(mapat_path, mapat_slices):
263
+ patient_id = record['MAPATPXID']
264
+ insurance_id = record['MAPATINID']
265
+ patient_id_to_insurance_id[patient_id] = insurance_id
266
+
267
+ return patient_id_to_insurance_id
268
+
269
+ def parse_z_dat(z_dat_path, config):
270
+ """
271
+ Parses the Z.dat file to map Patient IDs to Insurance Names using the provided fixed-width file format.
272
+
273
+ Args:
274
+ z_dat_path (str): Path to the Z.dat file.
275
+ config (dict): Configuration object containing slicing information and other parameters.
276
+
277
+ Returns:
278
+ dict: A dictionary mapping Patient IDs to Insurance Names.
279
+ """
280
+ patient_id_to_insurance_name = {}
281
+
282
+ try:
283
+ # Reading blocks of fixed-width data (3 lines per record: personal, insurance, service)
284
+ for personal_info, insurance_info, service_info in MediLink_DataMgmt.read_fixed_width_data(z_dat_path):
285
+ # Parsing the data using slice definitions from the config
286
+ parsed_data = MediLink_DataMgmt.parse_fixed_width_data(personal_info, insurance_info, service_info, config.get('MediLink_Config', config))
287
+
288
+ # Extract Patient ID and Insurance Name from parsed data
289
+ patient_id = parsed_data.get('PATID')
290
+ insurance_name = parsed_data.get('INAME')
291
+
292
+ if patient_id and insurance_name:
293
+ patient_id_to_insurance_name[patient_id] = insurance_name
294
+ MediLink_ConfigLoader.log("Mapped Patient ID {} to Insurance Name {}".format(patient_id, insurance_name), config, level="INFO")
295
+
296
+ except FileNotFoundError:
297
+ MediLink_ConfigLoader.log("File not found: {}".format(z_dat_path), config, level="ERROR")
298
+ raise
299
+ except Exception as e:
300
+ MediLink_ConfigLoader.log("Failed to parse Z.dat: {}".format(str(e)), config, level="ERROR")
301
+ raise
302
+
303
+ return patient_id_to_insurance_name
304
+
305
+ def load_historical_payer_to_patient_mappings(config):
306
+ """
307
+ Loads historical mappings from multiple Carol's CSV files in a specified directory,
308
+ mapping Payer IDs to sets of Patient IDs.
309
+
310
+ Args:
311
+ config (dict): Configuration object containing the directory path for Carol's CSV files
312
+ and other necessary parameters.
313
+
314
+ Returns:
315
+ dict: A dictionary where each key is a Payer ID and the value is a set of Patient IDs.
316
+ """
317
+ directory_path = os.path.dirname(config['CSV_FILE_PATH'])
318
+ payer_to_patient_ids = defaultdict(set)
319
+
320
+ try:
321
+ # Check if the directory exists
322
+ if not os.path.isdir(directory_path):
323
+ raise FileNotFoundError("Directory '{}' not found.".format(directory_path))
324
+
325
+ # Loop through each file in the directory containing Carol's historical CSVs
326
+ for filename in os.listdir(directory_path):
327
+ file_path = os.path.join(directory_path, filename)
328
+ if filename.endswith('.csv'):
329
+ try:
330
+ with open(file_path, 'r', encoding='utf-8') as csvfile:
331
+ reader = csv.DictReader(csvfile)
332
+ patient_count = 0 # Counter for Patient IDs found in this CSV
333
+ for row in reader:
334
+ if 'Patient ID' not in row or 'Ins1 Payer ID' not in row:
335
+ continue # Skip this row if either key is missing
336
+ if not row.get('Patient ID').strip() or not row.get('Ins1 Payer ID').strip():
337
+ continue # Skip this row if either value is missing or empty
338
+
339
+ payer_id = row['Ins1 Payer ID'].strip()
340
+ patient_id = row['Patient ID'].strip()
341
+ payer_to_patient_ids[payer_id].add(patient_id)
342
+ patient_count += 1 # Increment the counter for each valid mapping
343
+
344
+ # Log the accumulated count for this CSV file
345
+ if patient_count > 0:
346
+ MediLink_ConfigLoader.log("CSV file '{}' has {} Patient IDs with Payer IDs.".format(filename, patient_count))
347
+ else:
348
+ MediLink_ConfigLoader.log("CSV file '{}' is empty or does not have valid Patient ID or Payer ID mappings.".format(filename))
349
+ except Exception as e:
350
+ print("Error processing file {}: {}".format(filename, e))
351
+ except FileNotFoundError as e:
352
+ print("Error: {}".format(e))
353
+
354
+ if not payer_to_patient_ids:
355
+ print("No historical mappings were generated.")
356
+
357
+ return dict(payer_to_patient_ids)
MediBot/MediBot_UI.py CHANGED
@@ -3,22 +3,66 @@ import ctypes
3
3
  from ctypes import wintypes
4
4
  import time
5
5
  import re
6
- import re #for addresses
7
- from MediBot_Preprocessor import config
6
+
7
+ # Add parent directory of the project to the Python path
8
+ import os
9
+ import sys
10
+ project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
11
+ sys.path.append(project_dir)
12
+
13
+ try:
14
+ from MediLink import MediLink_ConfigLoader
15
+ config, crosswalk = MediLink_ConfigLoader.load_configuration()
16
+ except ImportError:
17
+ from MediLink_ConfigLoader import load_configuration
18
+ config, crosswalk = load_configuration()
8
19
 
9
20
  """
10
21
  User Interaction Refinements
11
22
  - [ ] Refine the menu options for clearer user guidance during script pauses and errors.
12
23
  - [ ] Add functionality for user to easily repeat or skip specific entries without script restart.
13
24
  Develop more intuitive skip and retry mechanisms that are responsive to user input during data entry sessions.
14
-
15
25
  """
16
26
  # Function to check if a specific key is pressed
17
27
  VK_END = int(config.get('VK_END', ""), 16) # Try F12 (7B). Virtual key code for 'End' (23)
18
28
  VK_PAUSE = int(config.get('VK_PAUSE', ""), 16) # Try F11 (7A). Virtual-key code for 'Home' (24)
19
29
 
20
- MAPAT_MED_PATH = '' # Initialize global constant for MAPAT path
21
- MEDISOFT_SHORTCUT = '' # Initialize global constant for LNK path
30
+ class AppControl:
31
+ def __init__(self):
32
+ self.script_paused = False
33
+ self.mapat_med_path = ''
34
+ self.medisoft_shortcut = ''
35
+ # Load initial paths from config when instance is created
36
+ self.load_paths_from_config()
37
+
38
+ def get_pause_status(self):
39
+ return self.script_paused
40
+
41
+ def set_pause_status(self, status):
42
+ self.script_paused = status
43
+
44
+ def get_mapat_med_path(self):
45
+ return self.mapat_med_path
46
+
47
+ def set_mapat_med_path(self, path):
48
+ self.mapat_med_path = path
49
+
50
+ def get_medisoft_shortcut(self):
51
+ return self.medisoft_shortcut
52
+
53
+ def set_medisoft_shortcut(self, path):
54
+ self.medisoft_shortcut = path
55
+
56
+ def load_paths_from_config(self, medicare=False):
57
+ # Assuming `config` is a module or a globally accessible configuration dictionary
58
+ if medicare:
59
+ self.mapat_med_path = config.get('MEDICARE_MAPAT_MED_PATH', "")
60
+ self.medisoft_shortcut = config.get('MEDICARE_SHORTCUT', "")
61
+ else:
62
+ self.mapat_med_path = config.get('MAPAT_MED_PATH', "")
63
+ self.medisoft_shortcut = config.get('PRIVATE_SHORTCUT', "")
64
+
65
+ app_control = AppControl()
22
66
 
23
67
  def is_key_pressed(key_code):
24
68
  user32 = ctypes.WinDLL('user32', use_last_error=True)
@@ -27,19 +71,17 @@ def is_key_pressed(key_code):
27
71
  return user32.GetAsyncKeyState(key_code) & 0x8000 != 0
28
72
 
29
73
  def manage_script_pause(csv_data, error_message, reverse_mapping):
30
- global script_paused
31
- #print("Debug - Entered manage_script_pause with pause status: {}".format(script_paused))
32
74
  user_action = 0 # initialize as 'continue'
33
75
 
34
- if not script_paused and is_key_pressed(VK_PAUSE):
35
- script_paused = True
76
+ if not app_control.get_pause_status() and is_key_pressed(VK_PAUSE):
77
+ app_control.set_pause_status(True)
36
78
  print("Script paused. Opening menu...")
37
79
  interaction_mode = 'normal' # Assuming normal interaction mode for script pause
38
80
  user_action = user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
39
81
 
40
- while script_paused:
82
+ while app_control.get_pause_status():
41
83
  if is_key_pressed(VK_END):
42
- script_paused = False
84
+ app_control.set_pause_status(False)
43
85
  print("Continuing...")
44
86
  elif is_key_pressed(VK_PAUSE):
45
87
  user_action = user_interaction(csv_data, 'normal', error_message, reverse_mapping)
@@ -80,7 +122,7 @@ def display_patient_selection_menu(csv_data, reverse_mapping, proceed_as_medicar
80
122
  patient_name = row.get(patient_name_header, "Unknown")
81
123
  surgery_date = row.get('Surgery Date', "Unknown Date") # Access 'Surgery Date' as string directly from the row
82
124
 
83
- print("{0:02d}: {3:.5s} (ID: {2}) {1} ".format(index+1, patient_name, patient_id, surgery_date))
125
+ print("{0:03d}: {3:.5s} (ID: {2}) {1} ".format(index+1, patient_name, patient_id, surgery_date))
84
126
 
85
127
  displayed_indices.append(index)
86
128
  displayed_patient_ids.append(patient_id)
@@ -101,10 +143,23 @@ def display_patient_selection_menu(csv_data, reverse_mapping, proceed_as_medicar
101
143
  display_menu_header("Patient Selection for Today's Data Entry")
102
144
  selected_indices, selected_patient_ids = display_patient_list(csv_data, reverse_mapping)
103
145
  print("-" * 60)
104
- selection = input("\nEnter the number(s) of the patients you wish to proceed with \n(e.g., 1,3,5): ")
105
- selection = selection.replace('.', ',') # Replace '.' with ',' in the user input just in case
106
- selected_indices = [int(x.strip()) - 1 for x in selection.split(',')]
107
- proceed = True
146
+
147
+ while True:
148
+ selection = input("\nEnter the number(s) of the patients you wish to proceed with \n(e.g., 1,3,5): ").strip()
149
+
150
+ if not selection:
151
+ print("Invalid entry. Please provide at least one number.")
152
+ continue
153
+
154
+ selection = selection.replace('.', ',') # Replace '.' with ',' in the user input just in case
155
+ selected_indices = [int(x.strip()) - 1 for x in selection.split(',') if x.strip().isdigit()]
156
+
157
+ if not selected_indices:
158
+ print("Invalid entry. Please provide at least one integer.")
159
+ continue
160
+
161
+ proceed = True
162
+ break
108
163
 
109
164
  patient_id_header = reverse_mapping['Patient ID #2']
110
165
  selected_patient_ids = [csv_data[i][patient_id_header] for i in selected_indices if i < len(csv_data)]
@@ -153,38 +208,33 @@ def handle_user_interaction(interaction_mode, error_message):
153
208
  print("Invalid choice. Please enter a valid number.")
154
209
 
155
210
  def user_interaction(csv_data, interaction_mode, error_message, reverse_mapping):
156
- # Consider logging the actions taken during user interaction for audit purposes.
157
- global MAPAT_MED_PATH, MEDISOFT_SHORTCUT # Initialize global constants
211
+ global app_control # Use the instance of AppControl
158
212
  selected_patient_ids = []
159
213
  selected_indices = []
160
214
 
161
215
  if interaction_mode == 'triage':
162
-
163
216
  display_menu_header(" =(^.^)= Welcome to MediBot! =(^.^)=")
164
-
217
+
165
218
  while True:
166
219
  response = input("\nAm I processing Medicare patients? (yes/no): ").lower().strip()
167
- if response: # Check if the response is not empty
220
+ if response:
168
221
  if response in ['yes', 'y']:
169
- proceed_as_medicare = True
222
+ app_control.load_paths_from_config(medicare=True)
170
223
  break
171
224
  elif response in ['no', 'n']:
172
- proceed_as_medicare = False
225
+ app_control.load_paths_from_config(medicare=False)
173
226
  break
174
227
  else:
175
228
  print("Invalid entry. Please enter 'yes' or 'no'.")
176
229
  else:
177
230
  print("A response is required. Please try again.")
178
231
 
179
- MAPAT_MED_PATH = config.get('MEDICARE_MAPAT_MED_PATH', "") if proceed_as_medicare else config.get('MAPAT_MED_PATH', "")
180
- MEDISOFT_SHORTCUT = config.get('MEDICARE_SHORTCUT', "") if proceed_as_medicare else config.get('PRIVATE_SHORTCUT', "")
181
-
182
232
  fixed_values = config.get('fixed_values', {}) # Get fixed values from config json
183
- if proceed_as_medicare:
233
+ if response in ['yes', 'y']:
184
234
  medicare_added_fixed_values = config.get('medicare_added_fixed_values', {})
185
- fixed_values.update(medicare_added_fixed_values) # Add any medicare-specific fixed values from config
235
+ fixed_values.update(medicare_added_fixed_values) # Add any medicare-specific fixed values from config
186
236
 
187
- proceed, selected_patient_ids, selected_indices = display_patient_selection_menu(csv_data, reverse_mapping, proceed_as_medicare)
237
+ proceed, selected_patient_ids, selected_indices = display_patient_selection_menu(csv_data, reverse_mapping, response in ['yes', 'y'])
188
238
  return proceed, selected_patient_ids, selected_indices, fixed_values
189
-
239
+
190
240
  return handle_user_interaction(interaction_mode, error_message)