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

Files changed (38) hide show
  1. MediBot/MediBot.bat +174 -38
  2. MediBot/MediBot.py +80 -77
  3. MediBot/MediBot_Charges.py +0 -28
  4. MediBot/MediBot_Crosswalk_Library.py +281 -0
  5. MediBot/MediBot_Post.py +0 -0
  6. MediBot/MediBot_Preprocessor.py +138 -211
  7. MediBot/MediBot_Preprocessor_lib.py +496 -0
  8. MediBot/MediBot_UI.py +80 -35
  9. MediBot/MediBot_dataformat_library.py +79 -35
  10. MediBot/MediBot_docx_decoder.py +295 -0
  11. MediBot/update_medicafe.py +46 -8
  12. MediLink/MediLink.py +207 -108
  13. MediLink/MediLink_837p_encoder.py +299 -214
  14. MediLink/MediLink_837p_encoder_library.py +445 -245
  15. MediLink/MediLink_API_v2.py +174 -0
  16. MediLink/MediLink_APIs.py +139 -0
  17. MediLink/MediLink_ConfigLoader.py +44 -32
  18. MediLink/MediLink_DataMgmt.py +297 -89
  19. MediLink/MediLink_Decoder.py +63 -0
  20. MediLink/MediLink_Down.py +73 -102
  21. MediLink/MediLink_ERA_decoder.py +4 -4
  22. MediLink/MediLink_Gmail.py +479 -4
  23. MediLink/MediLink_Mailer.py +0 -0
  24. MediLink/MediLink_Parser.py +111 -0
  25. MediLink/MediLink_Scan.py +0 -0
  26. MediLink/MediLink_Scheduler.py +2 -131
  27. MediLink/MediLink_StatusCheck.py +0 -4
  28. MediLink/MediLink_UI.py +87 -27
  29. MediLink/MediLink_Up.py +301 -45
  30. MediLink/MediLink_batch.bat +1 -1
  31. MediLink/test.py +74 -0
  32. medicafe-0.240613.0.dist-info/METADATA +55 -0
  33. medicafe-0.240613.0.dist-info/RECORD +43 -0
  34. {medicafe-0.240419.2.dist-info → medicafe-0.240613.0.dist-info}/WHEEL +5 -5
  35. medicafe-0.240419.2.dist-info/METADATA +0 -19
  36. medicafe-0.240419.2.dist-info/RECORD +0 -32
  37. {medicafe-0.240419.2.dist-info → medicafe-0.240613.0.dist-info}/LICENSE +0 -0
  38. {medicafe-0.240419.2.dist-info → medicafe-0.240613.0.dist-info}/top_level.txt +0 -0
MediBot/MediBot.bat CHANGED
@@ -8,63 +8,199 @@ set "config_file=F:\Medibot\json\config.json"
8
8
  set "python_script=C:\Python34\Lib\site-packages\MediBot\update_json.py"
9
9
  set "python_script2=C:\Python34\Lib\site-packages\MediBot\Medibot.py"
10
10
  set "medicafe_package=medicafe"
11
- set "upgrade_medicafe=F:\Medibot\upgrade_medicafe.py"
12
-
13
- :: Set PYTHONWARNINGS environment variable to ignore deprecation warnings
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="
14
15
  set PYTHONWARNINGS=ignore
15
16
 
16
- :: Upgrade Medicafe package
17
- py "%upgrade_medicafe%"
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
+ )
18
23
 
19
- :: Check for the latest CSV file in source folder
20
- set "latest_csv="
21
- for /f "delims=" %%a in ('dir /b /a-d /o-d "%source_folder%\*.csv" 2^>nul') do (
22
- set "latest_csv=%%a"
23
- goto :found_latest_csv
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
24
33
  )
25
34
 
26
- :: If no CSV found in source folder, check target folder
27
- echo No CSV file found in "%source_folder%".
28
- for /f "delims=" %%a in ('dir /b /a-d /o-d "%target_folder%\*.csv" 2^>nul') do (
29
- set "latest_csv=%%a"
30
- echo Using latest processed file in CSV folder: !latest_csv!
31
- goto :found_latest_csv
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%
32
44
  )
33
45
 
34
- :found_latest_csv
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
+ )
35
55
 
36
- :: If no CSV found in either folder, end the script
37
- if not defined latest_csv (
38
- echo No CSV file found in either folder.
39
- goto :end_script
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
40
61
  )
41
62
 
42
- :: Display the name of the found CSV file to the user
43
- echo Found CSV file: !latest_csv!
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
+ )
44
88
 
45
- :: Get the current date in MMDDYY format
46
- for /f "tokens=1-3 delims=/" %%a in ("%date%") do (
47
- set "month=%%a"
48
- set "day=%%b"
49
- set "year=%%c"
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
50
119
  )
51
- set "datestamp=!month!!day!!year:~2,2!"
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
52
128
 
53
- :: Move and rename the CSV file only if found in source folder
54
- if exist "%source_folder%\!latest_csv!" (
55
- move "%source_folder%\!latest_csv!" "%target_folder%\SX_CSV_!datestamp!.csv"
56
- set "new_csv_path=%target_folder%\SX_CSV_!datestamp!.csv"
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
57
141
  ) else (
58
- set "new_csv_path=%target_folder%\!latest_csv!"
142
+ echo Calling CSV Processor...
143
+ call :process_csvs
59
144
  )
145
+ goto main_menu
60
146
 
147
+ :: Run MediBot Flow
148
+ :medibot_flow
149
+ call :process_csvs
150
+ cls
61
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
62
156
 
63
- :: Call Python script to update the JSON file
64
- py "%python_script%" "%config_file%" "!new_csv_path!"
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
65
170
 
66
- :: Execute the second Python script
67
- py "%python_script2%" "%config_file%"
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
68
201
 
202
+ :: Exit Script
69
203
  :end_script
204
+ echo Exiting MediCafe.
70
205
  pause
206
+ exit /b
MediBot/MediBot.py CHANGED
@@ -4,10 +4,10 @@ import tempfile
4
4
  import traceback
5
5
  import re #for addresses
6
6
  from collections import OrderedDict
7
- import MediBot_UI
8
7
  import MediBot_dataformat_library
9
8
  import MediBot_Preprocessor
10
- from MediBot_Preprocessor import initialize, AHK_EXECUTABLE, CSV_FILE_PATH, field_mapping
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
11
 
12
12
  # Add parent directory of the project to the Python path
13
13
  import sys
@@ -16,39 +16,11 @@ sys.path.append(project_dir)
16
16
 
17
17
  from MediLink import MediLink_ConfigLoader
18
18
 
19
- """
20
- # Development Task List for MediBot
21
-
22
- Error Handling Improvements
23
- - [ ] Develop a centralized error handling and logging mechanism for improved troubleshooting.
24
- - [ ] Implement validation checks during patient data entry to prevent submission of incomplete or incorrect records.
25
-
26
- Insurance Mode Adjustments
27
- - [ ] Integrate a comprehensive list of insurance company codes for automatic selection.
28
- - [ ] Automate insurance-specific data entry adjustments, such as character replacements specific to Medicare.
29
-
30
- Diagnosis Entry
31
- - [ ] Automate data extraction from Surgery Schedule to import to CSV a column indicating diagnosis code per px.
32
-
33
- Script Efficiency and Reliability
34
- - [ ] Ensure robust handling of Medisoft's field navigation quirks, particularly for fields that are skipped or require special access.
35
-
36
- Documentation and Support
37
- - [ ] Create detailed documentation for setup, configuration, and usage of the script.
38
- - [ ] Establish a support channel for users to report issues or request features.
39
-
40
- Future Directions
41
- - [ ] Consider developing a graphical user interface (GUI) for non-technical users for easier script management and execution.
42
-
43
- Medisoft Field Navigation:
44
- Investigate and optimize navigation for fields that Medisoft skips or requires backward navigation to access.
45
-
46
- Insurance Mode Features:
47
- Evaluate the feasibility and implement the use of the F6 search for insurance address verification, enhancing user verification processes.
48
-
49
- Error Handling and Logging:
50
- Implement a check for AHK script execution status, providing feedback or troubleshooting steps if the script encounters issues.
51
- """
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
52
24
 
53
25
  def identify_field(header, field_mapping):
54
26
  for medisoft_field, patterns in field_mapping.items():
@@ -102,6 +74,8 @@ def process_field(medisoft_field, csv_row, parsed_address_components, reverse_ma
102
74
  elif medisoft_field in fixed_values:
103
75
  value = fixed_values[medisoft_field][0] # Use the fixed value
104
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))
105
79
  csv_header = reverse_mapping[medisoft_field]
106
80
  value = csv_row.get(csv_header, '')
107
81
 
@@ -114,10 +88,11 @@ def process_field(medisoft_field, csv_row, parsed_address_components, reverse_ma
114
88
  return handle_error(e, medisoft_field, last_processed_entry, csv_data)
115
89
 
116
90
  def handle_error(error, medisoft_field, last_processed_entry, csv_data):
91
+ MediLink_ConfigLoader.log("Error in process_field: ", e)
117
92
  print("An error occurred while processing {0}: {1}".format(medisoft_field, error))
118
93
  # Assuming the interaction mode is 'error' in this case
119
94
  interaction_mode = 'error'
120
- response = MediBot_UI.user_interaction(csv_data, interaction_mode, error, reverse_mapping)
95
+ response = user_interaction(csv_data, interaction_mode, error, reverse_mapping)
121
96
  return response, last_processed_entry
122
97
 
123
98
  # iterating through each field defined in the field_mapping.
@@ -125,7 +100,7 @@ def iterate_fields(csv_row, field_mapping, parsed_address_components, reverse_ma
125
100
  global last_processed_entry
126
101
  # Check for user action at the start of each field processing
127
102
  for medisoft_field in field_mapping.keys():
128
- action = MediBot_UI.manage_script_pause(csv_data,'',reverse_mapping) # per-field pause availability. Necessary to provide frequent opportunities for the user to pause the script.
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.
129
104
  if action != 0: # If action is either 'Retry' (-1) or 'Skip' (1)
130
105
  return action # Break out and pass the action up
131
106
 
@@ -135,8 +110,8 @@ def iterate_fields(csv_row, field_mapping, parsed_address_components, reverse_ma
135
110
  return 0 # Default action to continue
136
111
 
137
112
  def data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values):
138
- global last_processed_entry, parsed_address_components, script_paused
139
- script_paused = False
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?
140
115
  error_message = '' # Initialize error_message once
141
116
  current_row_index = 0
142
117
 
@@ -144,10 +119,10 @@ def data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values):
144
119
  row = csv_data[current_row_index]
145
120
 
146
121
  # Handle script pause at the start of each row (patient record).
147
- MediBot_UI.manage_script_pause(csv_data, error_message, reverse_mapping)
122
+ manage_script_pause(csv_data, error_message, reverse_mapping)
148
123
  error_message = '' # Clear error message for the next iteration
149
124
 
150
- if script_paused:
125
+ if app_control.get_pause_status():
151
126
  continue # Skip processing this row if the script is paused
152
127
 
153
128
  # I feel like this is overwriting what would have already been idenfitied in the mapping.
@@ -157,12 +132,13 @@ def data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values):
157
132
 
158
133
  # Process each field in the row
159
134
  action = iterate_fields(row, field_mapping, parsed_address_components, reverse_mapping, csv_data, fixed_values)
160
- # TODO add a feature here where if you accidentally started overwriting a patient that you could go back 2 patients.
135
+ # TODO (Low) add a feature here where if you accidentally started overwriting a patient that you could go back 2 patients.
161
136
  # Need to tell the user which patient we're talking about because it won't be obvious anymore.
162
137
  if action == -1: # Retry
163
138
  continue # Remain on the current row.
164
139
  elif action == 1: # Skip
165
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.")
166
142
  print("Reached the end of the patient list. Looping back to the beginning.")
167
143
  current_row_index = 0 # Reset to the first row
168
144
  else:
@@ -173,9 +149,8 @@ def data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values):
173
149
  continue
174
150
 
175
151
  # Code to handle the end of a patient record
176
- # print("\nA patient record was completed.")
177
- script_paused = True
178
- # Handle script pause at the end of each row (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
179
154
  current_row_index += 1 # Move to the next row by default
180
155
 
181
156
  def open_medisoft(shortcut_path):
@@ -198,14 +173,24 @@ def cleanup():
198
173
  pass
199
174
 
200
175
  class ExecutionState:
201
- def __init__(self) -> None:
202
-
203
- #print("Loading Configuration...")
204
- config, _ = MediLink_ConfigLoader.load_configuration(config_path, crosswalk_path)
205
-
206
- self.verify_config_type(config)
207
- #print("Initializing Constants...")
208
- initialize(config)
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)??
209
194
 
210
195
  def verify_config_type(self, config):
211
196
  if not isinstance(config, (dict, OrderedDict)):
@@ -215,7 +200,8 @@ class ExecutionState:
215
200
  if __name__ == "__main__":
216
201
  e_state = None
217
202
  try:
218
- # Default paths
203
+ print("Please wait...")
204
+ # Default paths
219
205
  default_config_path = os.path.join(os.path.dirname(__file__), '..', 'json', 'config.json')
220
206
  default_crosswalk_path = os.path.join(os.path.dirname(__file__), '..', 'json', 'crosswalk.json')
221
207
 
@@ -229,39 +215,57 @@ if __name__ == "__main__":
229
215
  config_path = default_config_path
230
216
  crosswalk_path = default_crosswalk_path
231
217
 
232
- e_state = ExecutionState()
218
+ e_state = ExecutionState(config_path, crosswalk_path)
233
219
 
234
- #print("Loading CSV Data...")
235
- csv_data = MediBot_Preprocessor.load_csv_data(CSV_FILE_PATH)
220
+ print("Loading CSV Data...")
221
+ MediLink_ConfigLoader.log("Loading CSV Data...", level="INFO")
222
+ csv_data = load_csv_data(CSV_FILE_PATH)
236
223
 
237
- #print("Pre-processing CSV Data...")
238
- MediBot_Preprocessor.preprocess_csv_data(csv_data) # Pre-process CSV data to add combined fields
239
- headers = csv_data[0].keys() # Including Patient Name and Patient Address
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.
240
230
 
241
- #print("Performing Intake Scan...")
231
+ print("Performing Intake Scan...")
232
+ MediLink_ConfigLoader.log("Performing Intake Scan...", level="INFO")
242
233
  # identified_fields is an OrderedDict
243
234
  identified_fields = MediBot_Preprocessor.intake_scan(headers, field_mapping)
244
235
 
245
236
  # Reverse the identified_fields mapping for lookup
246
237
  reverse_mapping = {v: k for k, v in identified_fields.items()}
238
+ # MediLink_ConfigLoader.log("Reverse Mapping: {}".format(reverse_mapping))
247
239
 
248
240
  # CSV Patient Triage
249
241
  interaction_mode = 'triage' # Start in triage mode
250
242
  error_message = "" # This will be filled if an error has occurred
251
243
  #print("Debug - Identified fields mapping (main): {}".format(identified_fields)) # Debug Line
252
244
 
253
- proceed, selected_patient_ids, selected_indices, fixed_values = MediBot_UI.user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
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)
254
249
 
255
250
  if proceed:
256
251
  # Filter csv_data for selected patients from Triage mode.
257
252
  csv_data = [row for index, row in enumerate(csv_data) if index in selected_indices]
258
- existing_patients, patients_to_process = MediBot_Preprocessor.check_existing_patients(selected_patient_ids, MediBot_UI.MAPAT_MED_PATH)
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())
259
260
 
260
261
  if existing_patients:
261
- print("\nNOTE: The following patient(s) already EXIST in the system and \nwill be excluded from processing:")
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.
262
265
  for patient_id, patient_name in existing_patients:
263
266
  print("(ID: {0}) {1}".format(patient_id, patient_name))
264
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.
265
269
  csv_data = [row for row in csv_data if row[reverse_mapping['Patient ID #2']] in patients_to_process]
266
270
  else:
267
271
  print("\nSelected patient(s) are NEW patients and will be processed.")
@@ -271,6 +275,10 @@ if __name__ == "__main__":
271
275
  else:
272
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']
273
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
+
274
282
  if proceed:
275
283
 
276
284
  # Would be nice to have some kind of self-test here.
@@ -290,27 +298,22 @@ if __name__ == "__main__":
290
298
  print(" Press 'F12' to begin data entry.")
291
299
  print(" Press 'F11' at any time to Pause.")
292
300
  input("\n*** Press [Enter] when ready to begin! ***\n")
293
- open_medisoft(MediBot_UI.MEDISOFT_SHORTCUT)
294
- script_paused = True
295
- _ = MediBot_UI.manage_script_pause(csv_data, error_message, reverse_mapping)
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)
296
305
  data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values)
297
306
  cleanup()
298
307
  else:
299
- print("Data entry canceled by user.")
308
+ print("Data entry canceled by user. Exiting MediBot.")
300
309
  except Exception as e:
301
310
  if e_state:
302
311
  interaction_mode = 'error' # Switch to error mode
303
312
  error_message = str(e) # Capture the error message
304
- print("An error occurred: {0}".format(e))
313
+ print("An error occurred while running MediBot: {0}".format(e))
305
314
  # Handle the error by calling user interaction with the error information
306
315
  # Ensure that identified_fields is defined before using it in user interaction
307
316
  if 'identified_fields' in locals():
308
- _ = MediBot_UI.user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
317
+ _ = user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
309
318
  else:
310
- print("Please ensure CSV headers match expected field names in config file, then re-run Medibot.")
311
-
312
- # Performance: Process flow (25px - 13 min)
313
- # 2:00 Internet connect & Email
314
- # 6:00 6 px medicare
315
- # 1:00 menu handling for privado
316
- # 4:00 5 px privado
319
+ print("Please ensure CSV headers match expected field names in config file, then re-run Medibot.")
@@ -1,28 +0,0 @@
1
- """
2
- MediBot_Charges.py
3
-
4
- This module provides a helper function for MediBot.py, specifically designed to handle the charge entry process in Medisoft for patients undergoing cataract surgeries. Each patient typically undergoes procedures on both eyes, treated as separate procedures but often requiring price bundling to address patient preferences for consistent billing across both eyes.
5
-
6
- Key Features:
7
- - Handles up to 200 patients in a single batch, with typical usage around 20 patients.
8
- - Implements price bundling logic to ensure that if a patient has multiple procedures (one for each eye), the charges are balanced such that the total cost is evenly spread across both procedures. This approach aligns with patient expectations of receiving consistent charges for each eye.
9
- - Integrates pricing schedules from a configuration file for private insurance, which vary based on the duration of the procedure:
10
- - $450 for 1-15 minutes
11
- - $480 for 16-22 minutes
12
- - $510 for 23-27 minutes
13
- - $540 for 28-37 minutes
14
- - $580 for 37-59 minutes (59 minutes being the maximum allowed duration)
15
- - Special handling for Medicare patients, details of which are pending clarification.
16
-
17
- Limitations:
18
- - The bundling logic for commercial insurance billing is subject to the fulfillment of deductibles and other conditions, which do not necessarily synchronize with the timing of procedures for both eyes. The exact mechanics of this bundling under various conditions remain partially unspecified.
19
-
20
- Usage:
21
- - This module is intended to be used as part of the MediBot system, interfaced through MediBot.py, to automate the data entry and billing process in Medisoft for ophthalmology clinics, specifically those performing cataract surgeries.
22
-
23
- Note:
24
- - The exact implementation details for Medicare patients and the full logic for price bundling under all insurance conditions are yet to be finalized and documented.
25
-
26
- Date:
27
- - 4/16/24
28
- """