medicafe 0.240517.0__py3-none-any.whl → 0.240716.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.

Files changed (37) hide show
  1. MediBot/MediBot.bat +46 -6
  2. MediBot/MediBot.py +9 -36
  3. MediBot/MediBot_Charges.py +0 -28
  4. MediBot/MediBot_Crosswalk_Library.py +16 -8
  5. MediBot/MediBot_Post.py +0 -0
  6. MediBot/MediBot_Preprocessor.py +26 -63
  7. MediBot/MediBot_Preprocessor_lib.py +182 -43
  8. MediBot/MediBot_UI.py +2 -7
  9. MediBot/MediBot_dataformat_library.py +0 -9
  10. MediBot/MediBot_docx_decoder.py +283 -60
  11. MediLink/MediLink.py +80 -120
  12. MediLink/MediLink_837p_encoder.py +3 -28
  13. MediLink/MediLink_837p_encoder_library.py +19 -53
  14. MediLink/MediLink_API_Generator.py +246 -0
  15. MediLink/MediLink_API_v2.py +2 -0
  16. MediLink/MediLink_API_v3.py +325 -0
  17. MediLink/MediLink_APIs.py +2 -0
  18. MediLink/MediLink_ClaimStatus.py +144 -0
  19. MediLink/MediLink_ConfigLoader.py +13 -7
  20. MediLink/MediLink_DataMgmt.py +224 -68
  21. MediLink/MediLink_Decoder.py +165 -0
  22. MediLink/MediLink_Deductible.py +203 -0
  23. MediLink/MediLink_Down.py +122 -96
  24. MediLink/MediLink_Gmail.py +453 -74
  25. MediLink/MediLink_Mailer.py +0 -7
  26. MediLink/MediLink_Parser.py +193 -0
  27. MediLink/MediLink_Scan.py +0 -0
  28. MediLink/MediLink_Scheduler.py +2 -172
  29. MediLink/MediLink_StatusCheck.py +0 -4
  30. MediLink/MediLink_UI.py +54 -18
  31. MediLink/MediLink_Up.py +6 -15
  32. {medicafe-0.240517.0.dist-info → medicafe-0.240716.2.dist-info}/METADATA +4 -1
  33. medicafe-0.240716.2.dist-info/RECORD +47 -0
  34. {medicafe-0.240517.0.dist-info → medicafe-0.240716.2.dist-info}/WHEEL +1 -1
  35. medicafe-0.240517.0.dist-info/RECORD +0 -39
  36. {medicafe-0.240517.0.dist-info → medicafe-0.240716.2.dist-info}/LICENSE +0 -0
  37. {medicafe-0.240517.0.dist-info → medicafe-0.240716.2.dist-info}/top_level.txt +0 -0
MediBot/MediBot.bat CHANGED
@@ -11,6 +11,8 @@ set "medicafe_package=medicafe"
11
11
  set "upgrade_medicafe=F:\Medibot\update_medicafe.py"
12
12
  set "temp_file=F:\Medibot\last_update_timestamp.txt"
13
13
  set "firefox_path=C:\Program Files\Mozilla Firefox\firefox.exe"
14
+ set "claims_status_script=..\MediLink\MediLink_ClaimStatus.py"
15
+ set "deductible_script=..\MediLink\MediLink_Deductible.py"
14
16
  set "package_version="
15
17
  set PYTHONWARNINGS=ignore
16
18
 
@@ -99,14 +101,18 @@ if "!internet_available!"=="1" (
99
101
  echo 1. Check for MediCafe Package Updates
100
102
  echo 2. Download Email de Carol
101
103
  echo 3. MediLink Claims
104
+ echo 4. United Claims Status
105
+ echo 5. United Deductible
102
106
  )
103
- echo 4. Run MediBot
104
- echo 5. Exit
107
+ echo 6. Run MediBot
108
+ echo 7. Exit
105
109
  echo.
106
110
  set /p choice=Enter your choice:
107
111
 
108
- if "!choice!"=="5" goto end_script
109
- if "!choice!"=="4" goto medibot_flow
112
+ if "!choice!"=="7" goto end_script
113
+ if "!choice!"=="6" goto medibot_flow
114
+ if "!choice!"=="5" goto united_deductible
115
+ if "!choice!"=="4" goto united_claims_status
110
116
  if "!choice!"=="3" goto medilink_flow
111
117
  if "!choice!"=="2" goto download_emails
112
118
  if "!choice!"=="1" goto check_updates
@@ -133,6 +139,7 @@ if "!internet_available!"=="0" (
133
139
  goto main_menu
134
140
  )
135
141
  echo Downloading emails...
142
+ :: move this path.
136
143
  py "../MediLink/MediLink_Gmail.py" "%firefox_path%"
137
144
  if errorlevel 1 (
138
145
  echo Failed to download emails.
@@ -161,11 +168,38 @@ if "!internet_available!"=="0" (
161
168
  )
162
169
  call :process_csvs
163
170
  cls
171
+ :: move this path.
164
172
  py "C:\Python34\Lib\site-packages\MediLink\MediLink.py"
165
173
  if errorlevel 1 echo MediLink failed to execute.
166
174
  pause
167
175
  goto main_menu
168
176
 
177
+ :: United Claims Status
178
+ :united_claims_status
179
+ if "!internet_available!"=="0" (
180
+ echo No internet connection available.
181
+ goto main_menu
182
+ )
183
+ cls
184
+ echo Checking United Claims Status...
185
+ py "%claims_status_script%"
186
+ if errorlevel 1 echo Failed to check United Claims Status.
187
+ pause
188
+ goto main_menu
189
+
190
+ :: United Deductible
191
+ :united_deductible
192
+ if "!internet_available!"=="0" (
193
+ echo No internet connection available.
194
+ goto main_menu
195
+ )
196
+ cls
197
+ echo Checking United Deductible...
198
+ py "%deductible_script%"
199
+ if errorlevel 1 echo Failed to check United Deductible.
200
+ pause
201
+ goto main_menu
202
+
169
203
  :: Process CSV Files
170
204
  :process_csvs
171
205
  for /f "tokens=1-5 delims=/: " %%a in ('echo %time%') do (
@@ -173,7 +207,13 @@ for /f "tokens=1-5 delims=/: " %%a in ('echo %time%') do (
173
207
  set "minute=%%b"
174
208
  set "second=%%c"
175
209
  )
176
- set "timestamp=%DATE:~-4%%DATE:~3,2%%DATE:~0,2%_%hour%%minute%"
210
+ for /f "tokens=2-4 delims=/ " %%a in ('echo %date%') do (
211
+ set "day=%%a"
212
+ set "month=%%b"
213
+ set "year=%%c"
214
+ )
215
+ set "timestamp=!year!!month!!day!_!hour!!minute!"
216
+
177
217
  set "latest_csv="
178
218
  for /f "delims=" %%a in ('dir /b /a-d /o-d "%source_folder%\*.csv" 2^>nul') do (
179
219
  set "latest_csv=%%a"
@@ -195,4 +235,4 @@ goto :eof
195
235
  :end_script
196
236
  echo Exiting MediCafe.
197
237
  pause
198
- exit /b
238
+ exit /b
MediBot/MediBot.py CHANGED
@@ -22,41 +22,6 @@ except ImportError:
22
22
  from MediBot import MediBot_Crosswalk_Library
23
23
  crosswalk_update = MediBot_Crosswalk_Library.crosswalk_update
24
24
 
25
- """
26
- # Development Task List for MediBot
27
-
28
- Error Handling Improvements
29
- - [ ] Its really difficult to get out of the main menu if you go open MediBot by accident
30
- - [ ] Develop a centralized error handling and logging mechanism for improved troubleshooting.
31
- - [ ] Implement validation checks during patient data entry to prevent submission of incomplete or incorrect records.
32
-
33
- Insurance Mode Adjustments
34
- - [ ] Integrate a comprehensive list of insurance company codes for automatic selection.
35
- - [ ] Automate insurance-specific data entry adjustments, such as character replacements specific to Medicare.
36
-
37
- Diagnosis Entry
38
- - [ ] Automate data extraction from Surgery Schedule to import to CSV a column indicating diagnosis code per px.
39
-
40
- Script Efficiency and Reliability
41
- - [ ] Ensure robust handling of Medisoft's field navigation quirks, particularly for fields that are skipped or require special access.
42
-
43
- Documentation and Support
44
- - [ ] Create detailed documentation for setup, configuration, and usage of the script.
45
- - [ ] Establish a support channel for users to report issues or request features.
46
-
47
- Future Directions
48
- - [ ] Consider developing a graphical user interface (GUI) for non-technical users for easier script management and execution.
49
-
50
- Medisoft Field Navigation:
51
- Investigate and optimize navigation for fields that Medisoft skips or requires backward navigation to access.
52
-
53
- Insurance Mode Features:
54
- Evaluate the feasibility and implement the use of the F6 search for insurance address verification, enhancing user verification processes.
55
-
56
- Error Handling and Logging:
57
- Implement a check for AHK script execution status, providing feedback or troubleshooting steps if the script encounters issues.
58
- """
59
-
60
25
  def identify_field(header, field_mapping):
61
26
  for medisoft_field, patterns in field_mapping.items():
62
27
  for pattern in patterns:
@@ -223,7 +188,7 @@ class ExecutionState:
223
188
  MediLink_ConfigLoader.log("Constants initialized...")
224
189
 
225
190
  except Exception as e:
226
- print("Failed to load or update configuration: {}".format(e))
191
+ print("MediBot: Failed to load or update configuration: {}".format(e))
227
192
  raise # Re-throwing the exception or using a more sophisticated error handling mechanism might be needed
228
193
  # Handle the exception somehow (e.g., retry, halt, log)??
229
194
 
@@ -261,6 +226,7 @@ if __name__ == "__main__":
261
226
  MediLink_ConfigLoader.log("Pre-processing CSV Data...", level="INFO")
262
227
  MediBot_Preprocessor.preprocess_csv_data(csv_data, e_state.crosswalk)
263
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.
264
230
 
265
231
  print("Performing Intake Scan...")
266
232
  MediLink_ConfigLoader.log("Performing Intake Scan...", level="INFO")
@@ -294,9 +260,12 @@ if __name__ == "__main__":
294
260
 
295
261
  if existing_patients:
296
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.
297
265
  for patient_id, patient_name in existing_patients:
298
266
  print("(ID: {0}) {1}".format(patient_id, patient_name))
299
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.
300
269
  csv_data = [row for row in csv_data if row[reverse_mapping['Patient ID #2']] in patients_to_process]
301
270
  else:
302
271
  print("\nSelected patient(s) are NEW patients and will be processed.")
@@ -306,6 +275,10 @@ if __name__ == "__main__":
306
275
  else:
307
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']
308
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
+
309
282
  if proceed:
310
283
 
311
284
  # Would be nice to have some kind of self-test here.
@@ -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
- """
@@ -14,10 +14,10 @@ except ImportError:
14
14
  from MediLink import MediLink_ConfigLoader
15
15
 
16
16
  try:
17
- from MediLink_API_v2 import fetch_payer_name_from_api
17
+ from MediLink_API_v3 import fetch_payer_name_from_api
18
18
  except ImportError:
19
- from MediLink import MediLink_API_v2
20
- fetch_payer_name_from_api = MediLink_API_v2.fetch_payer_name_from_api
19
+ from MediLink import MediLink_API_v3
20
+ fetch_payer_name_from_api = MediLink_API_v3.fetch_payer_name_from_api
21
21
 
22
22
  try:
23
23
  from MediBot import MediBot_Preprocessor_lib
@@ -127,7 +127,7 @@ def initialize_crosswalk_from_mapat():
127
127
  validate_and_correct_payer_ids(crosswalk, config)
128
128
 
129
129
  # Save the initial crosswalk
130
- if save_crosswalk(config['MediLink_Config']['crosswalkPath'], crosswalk):
130
+ if save_crosswalk(config, crosswalk):
131
131
  message = "Crosswalk initialized with mappings for {} payers.".format(len(crosswalk.get('payer_id', {})))
132
132
  print(message)
133
133
  MediLink_ConfigLoader.log(message, config, level="INFO")
@@ -167,6 +167,7 @@ def crosswalk_update(config, crosswalk):
167
167
 
168
168
  # Load incremental mapping data from Z.dat (Patient ID to Insurance Name)
169
169
  # TODO This may be a redundant approach?
170
+ # This is a singular path. This is fine though because any time we process a Z.DAT we'd have the crosswalk incremented.
170
171
  patient_id_to_insurance_name = MediBot_Preprocessor_lib.parse_z_dat(config['MediLink_Config']['Z_DAT_PATH'], config['MediLink_Config'])
171
172
  MediLink_ConfigLoader.log("Parsed Z data...")
172
173
 
@@ -196,7 +197,7 @@ def crosswalk_update(config, crosswalk):
196
197
  crosswalk['payer_id'][payer_id]['medisoft_medicare_id'] = list(crosswalk['payer_id'][payer_id]['medisoft_medicare_id'])
197
198
 
198
199
  # Save the updated crosswalk to the specified file
199
- return save_crosswalk(config['MediLink_Config']['crosswalkPath'], crosswalk)
200
+ return save_crosswalk(config, crosswalk)
200
201
 
201
202
  def update_crosswalk_with_corrected_payer_id(old_payer_id, corrected_payer_id, config, crosswalk):
202
203
  """Updates the crosswalk with the corrected payer ID."""
@@ -215,7 +216,7 @@ def update_crosswalk_with_corrected_payer_id(old_payer_id, corrected_payer_id, c
215
216
  MediLink_ConfigLoader.log("Crosswalk csv_replacements updated: added {} -> {}".format(old_payer_id, corrected_payer_id), config, level="INFO")
216
217
 
217
218
  # Save the updated crosswalk
218
- return save_crosswalk(config['MediLink_Config']['crosswalkPath'], crosswalk)
219
+ return save_crosswalk(config, crosswalk)
219
220
 
220
221
  def update_crosswalk_with_new_payer_id(insurance_name, payer_id, config):
221
222
  """Updates the crosswalk with a new payer ID."""
@@ -228,14 +229,14 @@ def update_crosswalk_with_new_payer_id(insurance_name, payer_id, config):
228
229
  crosswalk['payer_id'][payer_id] = {"medisoft_id": [medisoft_id_str], "medisoft_medicare_id": []}
229
230
  else:
230
231
  crosswalk['payer_id'][payer_id]['medisoft_id'].append(medisoft_id_str)
231
- save_crosswalk(config['MediLink_Config']['crosswalkPath'], crosswalk)
232
+ save_crosswalk(config, crosswalk)
232
233
  MediLink_ConfigLoader.log("Updated crosswalk with new payer ID {} for insurance name {}".format(payer_id, insurance_name), config, level="INFO")
233
234
  else:
234
235
  message = "Failed to update crosswalk: Medisoft ID not found for insurance name {}".format(insurance_name)
235
236
  print(message)
236
237
  MediLink_ConfigLoader.log(message, config, level="ERROR")
237
238
 
238
- def save_crosswalk(crosswalk_path, crosswalk):
239
+ def save_crosswalk(config, crosswalk):
239
240
  """
240
241
  Saves the updated crosswalk to a JSON file.
241
242
  Args:
@@ -244,6 +245,13 @@ def save_crosswalk(crosswalk_path, crosswalk):
244
245
  Returns:
245
246
  bool: True if the file was successfully saved, False otherwise.
246
247
  """
248
+ # Attempt to fetch crosswalkPath from MediLink_Config
249
+ try:
250
+ crosswalk_path = config['MediLink_Config']['crosswalkPath']
251
+ except KeyError:
252
+ # If KeyError occurs, fall back to fetching crosswalkPath directly
253
+ crosswalk_path = config.get('crosswalkPath', None) # Replace None with a default value if needed
254
+
247
255
  try:
248
256
  # Initialize 'payer_id' key if not present
249
257
  if 'payer_id' not in crosswalk:
File without changes
@@ -20,61 +20,6 @@ try:
20
20
  except ImportError:
21
21
  from MediBot import MediBot_Preprocessor_lib
22
22
 
23
- """
24
- Preprocessing Enhancements
25
- - [X] Preprocess Insurance Policy Numbers and Group Numbers to replace '-' with ''.
26
- - [X] De-duplicate entries in the CSV and only entering the px once even if they show up twice in the file.
27
- - [ ] Implement dynamic field combination in CSV pre-processing for flexibility with various CSV formats.
28
- - [ ] Enhance SSN cleaning logic to handle more variations of sensitive data masking.
29
- - [ ] Optimize script startup and CSV loading to reduce initial latency.
30
-
31
- Data Integrity and Validation
32
- - [ ] Conduct a thorough CSV integrity check before processing to flag potential issues upfront.
33
- - [ ] Implement a mechanism to confirm the accuracy of entered data, potentially through a verification step or summary report.
34
- - [ ] Explore the possibility of integrating direct database queries for existing patient checks to streamline the process.
35
- - [ ] Automate the replacement of spaces with underscores ('_') in last names for Medicare entries.
36
- - [ ] Enhance CSV integrity checks to identify and report potential issues with data format, especially concerning insurance policy numbers and special character handling.
37
-
38
- Known Issues and Bugs
39
- - [ ] Address the handling of '.' and other special characters that may disrupt parsing, especially under Windows XP.
40
- - [ ] Investigate the issue with Excel modifying long policy numbers in the CSV and provide guidance or a workaround.
41
-
42
- Future Work
43
- - [X] Check for PatientID number in La Forma Z to link back to Carol's table for mapping Medisoft insurance name to payerID and payer name and address.
44
- - [X] Check for PatientID to Medisoft custom insurance name mapping in MAPAT.
45
- - [X] Middle Names should all be single letters. Make sure it gets truncated before submitting.
46
- - [ ] Consolidate data from multiple sources (Provider_Notes.csv, Surgery_Schedule.csv, and Carols_CSV.csv) into a single table with Patient ID as the key, ensuring all data elements are aligned and duplicate entries are minimized.
47
- - [ ] Implement logic to verify and match Patient IDs across different files to ensure data integrity before consolidation. (Catching errors between source data)
48
- - [ ] Optimize the preprocessing of surgery dates and diagnosis codes for use in patient billing and scheduling systems.
49
- - [ ] Read Surgery Schedule doc and parse out a Patient ID : Diagnosis Code table.
50
- - [ ] The Minutes & Cancellation data with logic to consolidate into one table in memory.
51
- - [ ] Dynamically list the endpoint for a new Payer ID via API or user interaction to update the crosswalk.json efficiently.
52
- - [ ] Pull listed addresses of insurance from the CSV. (Not really necessary)
53
- - [ ] Retroactively learn Medisoft insurance name and payerID from the provided data sources.
54
-
55
- Development Roadmap for crosswalk_update():
56
- - [X] Automation required for updating the crosswalk.json when new Medisoft insurance is discovered.
57
- - [X] New Medisoft insurances are identified based on the payer ID number.
58
- - [X] Check the existence of the payer ID in crosswalk.json under existing endpoints.
59
- - [X] Facilitate grouping of IDs for insurances like CIGNA with multiple addresses but few payer IDs.
60
- - [X] Retroactive learning based on selected insurances in Medisoft
61
- - [ ] Prompt user via endpoint APIs to add new payer ID to an endpoint if it does not exist.
62
- - [ ] Retain payer IDs without Insurance ID for future assignments.
63
- - [ ] Check for free payer IDs and determine the appropriate endpoint for assignment.
64
- - [ ] Present unrecognized payer IDs with Carol's Insurance Name to users for assignment to Insurance ID. (Try API Call)
65
- - [ ] Integrate API checks to verify payer ID availability and related information.
66
- - [ ] Implement "Fax/Mail or Other" endpoint for unavailable payer IDs.
67
- - [ ] Present user with a list of top insurances for selection based on fuzzy search scores.
68
- - [ ] Establish payer ID to insurance ID relationship based on user selection.
69
- - [ ] Implicitly establish payer ID to endpoint mapping based on user selection.
70
- - [ ] Implement validation mechanisms to prevent incorrect mappings and ensure data integrity.
71
- - [ ] Considerations for extracting insurance addresses (if necessary)
72
- - [ ] Handle better the case where a payer_id doesn't exist (When Carol's CSV doesn't bring the Payer ID).
73
- Maybe ask the user what the payer ID is for that patient? I dont know.
74
- - [ ] TODO (MED) Crosswalk (both initializing and updating) needs to pull AFTER the Preprocessor for Carol's CSV because
75
- all that data lives in-memory and then gets corrections or replacements before being used so we need
76
- the post-correction data to be used to build and update the crosswalk.
77
- """
78
23
  # Load configuration
79
24
  # Should this also take args? Path for ./MediLink needed to be added for this to resolve
80
25
  config, crosswalk = MediLink_ConfigLoader.load_configuration()
@@ -82,10 +27,11 @@ config, crosswalk = MediLink_ConfigLoader.load_configuration()
82
27
  # CSV Preprocessor built for Carol
83
28
  def preprocess_csv_data(csv_data, crosswalk):
84
29
  try:
85
- # Add the "Ins1 Insurance ID" column to the CSV data.
86
- # This initializes the column with empty values for each row.
87
- MediLink_ConfigLoader.log("CSV Pre-processor: Adding 'Ins1 Insurance ID' column to the CSV data...", level="INFO")
88
- MediBot_Preprocessor_lib.add_insurance_id_column(csv_data)
30
+ # Add the "Ins1 Insurance ID" and "Default Diagnosis #1" columns to the CSV data.
31
+ # This initializes the columns with empty values for each row.
32
+ columns_to_add = ['Ins1 Insurance ID', 'Default Diagnosis #1', 'Procedure Code', 'Minutes', 'Amount']
33
+ MediLink_ConfigLoader.log("CSV Pre-processor: Initializing empty columns to the CSV data...", level="INFO")
34
+ MediBot_Preprocessor_lib.add_columns(csv_data, columns_to_add)
89
35
 
90
36
  # Filter out rows without a Patient ID and rows where the Primary Insurance
91
37
  # is 'AETNA', 'AETNA MEDICARE', or 'HUMANA MED HMO'.
@@ -93,13 +39,20 @@ def preprocess_csv_data(csv_data, crosswalk):
93
39
  MediBot_Preprocessor_lib.filter_rows(csv_data)
94
40
 
95
41
  # Convert 'Surgery Date' from string format to datetime objects for sorting purposes.
96
- # Sort the patients by 'Surgery Date' and then by 'Patient Last' name alphabetically.
97
- # Deduplicate patient records based on Patient ID, keeping the entry with the earliest surgery date.
42
+ MediBot_Preprocessor_lib.convert_surgery_date(csv_data)
43
+
98
44
  # Update the CSV data to include only unique patient records.
99
45
  # Re-sort the CSV data after deduplication to ensure the correct order.
46
+ # Sort the patients by 'Surgery Date' and then by 'Patient Last' name alphabetically.
47
+ # Deduplicate patient records based on Patient ID, keeping the entry with the earliest surgery date.
100
48
  MediLink_ConfigLoader.log("CSV Pre-processor: Sorting and de-duplicating patient records...", level="INFO")
101
- MediBot_Preprocessor_lib.convert_surgery_date(csv_data)
102
- MediBot_Preprocessor_lib.sort_and_deduplicate(csv_data)
49
+ MediBot_Preprocessor_lib.sort_and_deduplicate(csv_data)
50
+ # TODO This eventually needs to be handled differently because now we're wanting to handle both surgery dates.
51
+ # Instead of deleting, maybe we need to make a secondary dataset or some kind of flag or isolate here where
52
+ # MediBot knows to skip it when entering the patient data but is ready to put Charges for the second surgery date.
53
+ # MediLink_Scheduler will have a dictionary persist somewhere that would tell us which patients were billed
54
+ # and which haven't been yet. So, if the patient 'exists' in the system, the next quetion is about claims/billing status.
55
+ # Eventually, we really want to get out of Medisoft...
103
56
 
104
57
  # Convert 'Surgery Date' back to string format if needed for further processing.
105
58
  # Combine 'Patient First', 'Patient Middle', and 'Patient Last' into a single 'Patient Name' field.
@@ -117,6 +70,16 @@ def preprocess_csv_data(csv_data, crosswalk):
117
70
  # If the Payer ID is not found in the crosswalk, create a placeholder entry in the crosswalk and mark the row for review.
118
71
  MediLink_ConfigLoader.log("CSV Pre-processor: Populating 'Ins1 Insurance ID' based on Crosswalk...", level="INFO")
119
72
  MediBot_Preprocessor_lib.update_insurance_ids(csv_data, crosswalk)
73
+
74
+ # Enrich the "Default Diagnosis #1" column based on the parsed docx for each row.
75
+ # This needs to handle the different patient dates correctly so we get the right diagnosis code assigned to the right patient on the right date of service.
76
+ # Currently, we've deleted all the second date entries for patients. As long as they exist in the system, they're just deleted.
77
+ MediLink_ConfigLoader.log("CSV Pre-processor: Populating 'Default Diagnosis #1' based on Surgery Schedule and Crosswalk...", level="INFO")
78
+ MediBot_Preprocessor_lib.update_diagnosis_codes(csv_data)
79
+
80
+ # Enrich the procedure code column based on the diagnosis code for each patient.
81
+ MediLink_ConfigLoader.log("CSV Pre-processor: Populating 'Procedure Code' based on Crosswalk...", level="INFO")
82
+ MediBot_Preprocessor_lib.update_procedure_codes(csv_data)
120
83
 
121
84
  except Exception as e:
122
85
  message = "An error occurred while pre-processing CSV data. Please repair the CSV directly and try again: {}".format(e)