medicafe 0.240415.1__py3-none-any.whl → 0.240419.2__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.
- MediBot/MediBot.bat +70 -0
- MediBot/MediBot.py +316 -0
- MediBot/MediBot_Charges.py +28 -0
- MediBot/MediBot_Preprocessor.py +283 -0
- MediBot/MediBot_UI.py +190 -0
- MediBot/MediBot_dataformat_library.py +145 -0
- MediBot/MediPost.py +5 -0
- MediBot/PDF_to_CSV_Cleaner.py +211 -0
- MediBot/__init__.py +0 -0
- MediBot/update_json.py +43 -0
- MediBot/update_medicafe.py +19 -0
- MediLink/MediLink.py +277 -0
- MediLink/MediLink_277_decoder.py +92 -0
- MediLink/MediLink_837p_encoder.py +392 -0
- MediLink/MediLink_837p_encoder_library.py +679 -0
- MediLink/MediLink_ConfigLoader.py +69 -0
- MediLink/MediLink_DataMgmt.py +206 -0
- MediLink/MediLink_Down.py +151 -0
- MediLink/MediLink_ERA_decoder.py +192 -0
- MediLink/MediLink_Gmail.py +4 -0
- MediLink/MediLink_Scheduler.py +132 -0
- MediLink/MediLink_StatusCheck.py +4 -0
- MediLink/MediLink_UI.py +116 -0
- MediLink/MediLink_Up.py +117 -0
- MediLink/MediLink_batch.bat +7 -0
- MediLink/Soumit_api.py +22 -0
- MediLink/__init__.py +0 -0
- {medicafe-0.240415.1.dist-info → medicafe-0.240419.2.dist-info}/METADATA +19 -17
- medicafe-0.240419.2.dist-info/RECORD +32 -0
- {medicafe-0.240415.1.dist-info → medicafe-0.240419.2.dist-info}/WHEEL +5 -5
- medicafe-0.240419.2.dist-info/top_level.txt +2 -0
- medicafe-0.240415.1.dist-info/RECORD +0 -5
- medicafe-0.240415.1.dist-info/top_level.txt +0 -1
- {medicafe-0.240415.1.dist-info → medicafe-0.240419.2.dist-info}/LICENSE +0 -0
MediBot/MediBot.bat
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
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\upgrade_medicafe.py"
|
|
12
|
+
|
|
13
|
+
:: Set PYTHONWARNINGS environment variable to ignore deprecation warnings
|
|
14
|
+
set PYTHONWARNINGS=ignore
|
|
15
|
+
|
|
16
|
+
:: Upgrade Medicafe package
|
|
17
|
+
py "%upgrade_medicafe%"
|
|
18
|
+
|
|
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
|
+
)
|
|
25
|
+
|
|
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
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
:found_latest_csv
|
|
35
|
+
|
|
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
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
:: Display the name of the found CSV file to the user
|
|
43
|
+
echo Found CSV file: !latest_csv!
|
|
44
|
+
|
|
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"
|
|
50
|
+
)
|
|
51
|
+
set "datestamp=!month!!day!!year:~2,2!"
|
|
52
|
+
|
|
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"
|
|
57
|
+
) else (
|
|
58
|
+
set "new_csv_path=%target_folder%\!latest_csv!"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
echo Please wait...
|
|
62
|
+
|
|
63
|
+
:: Call Python script to update the JSON file
|
|
64
|
+
py "%python_script%" "%config_file%" "!new_csv_path!"
|
|
65
|
+
|
|
66
|
+
:: Execute the second Python script
|
|
67
|
+
py "%python_script2%" "%config_file%"
|
|
68
|
+
|
|
69
|
+
:end_script
|
|
70
|
+
pause
|
MediBot/MediBot.py
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
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_UI
|
|
8
|
+
import MediBot_dataformat_library
|
|
9
|
+
import MediBot_Preprocessor
|
|
10
|
+
from MediBot_Preprocessor import initialize, AHK_EXECUTABLE, CSV_FILE_PATH, field_mapping
|
|
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
|
+
"""
|
|
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
|
+
"""
|
|
52
|
+
|
|
53
|
+
def identify_field(header, field_mapping):
|
|
54
|
+
for medisoft_field, patterns in field_mapping.items():
|
|
55
|
+
for pattern in patterns:
|
|
56
|
+
if re.search(pattern, header, re.IGNORECASE):
|
|
57
|
+
return medisoft_field
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
# Add this print to a function that is calling identify_field
|
|
61
|
+
#print("Warning: No matching field found for CSV header '{}'".format(header))
|
|
62
|
+
|
|
63
|
+
# Function to execute an AutoHotkey script
|
|
64
|
+
def run_ahk_script(script_content):
|
|
65
|
+
temp_script_name = None
|
|
66
|
+
try:
|
|
67
|
+
# Create a temporary AHK script file
|
|
68
|
+
with tempfile.NamedTemporaryFile(delete=False, suffix='.ahk') as temp_script:
|
|
69
|
+
temp_script_name = temp_script.name
|
|
70
|
+
temp_script.write(script_content.encode('utf-8'))
|
|
71
|
+
temp_script.flush()
|
|
72
|
+
# Attempt to run the AHK script
|
|
73
|
+
subprocess.check_call([AHK_EXECUTABLE, temp_script_name])
|
|
74
|
+
except subprocess.CalledProcessError as e:
|
|
75
|
+
# This exception will catch any non-zero exit status from the AHK script
|
|
76
|
+
print("AHK script failed with exit status:", e.returncode)
|
|
77
|
+
print("Output from AHK script:", e.output)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
# This catches any other exceptions that may occur
|
|
80
|
+
print("An unexpected error occurred while running the AHK script:", e)
|
|
81
|
+
traceback.print_exc() # Print the stack trace of the exception
|
|
82
|
+
finally:
|
|
83
|
+
# Delete the temporary script file
|
|
84
|
+
if temp_script_name:
|
|
85
|
+
try:
|
|
86
|
+
os.unlink(temp_script_name)
|
|
87
|
+
except OSError as e:
|
|
88
|
+
print("Error deleting temporary script file:", e)
|
|
89
|
+
|
|
90
|
+
# Global variable to store the last processed entry
|
|
91
|
+
last_processed_entry = None
|
|
92
|
+
# Global variable to store temporarily parsed address components
|
|
93
|
+
parsed_address_components = {}
|
|
94
|
+
|
|
95
|
+
def process_field(medisoft_field, csv_row, parsed_address_components, reverse_mapping, csv_data, fixed_values):
|
|
96
|
+
global last_processed_entry
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
value = ''
|
|
100
|
+
if medisoft_field in parsed_address_components:
|
|
101
|
+
value = parsed_address_components.get(medisoft_field, '')
|
|
102
|
+
elif medisoft_field in fixed_values:
|
|
103
|
+
value = fixed_values[medisoft_field][0] # Use the fixed value
|
|
104
|
+
elif medisoft_field in reverse_mapping:
|
|
105
|
+
csv_header = reverse_mapping[medisoft_field]
|
|
106
|
+
value = csv_row.get(csv_header, '')
|
|
107
|
+
|
|
108
|
+
formatted_value = MediBot_dataformat_library.format_data(medisoft_field, value, csv_data, reverse_mapping, parsed_address_components) if value else 'Send, {Enter}'
|
|
109
|
+
run_ahk_script(formatted_value)
|
|
110
|
+
|
|
111
|
+
last_processed_entry = (medisoft_field, value)
|
|
112
|
+
return 'continue', last_processed_entry
|
|
113
|
+
except Exception as e:
|
|
114
|
+
return handle_error(e, medisoft_field, last_processed_entry, csv_data)
|
|
115
|
+
|
|
116
|
+
def handle_error(error, medisoft_field, last_processed_entry, csv_data):
|
|
117
|
+
print("An error occurred while processing {0}: {1}".format(medisoft_field, error))
|
|
118
|
+
# Assuming the interaction mode is 'error' in this case
|
|
119
|
+
interaction_mode = 'error'
|
|
120
|
+
response = MediBot_UI.user_interaction(csv_data, interaction_mode, error, reverse_mapping)
|
|
121
|
+
return response, last_processed_entry
|
|
122
|
+
|
|
123
|
+
# iterating through each field defined in the field_mapping.
|
|
124
|
+
def iterate_fields(csv_row, field_mapping, parsed_address_components, reverse_mapping, csv_data, fixed_values):
|
|
125
|
+
global last_processed_entry
|
|
126
|
+
# Check for user action at the start of each field processing
|
|
127
|
+
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.
|
|
129
|
+
if action != 0: # If action is either 'Retry' (-1) or 'Skip' (1)
|
|
130
|
+
return action # Break out and pass the action up
|
|
131
|
+
|
|
132
|
+
# Process each field in the row
|
|
133
|
+
_, last_processed_entry = process_field(medisoft_field, csv_row, parsed_address_components, reverse_mapping, csv_data, fixed_values)
|
|
134
|
+
|
|
135
|
+
return 0 # Default action to continue
|
|
136
|
+
|
|
137
|
+
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
|
|
140
|
+
error_message = '' # Initialize error_message once
|
|
141
|
+
current_row_index = 0
|
|
142
|
+
|
|
143
|
+
while current_row_index < len(csv_data):
|
|
144
|
+
row = csv_data[current_row_index]
|
|
145
|
+
|
|
146
|
+
# Handle script pause at the start of each row (patient record).
|
|
147
|
+
MediBot_UI.manage_script_pause(csv_data, error_message, reverse_mapping)
|
|
148
|
+
error_message = '' # Clear error message for the next iteration
|
|
149
|
+
|
|
150
|
+
if script_paused:
|
|
151
|
+
continue # Skip processing this row if the script is paused
|
|
152
|
+
|
|
153
|
+
# I feel like this is overwriting what would have already been idenfitied in the mapping.
|
|
154
|
+
# This probably needs to be initialized differently.
|
|
155
|
+
# parsed_address_components = {'City': '', 'State': '', 'Zip Code': ''}
|
|
156
|
+
parsed_address_components = {}
|
|
157
|
+
|
|
158
|
+
# Process each field in the row
|
|
159
|
+
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.
|
|
161
|
+
# Need to tell the user which patient we're talking about because it won't be obvious anymore.
|
|
162
|
+
if action == -1: # Retry
|
|
163
|
+
continue # Remain on the current row.
|
|
164
|
+
elif action == 1: # Skip
|
|
165
|
+
if current_row_index == len(csv_data) - 1: # If it's the last row
|
|
166
|
+
print("Reached the end of the patient list. Looping back to the beginning.")
|
|
167
|
+
current_row_index = 0 # Reset to the first row
|
|
168
|
+
else:
|
|
169
|
+
current_row_index += 1 # Move to the next row
|
|
170
|
+
continue
|
|
171
|
+
elif action == -2: # Go back two patients and redo
|
|
172
|
+
current_row_index = max(0, current_row_index - 2) # Go back two rows, but not below 0
|
|
173
|
+
continue
|
|
174
|
+
|
|
175
|
+
# 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).
|
|
179
|
+
current_row_index += 1 # Move to the next row by default
|
|
180
|
+
|
|
181
|
+
def open_medisoft(shortcut_path):
|
|
182
|
+
try:
|
|
183
|
+
os.startfile(shortcut_path)
|
|
184
|
+
print("Medisoft is being opened...\n")
|
|
185
|
+
except subprocess.CalledProcessError as e:
|
|
186
|
+
print("Failed to open Medisoft:", e)
|
|
187
|
+
print("Please manually open Medisoft.")
|
|
188
|
+
except Exception as e:
|
|
189
|
+
print("An unexpected error occurred:", e)
|
|
190
|
+
print("Please manually open Medisoft.")
|
|
191
|
+
finally:
|
|
192
|
+
print("Press 'F12' to begin data entry.")
|
|
193
|
+
|
|
194
|
+
# Placeholder for any cleanup
|
|
195
|
+
def cleanup():
|
|
196
|
+
print("\n**** Medibot Finished! ****\n")
|
|
197
|
+
# THis might need to delete the staging stuff that gets set up by mostly MediLink but maybe other stuff too.
|
|
198
|
+
pass
|
|
199
|
+
|
|
200
|
+
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)
|
|
209
|
+
|
|
210
|
+
def verify_config_type(self, config):
|
|
211
|
+
if not isinstance(config, (dict, OrderedDict)):
|
|
212
|
+
raise TypeError("Error: Configuration must be a dictionary or an OrderedDict. Check unpacking.")
|
|
213
|
+
|
|
214
|
+
# Main script execution wrapped in try-except for error handling
|
|
215
|
+
if __name__ == "__main__":
|
|
216
|
+
e_state = None
|
|
217
|
+
try:
|
|
218
|
+
# Default paths
|
|
219
|
+
default_config_path = os.path.join(os.path.dirname(__file__), '..', 'json', 'config.json')
|
|
220
|
+
default_crosswalk_path = os.path.join(os.path.dirname(__file__), '..', 'json', 'crosswalk.json')
|
|
221
|
+
|
|
222
|
+
# Check if command-line arguments are provided
|
|
223
|
+
if len(sys.argv) > 1:
|
|
224
|
+
# If arguments are provided, use them
|
|
225
|
+
config_path = sys.argv[1]
|
|
226
|
+
crosswalk_path = sys.argv[2] if len(sys.argv) > 2 else default_crosswalk_path
|
|
227
|
+
else:
|
|
228
|
+
# If no arguments are provided, use default paths
|
|
229
|
+
config_path = default_config_path
|
|
230
|
+
crosswalk_path = default_crosswalk_path
|
|
231
|
+
|
|
232
|
+
e_state = ExecutionState()
|
|
233
|
+
|
|
234
|
+
#print("Loading CSV Data...")
|
|
235
|
+
csv_data = MediBot_Preprocessor.load_csv_data(CSV_FILE_PATH)
|
|
236
|
+
|
|
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
|
|
240
|
+
|
|
241
|
+
#print("Performing Intake Scan...")
|
|
242
|
+
# identified_fields is an OrderedDict
|
|
243
|
+
identified_fields = MediBot_Preprocessor.intake_scan(headers, field_mapping)
|
|
244
|
+
|
|
245
|
+
# Reverse the identified_fields mapping for lookup
|
|
246
|
+
reverse_mapping = {v: k for k, v in identified_fields.items()}
|
|
247
|
+
|
|
248
|
+
# CSV Patient Triage
|
|
249
|
+
interaction_mode = 'triage' # Start in triage mode
|
|
250
|
+
error_message = "" # This will be filled if an error has occurred
|
|
251
|
+
#print("Debug - Identified fields mapping (main): {}".format(identified_fields)) # Debug Line
|
|
252
|
+
|
|
253
|
+
proceed, selected_patient_ids, selected_indices, fixed_values = MediBot_UI.user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
|
|
254
|
+
|
|
255
|
+
if proceed:
|
|
256
|
+
# Filter csv_data for selected patients from Triage mode.
|
|
257
|
+
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)
|
|
259
|
+
|
|
260
|
+
if existing_patients:
|
|
261
|
+
print("\nNOTE: The following patient(s) already EXIST in the system and \nwill be excluded from processing:")
|
|
262
|
+
for patient_id, patient_name in existing_patients:
|
|
263
|
+
print("(ID: {0}) {1}".format(patient_id, patient_name))
|
|
264
|
+
# Update csv_data to exclude existing patients
|
|
265
|
+
csv_data = [row for row in csv_data if row[reverse_mapping['Patient ID #2']] in patients_to_process]
|
|
266
|
+
else:
|
|
267
|
+
print("\nSelected patient(s) are NEW patients and will be processed.")
|
|
268
|
+
|
|
269
|
+
if len(patients_to_process) == 0:
|
|
270
|
+
proceed = input("\nAll patients have been processed. Continue anyway?: ").lower().strip() in ['yes', 'y']
|
|
271
|
+
else:
|
|
272
|
+
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
|
+
|
|
274
|
+
if proceed:
|
|
275
|
+
|
|
276
|
+
# Would be nice to have some kind of self-test here.
|
|
277
|
+
# print("\nDebug - Starting AHK script. Reload AHK if failed...")
|
|
278
|
+
# try:
|
|
279
|
+
# subprocess.call([AHK_EXECUTABLE, r"G:\My Drive\CocoWave\XP typing bot\notepad_test.ahk"])
|
|
280
|
+
# run_ahk_script('MsgBox, Test AHK Script Execution')
|
|
281
|
+
# except subprocess.CalledProcessError as e:
|
|
282
|
+
# print("Error running AHK script. Please reload AHK and try again. Error: {}".format(e))
|
|
283
|
+
# exit(1)
|
|
284
|
+
# except Exception as e:
|
|
285
|
+
# print("An unexpected error occurred while running the AHK script: {}".format(e))
|
|
286
|
+
# exit(1)
|
|
287
|
+
|
|
288
|
+
print("\nRemember, when in Medisoft:")
|
|
289
|
+
print(" Press 'F8' to create a New Patient.")
|
|
290
|
+
print(" Press 'F12' to begin data entry.")
|
|
291
|
+
print(" Press 'F11' at any time to Pause.")
|
|
292
|
+
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)
|
|
296
|
+
data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values)
|
|
297
|
+
cleanup()
|
|
298
|
+
else:
|
|
299
|
+
print("Data entry canceled by user.")
|
|
300
|
+
except Exception as e:
|
|
301
|
+
if e_state:
|
|
302
|
+
interaction_mode = 'error' # Switch to error mode
|
|
303
|
+
error_message = str(e) # Capture the error message
|
|
304
|
+
print("An error occurred: {0}".format(e))
|
|
305
|
+
# Handle the error by calling user interaction with the error information
|
|
306
|
+
# Ensure that identified_fields is defined before using it in user interaction
|
|
307
|
+
if 'identified_fields' in locals():
|
|
308
|
+
_ = MediBot_UI.user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
|
|
309
|
+
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
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
"""
|