medicafe 0.240415.1__tar.gz → 0.240613.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.

Files changed (54) hide show
  1. medicafe-0.240613.0/MANIFEST.in +2 -0
  2. medicafe-0.240613.0/MediBot/MediBot.bat +206 -0
  3. medicafe-0.240613.0/MediBot/MediBot.py +319 -0
  4. medicafe-0.240613.0/MediBot/MediBot_Charges.py +0 -0
  5. medicafe-0.240613.0/MediBot/MediBot_Crosswalk_Library.py +281 -0
  6. medicafe-0.240613.0/MediBot/MediBot_Post.py +0 -0
  7. medicafe-0.240613.0/MediBot/MediBot_Preprocessor.py +210 -0
  8. medicafe-0.240613.0/MediBot/MediBot_Preprocessor_lib.py +496 -0
  9. medicafe-0.240613.0/MediBot/MediBot_UI.py +235 -0
  10. medicafe-0.240613.0/MediBot/MediBot_dataformat_library.py +189 -0
  11. medicafe-0.240613.0/MediBot/MediBot_docx_decoder.py +295 -0
  12. medicafe-0.240613.0/MediBot/PDF_to_CSV_Cleaner.py +211 -0
  13. medicafe-0.240613.0/MediBot/__init__.py +0 -0
  14. medicafe-0.240613.0/MediBot/update_json.py +43 -0
  15. medicafe-0.240613.0/MediBot/update_medicafe.py +57 -0
  16. medicafe-0.240613.0/MediLink/MediLink.py +376 -0
  17. medicafe-0.240613.0/MediLink/MediLink_837p_encoder.py +477 -0
  18. medicafe-0.240613.0/MediLink/MediLink_837p_encoder_library.py +879 -0
  19. medicafe-0.240613.0/MediLink/MediLink_API_v2.py +174 -0
  20. medicafe-0.240613.0/MediLink/MediLink_APIs.py +139 -0
  21. medicafe-0.240613.0/MediLink/MediLink_ConfigLoader.py +81 -0
  22. medicafe-0.240613.0/MediLink/MediLink_DataMgmt.py +414 -0
  23. medicafe-0.240613.0/MediLink/MediLink_Decoder.py +63 -0
  24. medicafe-0.240613.0/MediLink/MediLink_Down.py +122 -0
  25. medicafe-0.240613.0/MediLink/MediLink_Gmail.py +479 -0
  26. medicafe-0.240613.0/MediLink/MediLink_Mailer.py +0 -0
  27. medicafe-0.240613.0/MediLink/MediLink_Parser.py +111 -0
  28. medicafe-0.240613.0/MediLink/MediLink_Scan.py +0 -0
  29. medicafe-0.240613.0/MediLink/MediLink_Scheduler.py +3 -0
  30. medicafe-0.240613.0/MediLink/MediLink_StatusCheck.py +0 -0
  31. medicafe-0.240613.0/MediLink/MediLink_UI.py +176 -0
  32. medicafe-0.240613.0/MediLink/MediLink_Up.py +373 -0
  33. medicafe-0.240613.0/MediLink/MediLink_batch.bat +7 -0
  34. medicafe-0.240613.0/MediLink/Soumit_api.py +22 -0
  35. medicafe-0.240613.0/MediLink/__init__.py +0 -0
  36. medicafe-0.240613.0/MediLink/test.py +74 -0
  37. medicafe-0.240613.0/PKG-INFO +48 -0
  38. medicafe-0.240613.0/README.md +42 -0
  39. medicafe-0.240613.0/medicafe.egg-info/PKG-INFO +48 -0
  40. medicafe-0.240613.0/medicafe.egg-info/SOURCES.txt +45 -0
  41. medicafe-0.240613.0/medicafe.egg-info/requires.txt +7 -0
  42. medicafe-0.240613.0/medicafe.egg-info/top_level.txt +2 -0
  43. medicafe-0.240613.0/setup.py +65 -0
  44. medicafe-0.240415.1/PKG-INFO +0 -17
  45. medicafe-0.240415.1/README.md +0 -28
  46. medicafe-0.240415.1/medicafe.egg-info/PKG-INFO +0 -17
  47. medicafe-0.240415.1/medicafe.egg-info/SOURCES.txt +0 -9
  48. medicafe-0.240415.1/medicafe.egg-info/requires.txt +0 -4
  49. medicafe-0.240415.1/medicafe.egg-info/top_level.txt +0 -1
  50. medicafe-0.240415.1/setup.py +0 -22
  51. {medicafe-0.240415.1 → medicafe-0.240613.0}/LICENSE +0 -0
  52. {medicafe-0.240415.1 → medicafe-0.240613.0}/medicafe.egg-info/dependency_links.txt +0 -0
  53. {medicafe-0.240415.1 → medicafe-0.240613.0}/medicafe.egg-info/not-zip-safe +0 -0
  54. {medicafe-0.240415.1 → medicafe-0.240613.0}/setup.cfg +0 -0
@@ -0,0 +1,2 @@
1
+ include MediBot/MediBot.bat
2
+ include MediLink/MediLink_batch.bat
@@ -0,0 +1,206 @@
1
+ @echo off
2
+ setlocal enabledelayedexpansion
3
+
4
+ :: Define paths
5
+ set "source_folder=C:\MEDIANSI\MediCare"
6
+ set "target_folder=C:\MEDIANSI\MediCare\CSV"
7
+ set "config_file=F:\Medibot\json\config.json"
8
+ set "python_script=C:\Python34\Lib\site-packages\MediBot\update_json.py"
9
+ set "python_script2=C:\Python34\Lib\site-packages\MediBot\Medibot.py"
10
+ set "medicafe_package=medicafe"
11
+ set "upgrade_medicafe=F:\Medibot\update_medicafe.py"
12
+ set "temp_file=F:\Medibot\last_update_timestamp.txt"
13
+ set "firefox_path=C:\Program Files\Mozilla Firefox\firefox.exe"
14
+ set "package_version="
15
+ set PYTHONWARNINGS=ignore
16
+
17
+ :: Check if Python is installed and the path is correctly set
18
+ python --version >nul 2>&1
19
+ if %errorlevel% neq 0 (
20
+ echo Python is not installed or not added to PATH.
21
+ exit /b
22
+ )
23
+
24
+ :: Check if the MediCafe package is installed and retrieve its version
25
+ echo Checking for installed MediCafe package version...
26
+ python -c "import pkg_resources; print('MediCafe=='+pkg_resources.get_distribution('medicafe').version)" > temp.txt 2>nul
27
+ set /p package_version=<temp.txt
28
+ del temp.txt
29
+
30
+ if not defined package_version (
31
+ echo MediCafe package version not detected or MediCafe not installed. Consider manual re-install.
32
+ exit /b
33
+ )
34
+
35
+ :: Extract version number and display it
36
+ for /f "tokens=2 delims==" %%a in ("%package_version%") do (
37
+ set "medicafe_version=%%a"
38
+ )
39
+
40
+ if not defined medicafe_version (
41
+ echo Failed to detect MediCafe version.
42
+ ) else (
43
+ echo Detected MediCafe version: %medicafe_version%
44
+ )
45
+
46
+ :: Check for internet connectivity
47
+ ping -n 1 google.com > nul 2>&1
48
+ if %ERRORLEVEL% neq 0 (
49
+ set "internet_available=0"
50
+ echo No internet connection detected.
51
+ ) else (
52
+ set "internet_available=1"
53
+ echo Internet connection detected.
54
+ )
55
+
56
+ :: Common pre-menu setup
57
+ echo Setting up the environment...
58
+ if not exist "%config_file%" (
59
+ echo Configuration file missing.
60
+ goto end_script
61
+ )
62
+
63
+ :: Check if the file exists and attempt to move it
64
+ :: Implementing a check with copy as a fallback if move fails
65
+ echo Checking for the upgrade script...
66
+ if exist "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" (
67
+ echo Found upgrade_medicafe.py. Attempting to move...
68
+ move "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" "F:\Medibot\upgrade_medicafe.py" >nul 2>&1
69
+ if %errorlevel% neq 0 (
70
+ echo Move failed. Attempting copy and delete as fallback...
71
+ copy "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" "F:\Medibot\upgrade_medicafe.py" >nul 2>&1
72
+ if %errorlevel% neq 0 (
73
+ echo Copy failed. Error Level: %errorlevel%
74
+ ) else (
75
+ del "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" >nul 2>&1
76
+ if %errorlevel% neq 0 (
77
+ echo Delete failed. Manual cleanup may be required.
78
+ ) else (
79
+ echo File copied and original deleted successfully.
80
+ )
81
+ )
82
+ ) else (
83
+ echo File moved successfully.
84
+ )
85
+ ) else (
86
+ echo upgrade_medicafe.py not detected. Check path and filename.
87
+ )
88
+
89
+ :: Main menu
90
+ :main_menu
91
+ cls
92
+ echo version: %medicafe_version%
93
+ echo --------------------------------------------------------------
94
+ echo .//* Welcome to MediCafe *\\.
95
+ echo --------------------------------------------------------------
96
+ echo.
97
+ echo Please select an option:
98
+ if "!internet_available!"=="1" (
99
+ echo 1. Check for MediCafe Package Updates
100
+ echo 2. Download Email de Carol
101
+ echo 3. MediLink Claims
102
+ )
103
+ echo 4. Run MediBot
104
+ echo 5. Exit
105
+ echo.
106
+ set /p choice=Enter your choice:
107
+
108
+ if "!choice!"=="5" goto end_script
109
+ if "!choice!"=="4" goto medibot_flow
110
+ if "!choice!"=="3" goto medilink_flow
111
+ if "!choice!"=="2" goto download_emails
112
+ if "!choice!"=="1" goto check_updates
113
+
114
+ :: Medicafe Update
115
+ :check_updates
116
+ if "!internet_available!"=="0" (
117
+ echo No internet connection available.
118
+ goto main_menu
119
+ )
120
+ echo Checking for MediCafe package updates. Please wait...
121
+ start cmd /c py "%upgrade_medicafe%" > upgrade_log.txt 2>&1 && (
122
+ echo %DATE% %TIME% Upgrade initiated. >> "%temp_file%"
123
+ echo Exiting batch to complete the upgrade.
124
+ ) || (
125
+ echo %DATE% %TIME% Update failed. Check logs. >> upgrade_log.txt
126
+ )
127
+ exit /b
128
+
129
+ :: Download Carol's Emails
130
+ :download_emails
131
+ if "!internet_available!"=="0" (
132
+ echo No internet connection available.
133
+ goto main_menu
134
+ )
135
+ echo Downloading emails...
136
+ :: move this path.
137
+ py "../MediLink/MediLink_Gmail.py" "%firefox_path%"
138
+ if errorlevel 1 (
139
+ echo Failed to download emails.
140
+ pause
141
+ ) else (
142
+ echo Calling CSV Processor...
143
+ call :process_csvs
144
+ )
145
+ goto main_menu
146
+
147
+ :: Run MediBot Flow
148
+ :medibot_flow
149
+ call :process_csvs
150
+ cls
151
+ echo Please wait...
152
+ py "%python_script2%" "%config_file%"
153
+ if errorlevel 1 echo Failed to run MediBot.
154
+ pause
155
+ goto main_menu
156
+
157
+ :: Continue to MediLink
158
+ :medilink_flow
159
+ if "!internet_available!"=="0" (
160
+ echo No internet connection available.
161
+ goto main_menu
162
+ )
163
+ call :process_csvs
164
+ cls
165
+ :: move this path.
166
+ py "C:\Python34\Lib\site-packages\MediLink\MediLink.py"
167
+ if errorlevel 1 echo MediLink failed to execute.
168
+ pause
169
+ goto main_menu
170
+
171
+ :: Process CSV Files
172
+ :process_csvs
173
+ for /f "tokens=1-5 delims=/: " %%a in ('echo %time%') do (
174
+ set "hour=%%a"
175
+ set "minute=%%b"
176
+ set "second=%%c"
177
+ )
178
+ for /f "tokens=2-4 delims=/ " %%a in ('echo %date%') do (
179
+ set "day=%%a"
180
+ set "month=%%b"
181
+ set "year=%%c"
182
+ )
183
+ set "timestamp=!year!!month!!day!_!hour!!minute!"
184
+
185
+ set "latest_csv="
186
+ for /f "delims=" %%a in ('dir /b /a-d /o-d "%source_folder%\*.csv" 2^>nul') do (
187
+ set "latest_csv=%%a"
188
+ echo Found New CSV Files...
189
+ goto process_found_csv
190
+ )
191
+ ::echo CSV Check Complete.
192
+ goto :eof
193
+
194
+ :process_found_csv
195
+ echo Processing CSVs...
196
+ move "%source_folder%\!latest_csv!" "%target_folder%\SX_CSV_!timestamp!.csv"
197
+ set "new_csv_path=%target_folder%\SX_CSV_!timestamp!.csv"
198
+ py "%python_script%" "%config_file%" "!new_csv_path!"
199
+ echo CSV Processor Complete...
200
+ goto :eof
201
+
202
+ :: Exit Script
203
+ :end_script
204
+ echo Exiting MediCafe.
205
+ pause
206
+ exit /b
@@ -0,0 +1,319 @@
1
+ import subprocess
2
+ import os
3
+ import tempfile
4
+ import traceback
5
+ import re #for addresses
6
+ from collections import OrderedDict
7
+ import MediBot_dataformat_library
8
+ import MediBot_Preprocessor
9
+ from MediBot_Preprocessor_lib import initialize, AHK_EXECUTABLE, CSV_FILE_PATH, field_mapping, load_csv_data
10
+ from MediBot_UI import app_control, manage_script_pause, user_interaction
11
+
12
+ # Add parent directory of the project to the Python path
13
+ import sys
14
+ project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
15
+ sys.path.append(project_dir)
16
+
17
+ from MediLink import MediLink_ConfigLoader
18
+
19
+ try:
20
+ from MediBot_Crosswalk_Library import crosswalk_update
21
+ except ImportError:
22
+ from MediBot import MediBot_Crosswalk_Library
23
+ crosswalk_update = MediBot_Crosswalk_Library.crosswalk_update
24
+
25
+ def identify_field(header, field_mapping):
26
+ for medisoft_field, patterns in field_mapping.items():
27
+ for pattern in patterns:
28
+ if re.search(pattern, header, re.IGNORECASE):
29
+ return medisoft_field
30
+ return None
31
+
32
+ # Add this print to a function that is calling identify_field
33
+ #print("Warning: No matching field found for CSV header '{}'".format(header))
34
+
35
+ # Function to execute an AutoHotkey script
36
+ def run_ahk_script(script_content):
37
+ temp_script_name = None
38
+ try:
39
+ # Create a temporary AHK script file
40
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.ahk') as temp_script:
41
+ temp_script_name = temp_script.name
42
+ temp_script.write(script_content.encode('utf-8'))
43
+ temp_script.flush()
44
+ # Attempt to run the AHK script
45
+ subprocess.check_call([AHK_EXECUTABLE, temp_script_name])
46
+ except subprocess.CalledProcessError as e:
47
+ # This exception will catch any non-zero exit status from the AHK script
48
+ print("AHK script failed with exit status:", e.returncode)
49
+ print("Output from AHK script:", e.output)
50
+ except Exception as e:
51
+ # This catches any other exceptions that may occur
52
+ print("An unexpected error occurred while running the AHK script:", e)
53
+ traceback.print_exc() # Print the stack trace of the exception
54
+ finally:
55
+ # Delete the temporary script file
56
+ if temp_script_name:
57
+ try:
58
+ os.unlink(temp_script_name)
59
+ except OSError as e:
60
+ print("Error deleting temporary script file:", e)
61
+
62
+ # Global variable to store the last processed entry
63
+ last_processed_entry = None
64
+ # Global variable to store temporarily parsed address components
65
+ parsed_address_components = {}
66
+
67
+ def process_field(medisoft_field, csv_row, parsed_address_components, reverse_mapping, csv_data, fixed_values):
68
+ global last_processed_entry
69
+
70
+ try:
71
+ value = ''
72
+ if medisoft_field in parsed_address_components:
73
+ value = parsed_address_components.get(medisoft_field, '')
74
+ elif medisoft_field in fixed_values:
75
+ value = fixed_values[medisoft_field][0] # Use the fixed value
76
+ elif medisoft_field in reverse_mapping:
77
+ if medisoft_field == "Ins1 Insurance ID" or reverse_mapping[medisoft_field] == "Primary Insurance Company":
78
+ MediLink_ConfigLoader.log("Detected {} or {}: {}".format(medisoft_field, reverse_mapping[medisoft_field], value))
79
+ csv_header = reverse_mapping[medisoft_field]
80
+ value = csv_row.get(csv_header, '')
81
+
82
+ formatted_value = MediBot_dataformat_library.format_data(medisoft_field, value, csv_data, reverse_mapping, parsed_address_components) if value else 'Send, {Enter}'
83
+ run_ahk_script(formatted_value)
84
+
85
+ last_processed_entry = (medisoft_field, value)
86
+ return 'continue', last_processed_entry
87
+ except Exception as e:
88
+ return handle_error(e, medisoft_field, last_processed_entry, csv_data)
89
+
90
+ def handle_error(error, medisoft_field, last_processed_entry, csv_data):
91
+ MediLink_ConfigLoader.log("Error in process_field: ", e)
92
+ print("An error occurred while processing {0}: {1}".format(medisoft_field, error))
93
+ # Assuming the interaction mode is 'error' in this case
94
+ interaction_mode = 'error'
95
+ response = user_interaction(csv_data, interaction_mode, error, reverse_mapping)
96
+ return response, last_processed_entry
97
+
98
+ # iterating through each field defined in the field_mapping.
99
+ def iterate_fields(csv_row, field_mapping, parsed_address_components, reverse_mapping, csv_data, fixed_values):
100
+ global last_processed_entry
101
+ # Check for user action at the start of each field processing
102
+ for medisoft_field in field_mapping.keys():
103
+ action = manage_script_pause(csv_data,'',reverse_mapping) # per-field pause availability. Necessary to provide frequent opportunities for the user to pause the script.
104
+ if action != 0: # If action is either 'Retry' (-1) or 'Skip' (1)
105
+ return action # Break out and pass the action up
106
+
107
+ # Process each field in the row
108
+ _, last_processed_entry = process_field(medisoft_field, csv_row, parsed_address_components, reverse_mapping, csv_data, fixed_values)
109
+
110
+ return 0 # Default action to continue
111
+
112
+ def data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values):
113
+ global last_processed_entry, parsed_address_components
114
+ # last_processed_entry, parsed_address_components = None, {} // BUG should this just be this line rather than the global line above?
115
+ error_message = '' # Initialize error_message once
116
+ current_row_index = 0
117
+
118
+ while current_row_index < len(csv_data):
119
+ row = csv_data[current_row_index]
120
+
121
+ # Handle script pause at the start of each row (patient record).
122
+ manage_script_pause(csv_data, error_message, reverse_mapping)
123
+ error_message = '' # Clear error message for the next iteration
124
+
125
+ if app_control.get_pause_status():
126
+ continue # Skip processing this row if the script is paused
127
+
128
+ # I feel like this is overwriting what would have already been idenfitied in the mapping.
129
+ # This probably needs to be initialized differently.
130
+ # parsed_address_components = {'City': '', 'State': '', 'Zip Code': ''}
131
+ parsed_address_components = {}
132
+
133
+ # Process each field in the row
134
+ action = iterate_fields(row, field_mapping, parsed_address_components, reverse_mapping, csv_data, fixed_values)
135
+ # TODO (Low) add a feature here where if you accidentally started overwriting a patient that you could go back 2 patients.
136
+ # Need to tell the user which patient we're talking about because it won't be obvious anymore.
137
+ if action == -1: # Retry
138
+ continue # Remain on the current row.
139
+ elif action == 1: # Skip
140
+ if current_row_index == len(csv_data) - 1: # If it's the last row
141
+ MediLink_ConfigLoader.log("Reached the end of the patient list.")
142
+ print("Reached the end of the patient list. Looping back to the beginning.")
143
+ current_row_index = 0 # Reset to the first row
144
+ else:
145
+ current_row_index += 1 # Move to the next row
146
+ continue
147
+ elif action == -2: # Go back two patients and redo
148
+ current_row_index = max(0, current_row_index - 2) # Go back two rows, but not below 0
149
+ continue
150
+
151
+ # Code to handle the end of a patient record
152
+ # TODO One day this can just not pause...
153
+ app_control.set_pause_status(True) # Pause at the end of processing each patient record
154
+ current_row_index += 1 # Move to the next row by default
155
+
156
+ def open_medisoft(shortcut_path):
157
+ try:
158
+ os.startfile(shortcut_path)
159
+ print("Medisoft is being opened...\n")
160
+ except subprocess.CalledProcessError as e:
161
+ print("Failed to open Medisoft:", e)
162
+ print("Please manually open Medisoft.")
163
+ except Exception as e:
164
+ print("An unexpected error occurred:", e)
165
+ print("Please manually open Medisoft.")
166
+ finally:
167
+ print("Press 'F12' to begin data entry.")
168
+
169
+ # Placeholder for any cleanup
170
+ def cleanup():
171
+ print("\n**** Medibot Finished! ****\n")
172
+ # THis might need to delete the staging stuff that gets set up by mostly MediLink but maybe other stuff too.
173
+ pass
174
+
175
+ class ExecutionState:
176
+ def __init__(self, config_path, crosswalk_path) -> None:
177
+ try:
178
+ config, crosswalk = MediLink_ConfigLoader.load_configuration(config_path, crosswalk_path)
179
+ self.verify_config_type(config)
180
+ self.crosswalk = crosswalk
181
+ self.config = config
182
+ MediLink_ConfigLoader.log("Config loaded successfully...")
183
+
184
+ crosswalk_update(config, crosswalk)
185
+ MediLink_ConfigLoader.log("Crosswalk update complete...")
186
+
187
+ initialize(config)
188
+ MediLink_ConfigLoader.log("Constants initialized...")
189
+
190
+ except Exception as e:
191
+ print("MediBot: Failed to load or update configuration: {}".format(e))
192
+ raise # Re-throwing the exception or using a more sophisticated error handling mechanism might be needed
193
+ # Handle the exception somehow (e.g., retry, halt, log)??
194
+
195
+ def verify_config_type(self, config):
196
+ if not isinstance(config, (dict, OrderedDict)):
197
+ raise TypeError("Error: Configuration must be a dictionary or an OrderedDict. Check unpacking.")
198
+
199
+ # Main script execution wrapped in try-except for error handling
200
+ if __name__ == "__main__":
201
+ e_state = None
202
+ try:
203
+ print("Please wait...")
204
+ # Default paths
205
+ default_config_path = os.path.join(os.path.dirname(__file__), '..', 'json', 'config.json')
206
+ default_crosswalk_path = os.path.join(os.path.dirname(__file__), '..', 'json', 'crosswalk.json')
207
+
208
+ # Check if command-line arguments are provided
209
+ if len(sys.argv) > 1:
210
+ # If arguments are provided, use them
211
+ config_path = sys.argv[1]
212
+ crosswalk_path = sys.argv[2] if len(sys.argv) > 2 else default_crosswalk_path
213
+ else:
214
+ # If no arguments are provided, use default paths
215
+ config_path = default_config_path
216
+ crosswalk_path = default_crosswalk_path
217
+
218
+ e_state = ExecutionState(config_path, crosswalk_path)
219
+
220
+ print("Loading CSV Data...")
221
+ MediLink_ConfigLoader.log("Loading CSV Data...", level="INFO")
222
+ csv_data = load_csv_data(CSV_FILE_PATH)
223
+
224
+ # Pre-process CSV data to add combined fields & crosswalk values.
225
+ print("Pre-Processing CSV...")
226
+ MediLink_ConfigLoader.log("Pre-processing CSV Data...", level="INFO")
227
+ MediBot_Preprocessor.preprocess_csv_data(csv_data, e_state.crosswalk)
228
+ headers = csv_data[0].keys() # Make sure all the headers are in place
229
+ # Patient charges should be added prior to the intake_scan.
230
+
231
+ print("Performing Intake Scan...")
232
+ MediLink_ConfigLoader.log("Performing Intake Scan...", level="INFO")
233
+ # identified_fields is an OrderedDict
234
+ identified_fields = MediBot_Preprocessor.intake_scan(headers, field_mapping)
235
+
236
+ # Reverse the identified_fields mapping for lookup
237
+ reverse_mapping = {v: k for k, v in identified_fields.items()}
238
+ # MediLink_ConfigLoader.log("Reverse Mapping: {}".format(reverse_mapping))
239
+
240
+ # CSV Patient Triage
241
+ interaction_mode = 'triage' # Start in triage mode
242
+ error_message = "" # This will be filled if an error has occurred
243
+ #print("Debug - Identified fields mapping (main): {}".format(identified_fields)) # Debug Line
244
+
245
+ print("Load Complete...")
246
+ _ = os.system('cls')
247
+
248
+ proceed, selected_patient_ids, selected_indices, fixed_values = user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
249
+
250
+ if proceed:
251
+ # Filter csv_data for selected patients from Triage mode.
252
+ csv_data = [row for index, row in enumerate(csv_data) if index in selected_indices]
253
+
254
+ # Check if MAPAT_MED_PATH is missing or blank
255
+ if not app_control.get_mapat_med_path() or not os.path.exists(app_control.get_mapat_med_path()):
256
+ print("Warning: MAPAT.MED PATH is missing or invalid. Please check the path configuration.")
257
+
258
+ # Perform the existing patients check
259
+ existing_patients, patients_to_process = MediBot_Preprocessor.check_existing_patients(selected_patient_ids, app_control.get_mapat_med_path())
260
+
261
+ if existing_patients:
262
+ print("\nNOTE: The following patient(s) already EXIST in the system and \n will be excluded from processing:")
263
+ # TODO ... not excluded anymore, because charges may need to be added.
264
+ # So at this point in the processing, we should have already processed the surgery schedules and enriched the data with Charges.
265
+ for patient_id, patient_name in existing_patients:
266
+ print("(ID: {0}) {1}".format(patient_id, patient_name))
267
+ # Update csv_data to exclude existing patients
268
+ # TODO This now has to be updated to handle patients that exist but need new charges added.
269
+ csv_data = [row for row in csv_data if row[reverse_mapping['Patient ID #2']] in patients_to_process]
270
+ else:
271
+ print("\nSelected patient(s) are NEW patients and will be processed.")
272
+
273
+ if len(patients_to_process) == 0:
274
+ proceed = input("\nAll patients have been processed. Continue anyway?: ").lower().strip() in ['yes', 'y']
275
+ else:
276
+ proceed = input("\nDo you want to proceed with the {} remaining patient(s)? (yes/no): ".format(len(patients_to_process))).lower().strip() in ['yes', 'y']
277
+
278
+ # TODO Here is where we need to add the step where we move to MediBot_Charges.
279
+ # The return is an enriched dataset to be picked up by medibot which means we need to return:
280
+ # csv_data, field_mapping, reverse_mapping, and fixed_values.
281
+
282
+ if proceed:
283
+
284
+ # Would be nice to have some kind of self-test here.
285
+ # print("\nDebug - Starting AHK script. Reload AHK if failed...")
286
+ # try:
287
+ # subprocess.call([AHK_EXECUTABLE, r"G:\My Drive\CocoWave\XP typing bot\notepad_test.ahk"])
288
+ # run_ahk_script('MsgBox, Test AHK Script Execution')
289
+ # except subprocess.CalledProcessError as e:
290
+ # print("Error running AHK script. Please reload AHK and try again. Error: {}".format(e))
291
+ # exit(1)
292
+ # except Exception as e:
293
+ # print("An unexpected error occurred while running the AHK script: {}".format(e))
294
+ # exit(1)
295
+
296
+ print("\nRemember, when in Medisoft:")
297
+ print(" Press 'F8' to create a New Patient.")
298
+ print(" Press 'F12' to begin data entry.")
299
+ print(" Press 'F11' at any time to Pause.")
300
+ input("\n*** Press [Enter] when ready to begin! ***\n")
301
+ MediLink_ConfigLoader.log("Opening Medisoft...")
302
+ open_medisoft(app_control.get_medisoft_shortcut())
303
+ app_control.set_pause_status(True)
304
+ _ = manage_script_pause(csv_data, error_message, reverse_mapping)
305
+ data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values)
306
+ cleanup()
307
+ else:
308
+ print("Data entry canceled by user. Exiting MediBot.")
309
+ except Exception as e:
310
+ if e_state:
311
+ interaction_mode = 'error' # Switch to error mode
312
+ error_message = str(e) # Capture the error message
313
+ print("An error occurred while running MediBot: {0}".format(e))
314
+ # Handle the error by calling user interaction with the error information
315
+ # Ensure that identified_fields is defined before using it in user interaction
316
+ if 'identified_fields' in locals():
317
+ _ = user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
318
+ else:
319
+ print("Please ensure CSV headers match expected field names in config file, then re-run Medibot.")
File without changes