medicafe 0.240809.0__tar.gz → 0.240925.9__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 (57) hide show
  1. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediBot/MediBot.bat +56 -16
  2. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediBot/MediBot.py +90 -79
  3. medicafe-0.240925.9/MediBot/MediBot_Crosswalk_Library.py +590 -0
  4. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediBot/MediBot_Preprocessor.py +22 -14
  5. medicafe-0.240925.9/MediBot/MediBot_Preprocessor_lib.py +654 -0
  6. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediBot/MediBot_UI.py +25 -24
  7. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediBot/MediBot_dataformat_library.py +17 -25
  8. medicafe-0.240925.9/MediBot/MediBot_docx_decoder.py +460 -0
  9. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediBot/update_json.py +26 -1
  10. medicafe-0.240925.9/MediBot/update_medicafe.py +147 -0
  11. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink.py +93 -51
  12. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_837p_encoder.py +23 -23
  13. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_837p_encoder_library.py +141 -96
  14. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_API_Generator.py +1 -7
  15. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_API_v3.py +240 -59
  16. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_APIs.py +1 -2
  17. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_ClaimStatus.py +21 -6
  18. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_ConfigLoader.py +8 -8
  19. medicafe-0.240925.9/MediLink/MediLink_DataMgmt.py +635 -0
  20. medicafe-0.240925.9/MediLink/MediLink_Decoder.py +327 -0
  21. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_Deductible.py +7 -8
  22. medicafe-0.240925.9/MediLink/MediLink_Down.py +148 -0
  23. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_Gmail.py +2 -11
  24. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_Parser.py +63 -36
  25. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_UI.py +29 -24
  26. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_Up.py +12 -8
  27. {medicafe-0.240809.0 → medicafe-0.240925.9}/PKG-INFO +1 -1
  28. {medicafe-0.240809.0 → medicafe-0.240925.9}/medicafe.egg-info/PKG-INFO +1 -1
  29. {medicafe-0.240809.0 → medicafe-0.240925.9}/setup.py +1 -1
  30. medicafe-0.240809.0/MediBot/MediBot_Crosswalk_Library.py +0 -288
  31. medicafe-0.240809.0/MediBot/MediBot_Preprocessor_lib.py +0 -508
  32. medicafe-0.240809.0/MediBot/MediBot_docx_decoder.py +0 -303
  33. medicafe-0.240809.0/MediBot/update_medicafe.py +0 -57
  34. medicafe-0.240809.0/MediLink/MediLink_DataMgmt.py +0 -414
  35. medicafe-0.240809.0/MediLink/MediLink_Decoder.py +0 -165
  36. medicafe-0.240809.0/MediLink/MediLink_Down.py +0 -153
  37. {medicafe-0.240809.0 → medicafe-0.240925.9}/LICENSE +0 -0
  38. {medicafe-0.240809.0 → medicafe-0.240925.9}/MANIFEST.in +0 -0
  39. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediBot/MediBot_Charges.py +0 -0
  40. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediBot/MediBot_Post.py +0 -0
  41. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediBot/PDF_to_CSV_Cleaner.py +0 -0
  42. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediBot/__init__.py +0 -0
  43. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_API_v2.py +0 -0
  44. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_Mailer.py +0 -0
  45. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_Scan.py +0 -0
  46. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_Scheduler.py +0 -0
  47. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/MediLink_batch.bat +0 -0
  48. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/Soumit_api.py +0 -0
  49. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/__init__.py +0 -0
  50. {medicafe-0.240809.0 → medicafe-0.240925.9}/MediLink/test.py +0 -0
  51. {medicafe-0.240809.0 → medicafe-0.240925.9}/README.md +0 -0
  52. {medicafe-0.240809.0 → medicafe-0.240925.9}/medicafe.egg-info/SOURCES.txt +0 -0
  53. {medicafe-0.240809.0 → medicafe-0.240925.9}/medicafe.egg-info/dependency_links.txt +0 -0
  54. {medicafe-0.240809.0 → medicafe-0.240925.9}/medicafe.egg-info/not-zip-safe +0 -0
  55. {medicafe-0.240809.0 → medicafe-0.240925.9}/medicafe.egg-info/requires.txt +0 -0
  56. {medicafe-0.240809.0 → medicafe-0.240925.9}/medicafe.egg-info/top_level.txt +0 -0
  57. {medicafe-0.240809.0 → medicafe-0.240925.9}/setup.cfg +0 -0
@@ -1,3 +1,4 @@
1
+ ::MediBot.bat
1
2
  @echo off
2
3
  setlocal enabledelayedexpansion
3
4
 
@@ -64,17 +65,17 @@ if not exist "%config_file%" (
64
65
 
65
66
  :: Check if the file exists and attempt to move it
66
67
  :: Implementing a check with copy as a fallback if move fails
67
- echo Checking for the upgrade script...
68
- if exist "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" (
69
- echo Found upgrade_medicafe.py. Attempting to move...
70
- move "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" "F:\Medibot\upgrade_medicafe.py" >nul 2>&1
68
+ echo Checking for the update script...
69
+ if exist "C:\Python34\Lib\site-packages\MediBot\update_medicafe.py" (
70
+ echo Found update_medicafe.py. Attempting to move...
71
+ move "C:\Python34\Lib\site-packages\MediBot\update_medicafe.py" "F:\Medibot\update_medicafe.py" >nul 2>&1
71
72
  if %errorlevel% neq 0 (
72
73
  echo Move failed. Attempting copy and delete as fallback...
73
- copy "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" "F:\Medibot\upgrade_medicafe.py" >nul 2>&1
74
+ copy "C:\Python34\Lib\site-packages\MediBot\update_medicafe.py" "F:\Medibot\update_medicafe.py" >nul 2>&1
74
75
  if %errorlevel% neq 0 (
75
76
  echo Copy failed. Error Level: %errorlevel%
76
77
  ) else (
77
- del "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" >nul 2>&1
78
+ del "C:\Python34\Lib\site-packages\MediBot\update_medicafe.py" >nul 2>&1
78
79
  if %errorlevel% neq 0 (
79
80
  echo Delete failed. Manual cleanup may be required.
80
81
  ) else (
@@ -85,26 +86,38 @@ if exist "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" (
85
86
  echo File moved successfully.
86
87
  )
87
88
  ) else (
88
- echo upgrade_medicafe.py not detected. Check path and filename.
89
+ echo update_medicafe.py not detected. Checking for existing update_medicafe.py in F:\Medibot...
90
+ if exist "F:\Medibot\update_medicafe.py" (
91
+ echo update_medicafe.py already exists in F:\Medibot. No action needed.
92
+ ) else (
93
+ echo update_medicafe.py not detected in either location. Check path and filename.
94
+ )
89
95
  )
90
96
 
91
97
  :: Main menu
92
98
  :main_menu
93
99
  cls
94
- echo version: %medicafe_version%
100
+ echo Version: %medicafe_version%
95
101
  echo --------------------------------------------------------------
96
102
  echo .//* Welcome to MediCafe *\\.
97
103
  echo --------------------------------------------------------------
98
104
  echo.
99
105
  echo Please select an option:
106
+ echo.
100
107
  if "!internet_available!"=="1" (
101
- echo 1. Check for MediCafe Package Updates
108
+ echo 1. Update MediCafe
109
+ echo.
102
110
  echo 2. Download Email de Carol
111
+ echo.
103
112
  echo 3. MediLink Claims
104
- echo 4. United Claims Status
105
- echo 5. United Deductible
113
+ echo.
114
+ echo 4. ^[United^] Claims Status
115
+ echo.
116
+ echo 5. ^[United^] Deductible
117
+ echo.
106
118
  )
107
119
  echo 6. Run MediBot
120
+ echo.
108
121
  echo 7. Exit
109
122
  echo.
110
123
  set /p choice=Enter your choice:
@@ -124,11 +137,12 @@ if "!internet_available!"=="0" (
124
137
  goto main_menu
125
138
  )
126
139
  echo Checking for MediCafe package updates. Please wait...
127
- start cmd /c py "%upgrade_medicafe%" > upgrade_log.txt 2>&1 && (
140
+ start "Medicafe Update" cmd /c py "%upgrade_medicafe%" %package_version% > upgrade_log.txt 2>&1 && (
128
141
  echo %DATE% %TIME% Upgrade initiated. >> "%temp_file%"
129
142
  echo Exiting batch to complete the upgrade.
130
143
  ) || (
131
144
  echo %DATE% %TIME% Update failed. Check logs. >> upgrade_log.txt
145
+ echo Upgrade failed. Check upgrade_log.txt for details.
132
146
  )
133
147
  exit /b
134
148
 
@@ -200,7 +214,7 @@ if errorlevel 1 echo Failed to check United Deductible.
200
214
  pause
201
215
  goto main_menu
202
216
 
203
- :: Process CSV Files
217
+ :: Process CSV Files and Validate Against Config
204
218
  :process_csvs
205
219
  for /f "tokens=1-5 delims=/: " %%a in ('echo %time%') do (
206
220
  set "hour=%%a"
@@ -220,13 +234,39 @@ for /f "delims=" %%a in ('dir /b /a-d /o-d "%source_folder%\*.csv" 2^>nul') do (
220
234
  echo Found New CSV Files...
221
235
  goto process_found_csv
222
236
  )
223
- ::echo CSV Check Complete.
224
237
  goto :eof
225
238
 
226
239
  :process_found_csv
227
- echo Processing CSVs...
240
+ echo Validating latest CSV with config file...
241
+ :: Run Python script to get current CSV path from JSON
242
+ for /f "delims=" %%a in ('python "%python_script%" "%config_file%"') do (
243
+ set "current_csv=%%a"
244
+ )
245
+
246
+ :: Extract filenames from paths
247
+ for %%f in ("!current_csv!") do set "current_csv_name=%%~nxf"
248
+ for %%f in ("%target_folder%\!latest_csv!") do set "latest_csv_name=%%~nxf"
249
+
250
+ :: Compare the paths and prompt user if necessary
251
+ if not "!current_csv_name!"=="!latest_csv_name!" (
252
+ echo ALERT: Config file CSV path differs from the latest CSV. This can happen if a new CSV is downloaded.
253
+ echo Current CSV: !current_csv_name!
254
+ echo Latest CSV: !latest_csv_name!
255
+ set /p update_choice="Do you want to update to the latest CSV? (Y/N): "
256
+ if /i "!update_choice!"=="Y" (
257
+ echo Updating config file with latest CSV...
258
+ py "%python_script%" "%config_file%" "%target_folder%\!latest_csv!"
259
+ echo Config file updated.
260
+ ) else (
261
+ echo Using existing CSV path from config.
262
+ )
263
+ ) else (
264
+ echo CSV path in config matches the latest CSV.
265
+ )
266
+
228
267
  move "%source_folder%\!latest_csv!" "%target_folder%\SX_CSV_!timestamp!.csv"
229
268
  set "new_csv_path=%target_folder%\SX_CSV_!timestamp!.csv"
269
+ echo Processing CSV...
230
270
  py "%python_script%" "%config_file%" "!new_csv_path!"
231
271
  echo CSV Processor Complete...
232
272
  goto :eof
@@ -235,4 +275,4 @@ goto :eof
235
275
  :end_script
236
276
  echo Exiting MediCafe.
237
277
  pause
238
- exit /b
278
+ exit /b
@@ -1,8 +1,5 @@
1
- import subprocess
2
- import os
3
- import tempfile
4
- import traceback
5
- import re #for addresses
1
+ #MediBot.py
2
+ import subprocess, os, tempfile, traceback, re, sys
6
3
  from collections import OrderedDict
7
4
  import MediBot_dataformat_library
8
5
  import MediBot_Preprocessor
@@ -10,7 +7,6 @@ from MediBot_Preprocessor_lib import initialize, AHK_EXECUTABLE, CSV_FILE_PATH,
10
7
  from MediBot_UI import app_control, manage_script_pause, user_interaction
11
8
 
12
9
  # Add parent directory of the project to the Python path
13
- import sys
14
10
  project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
15
11
  sys.path.append(project_dir)
16
12
 
@@ -22,6 +18,18 @@ except ImportError:
22
18
  from MediBot import MediBot_Crosswalk_Library
23
19
  crosswalk_update = MediBot_Crosswalk_Library.crosswalk_update
24
20
 
21
+ try:
22
+ from MediLink.MediLink_API_v3 import APIClient
23
+ except ImportError as e:
24
+ raise ImportError("Failed to import APIClient from MediLink.MediLink_API_v3. "
25
+ "Ensure the MediLink_API_v3 module is installed and accessible.") from e
26
+
27
+ # After successful import
28
+ try:
29
+ api_client = APIClient() # Pass necessary arguments if required
30
+ except Exception as e:
31
+ raise RuntimeError("Failed to instantiate APIClient. Ensure correct initialization parameters.") from e
32
+
25
33
  def identify_field(header, field_mapping):
26
34
  for medisoft_field, patterns in field_mapping.items():
27
35
  for pattern in patterns:
@@ -34,30 +42,29 @@ def identify_field(header, field_mapping):
34
42
 
35
43
  # Function to execute an AutoHotkey script
36
44
  def run_ahk_script(script_content):
37
- temp_script_name = None
45
+ temp_script_name = None # Initialize variable to hold the name of the temporary script file
38
46
  try:
39
47
  # 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()
48
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.ahk', encoding='utf-8') as temp_script:
49
+ temp_script_name = temp_script.name # Store the name of the temporary script file
50
+ temp_script.write(script_content) # Write the script content to the temporary file
51
+ temp_script.flush() # Ensure the file is written to disk
44
52
  # Attempt to run the AHK script
45
- subprocess.check_call([AHK_EXECUTABLE, temp_script_name])
53
+ subprocess.check_call([AHK_EXECUTABLE, temp_script_name]) # Execute the AHK script using the AutoHotkey executable
46
54
  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)
55
+ print("AHK script failed with exit status: {}".format(e.returncode)) # Log the exit status of the failed script
56
+ print("Output from AHK script: {}".format(e.output)) # Log the output from the failed script
50
57
  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
58
+ print("An unexpected error occurred while running the AHK script: {}".format(e)) # Log any unexpected errors
59
+ traceback.print_exc() # Print the full traceback for debugging purposes
54
60
  finally:
55
61
  # Delete the temporary script file
56
62
  if temp_script_name:
57
63
  try:
58
- os.unlink(temp_script_name)
64
+ os.unlink(temp_script_name) # Attempt to delete the temporary script file
59
65
  except OSError as e:
60
- print("Error deleting temporary script file:", e)
66
+ print("Error deleting temporary script file: {}".format(e)) # Log any errors encountered while deleting the file
67
+ # Future Improvement: Implement a cleanup mechanism to handle orphaned temporary files
61
68
 
62
69
  # Global variable to store the last processed entry
63
70
  last_processed_entry = None
@@ -68,23 +75,35 @@ def process_field(medisoft_field, csv_row, parsed_address_components, reverse_ma
68
75
  global last_processed_entry
69
76
 
70
77
  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))
78
+ # Attempt to retrieve the value for the current medisoft_field from parsed_address_components
79
+ value = parsed_address_components.get(medisoft_field, '') if medisoft_field in parsed_address_components else ''
80
+
81
+ # If no value is found, check if there is a fixed value available for this field
82
+ if not value:
83
+ if medisoft_field in fixed_values:
84
+ value = fixed_values[medisoft_field][0] # Use the fixed value if available
85
+
86
+ # If still no value, check if the field is present in the reverse mapping
87
+ if not value and medisoft_field in reverse_mapping:
88
+ # Retrieve the corresponding CSV header from the reverse mapping
79
89
  csv_header = reverse_mapping[medisoft_field]
80
- value = csv_row.get(csv_header, '')
90
+ value = csv_row.get(csv_header, '') # Get the value from the CSV row using the header
91
+
92
+ # Log the detected field and its value after assignment
93
+ MediLink_ConfigLoader.log("Detected {}: {}".format(medisoft_field, value), level="DEBUG")
81
94
 
82
- formatted_value = MediBot_dataformat_library.format_data(medisoft_field, value, csv_data, reverse_mapping, parsed_address_components) if value else 'Send, {Enter}'
95
+ # Format the value for the AutoHotkey script, or default to sending an Enter key if no value is found
96
+ formatted_value = (MediBot_dataformat_library.format_data(medisoft_field, value, csv_data, reverse_mapping, parsed_address_components)
97
+ if value else 'Send, {Enter}')
98
+
99
+ # Execute the AutoHotkey script with the formatted value
83
100
  run_ahk_script(formatted_value)
84
101
 
102
+ # Update the last processed entry with the current field and its value
85
103
  last_processed_entry = (medisoft_field, value)
86
- return 'continue', last_processed_entry
104
+ return 'continue', last_processed_entry # Indicate to continue processing
87
105
  except Exception as e:
106
+ # Handle any exceptions that occur during processing
88
107
  return handle_error(e, medisoft_field, last_processed_entry, csv_data)
89
108
 
90
109
  def handle_error(error, medisoft_field, last_processed_entry, csv_data):
@@ -176,23 +195,38 @@ class ExecutionState:
176
195
  def __init__(self, config_path, crosswalk_path) -> None:
177
196
  try:
178
197
  config, crosswalk = MediLink_ConfigLoader.load_configuration(config_path, crosswalk_path)
198
+ MediLink_ConfigLoader.log("Loaded configuration: {}".format(config), level="DEBUG")
199
+ MediLink_ConfigLoader.log("Loaded crosswalk: {}".format(crosswalk), level="DEBUG")
179
200
  self.verify_config_type(config)
180
201
  self.crosswalk = crosswalk
181
202
  self.config = config
182
203
  MediLink_ConfigLoader.log("Config loaded successfully...")
204
+
205
+ # Instantiate APIClient
206
+ self.api_client = APIClient() # Pass required arguments if any
207
+
208
+ # Simplified isinstance check
209
+ if not isinstance(self.api_client, APIClient):
210
+ raise TypeError("MediBot Error: api_client must be an instance of APIClient.")
183
211
 
184
- crosswalk_update(config, crosswalk)
185
- MediLink_ConfigLoader.log("Crosswalk update complete...")
186
-
187
- initialize(config)
188
- MediLink_ConfigLoader.log("Constants initialized...")
189
-
212
+ # Log before calling crosswalk_update
213
+ MediLink_ConfigLoader.log("Updating crosswalk with client and config...", level="INFO")
214
+ update_successful = crosswalk_update(self.api_client, config, crosswalk) # Ensure crosswalk_update uses the instance. TODO We need an internet-disabled version of this.
215
+ if update_successful:
216
+ MediLink_ConfigLoader.log("Crosswalk update completed successfully.", level="INFO")
217
+ print("Crosswalk update completed successfully.")
218
+ else:
219
+ MediLink_ConfigLoader.log("Crosswalk update failed.", level="ERROR")
220
+ print("Crosswalk update failed.")
221
+
190
222
  except Exception as e:
223
+ MediLink_ConfigLoader.log("MediBot: Failed to load or update configuration: {}".format(e), level="ERROR")
191
224
  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
225
+ raise # Re-throwing the exception or using a more sophisticated error handling mechanism might be needed
193
226
  # Handle the exception somehow (e.g., retry, halt, log)??
194
227
 
195
228
  def verify_config_type(self, config):
229
+ MediLink_ConfigLoader.log("Verifying configuration type: {}".format(type(config)), level="DEBUG")
196
230
  if not isinstance(config, (dict, OrderedDict)):
197
231
  raise TypeError("Error: Configuration must be a dictionary or an OrderedDict. Check unpacking.")
198
232
 
@@ -201,19 +235,13 @@ if __name__ == "__main__":
201
235
  e_state = None
202
236
  try:
203
237
  print("Please wait...")
204
- # Default paths
238
+ # Default paths for configuration and crosswalk files
205
239
  default_config_path = os.path.join(os.path.dirname(__file__), '..', 'json', 'config.json')
206
240
  default_crosswalk_path = os.path.join(os.path.dirname(__file__), '..', 'json', 'crosswalk.json')
207
241
 
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
242
+ # Determine paths based on command-line arguments or use defaults
243
+ config_path = sys.argv[1] if len(sys.argv) > 1 else default_config_path
244
+ crosswalk_path = sys.argv[2] if len(sys.argv) > 2 else default_crosswalk_path
217
245
 
218
246
  e_state = ExecutionState(config_path, crosswalk_path)
219
247
 
@@ -221,37 +249,34 @@ if __name__ == "__main__":
221
249
  MediLink_ConfigLoader.log("Loading CSV Data...", level="INFO")
222
250
  csv_data = load_csv_data(CSV_FILE_PATH)
223
251
 
224
- # Pre-process CSV data to add combined fields & crosswalk values.
252
+ # Pre-process CSV data to add combined fields & crosswalk values
225
253
  print("Pre-Processing CSV...")
226
254
  MediLink_ConfigLoader.log("Pre-processing CSV Data...", level="INFO")
227
255
  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.
256
+ headers = csv_data[0].keys() # Ensure all headers are in place
230
257
 
231
258
  print("Performing Intake Scan...")
232
259
  MediLink_ConfigLoader.log("Performing Intake Scan...", level="INFO")
233
- # identified_fields is an OrderedDict
234
260
  identified_fields = MediBot_Preprocessor.intake_scan(headers, field_mapping)
235
261
 
236
262
  # Reverse the identified_fields mapping for lookup
237
263
  reverse_mapping = {v: k for k, v in identified_fields.items()}
238
- # MediLink_ConfigLoader.log("Reverse Mapping: {}".format(reverse_mapping))
239
-
264
+
240
265
  # CSV Patient Triage
241
266
  interaction_mode = 'triage' # Start in triage mode
242
267
  error_message = "" # This will be filled if an error has occurred
243
- #print("Debug - Identified fields mapping (main): {}".format(identified_fields)) # Debug Line
244
268
 
245
269
  print("Load Complete...")
270
+ MediLink_ConfigLoader.log("Load Complete event triggered. Clearing console. Displaying Menu...", level="INFO")
246
271
  _ = os.system('cls')
247
272
 
248
273
  proceed, selected_patient_ids, selected_indices, fixed_values = user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
249
274
 
250
275
  if proceed:
251
- # Filter csv_data for selected patients from Triage mode.
276
+ # Filter csv_data for selected patients from Triage mode
252
277
  csv_data = [row for index, row in enumerate(csv_data) if index in selected_indices]
253
278
 
254
- # Check if MAPAT_MED_PATH is missing or blank
279
+ # Check if MAPAT_MED_PATH is missing or invalid
255
280
  if not app_control.get_mapat_med_path() or not os.path.exists(app_control.get_mapat_med_path()):
256
281
  print("Warning: MAPAT.MED PATH is missing or invalid. Please check the path configuration.")
257
282
 
@@ -260,9 +285,8 @@ if __name__ == "__main__":
260
285
 
261
286
  if existing_patients:
262
287
  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
- # Find the corresponding rows in csv_data to get the surgery dates and store them along with patient info
288
+
289
+ # Collect surgery dates and patient info for existing patients
266
290
  patient_info = []
267
291
  for patient_id, patient_name in existing_patients:
268
292
  surgery_date = next((row.get('Surgery Date', 'Unknown Date') for row in csv_data if row.get(reverse_mapping['Patient ID #2']) == patient_id), 'Unknown Date')
@@ -273,37 +297,25 @@ if __name__ == "__main__":
273
297
 
274
298
  # Print the sorted patient info
275
299
  for index, (surgery_date, patient_name, patient_id) in enumerate(patient_info):
276
- print("{0:03d}: {3:%m-%d} (ID: {2}) {1} ".format(index + 1, patient_name, patient_id, surgery_date))
300
+ print("{:03d}: {} (ID: {}) {}".format(index + 1, surgery_date.strftime('%m-%d'), patient_id, patient_name))
277
301
 
278
302
  # Update csv_data to exclude existing patients
279
- # TODO This now has to be updated to handle patients that exist but need new charges added.
303
+ # TODO: Update this logic to handle patients that exist but need new charges added.
280
304
  csv_data = [row for row in csv_data if row[reverse_mapping['Patient ID #2']] in patients_to_process]
281
305
  else:
282
306
  print("\nSelected patient(s) are NEW patients and will be processed.")
283
307
 
308
+ # Check if there are patients left to process
284
309
  if len(patients_to_process) == 0:
285
310
  proceed = input("\nAll patients have been processed. Continue anyway?: ").lower().strip() in ['yes', 'y']
286
311
  else:
287
312
  proceed = input("\nDo you want to proceed with the {} remaining patient(s)? (yes/no): ".format(len(patients_to_process))).lower().strip() in ['yes', 'y']
288
313
 
289
- # TODO Here is where we need to add the step where we move to MediBot_Charges.
290
- # The return is an enriched dataset to be picked up by medibot which means we need to return:
314
+ # TODO: Here is where we need to add the step where we move to MediBot_Charges.
315
+ # The return is an enriched dataset to be picked up by MediBot which means we need to return:
291
316
  # csv_data, field_mapping, reverse_mapping, and fixed_values.
292
317
 
293
318
  if proceed:
294
-
295
- # Would be nice to have some kind of self-test here.
296
- # print("\nDebug - Starting AHK script. Reload AHK if failed...")
297
- # try:
298
- # subprocess.call([AHK_EXECUTABLE, r"G:\My Drive\CocoWave\XP typing bot\notepad_test.ahk"])
299
- # run_ahk_script('MsgBox, Test AHK Script Execution')
300
- # except subprocess.CalledProcessError as e:
301
- # print("Error running AHK script. Please reload AHK and try again. Error: {}".format(e))
302
- # exit(1)
303
- # except Exception as e:
304
- # print("An unexpected error occurred while running the AHK script: {}".format(e))
305
- # exit(1)
306
-
307
319
  print("\nRemember, when in Medisoft:")
308
320
  print(" Press 'F8' to create a New Patient.")
309
321
  print(" Press 'F12' to begin data entry.")
@@ -321,9 +333,8 @@ if __name__ == "__main__":
321
333
  if e_state:
322
334
  interaction_mode = 'error' # Switch to error mode
323
335
  error_message = str(e) # Capture the error message
324
- print("An error occurred while running MediBot: {0}".format(e))
336
+ print("An error occurred while running MediBot: {}".format(e))
325
337
  # Handle the error by calling user interaction with the error information
326
- # Ensure that identified_fields is defined before using it in user interaction
327
338
  if 'identified_fields' in locals():
328
339
  _ = user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
329
340
  else: