medicafe 0.240809.0__py3-none-any.whl → 0.240925.9__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 +56 -16
- MediBot/MediBot.py +90 -79
- MediBot/MediBot_Crosswalk_Library.py +496 -194
- MediBot/MediBot_Preprocessor.py +22 -14
- MediBot/MediBot_Preprocessor_lib.py +299 -153
- MediBot/MediBot_UI.py +25 -24
- MediBot/MediBot_dataformat_library.py +17 -25
- MediBot/MediBot_docx_decoder.py +267 -110
- MediBot/update_json.py +26 -1
- MediBot/update_medicafe.py +134 -44
- MediLink/MediLink.py +93 -51
- MediLink/MediLink_837p_encoder.py +23 -23
- MediLink/MediLink_837p_encoder_library.py +141 -96
- MediLink/MediLink_API_Generator.py +1 -7
- MediLink/MediLink_API_v3.py +240 -59
- MediLink/MediLink_APIs.py +1 -2
- MediLink/MediLink_ClaimStatus.py +21 -6
- MediLink/MediLink_ConfigLoader.py +8 -8
- MediLink/MediLink_DataMgmt.py +321 -100
- MediLink/MediLink_Decoder.py +249 -87
- MediLink/MediLink_Deductible.py +7 -8
- MediLink/MediLink_Down.py +115 -120
- MediLink/MediLink_Gmail.py +2 -11
- MediLink/MediLink_Parser.py +63 -36
- MediLink/MediLink_UI.py +29 -24
- MediLink/MediLink_Up.py +12 -8
- {medicafe-0.240809.0.dist-info → medicafe-0.240925.9.dist-info}/METADATA +1 -1
- medicafe-0.240925.9.dist-info/RECORD +47 -0
- {medicafe-0.240809.0.dist-info → medicafe-0.240925.9.dist-info}/WHEEL +1 -1
- medicafe-0.240809.0.dist-info/RECORD +0 -47
- {medicafe-0.240809.0.dist-info → medicafe-0.240925.9.dist-info}/LICENSE +0 -0
- {medicafe-0.240809.0.dist-info → medicafe-0.240925.9.dist-info}/top_level.txt +0 -0
|
@@ -1,288 +1,590 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import sys
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
# Add parent directory of the project to the Python path
|
|
6
|
-
import sys
|
|
1
|
+
import json, sys, os
|
|
7
2
|
|
|
3
|
+
# Set the project directory to the parent directory of the current file
|
|
8
4
|
project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
9
|
-
sys.path
|
|
5
|
+
if project_dir not in sys.path:
|
|
6
|
+
sys.path.append(project_dir)
|
|
10
7
|
|
|
11
|
-
|
|
8
|
+
# Attempt to import the MediLink_ConfigLoader module, falling back to an alternative import if necessary
|
|
9
|
+
try:
|
|
12
10
|
import MediLink_ConfigLoader
|
|
13
|
-
except ImportError:
|
|
11
|
+
except ImportError:
|
|
14
12
|
from MediLink import MediLink_ConfigLoader
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
# Attempt to import the fetch_payer_name_from_api function from MediLink_API_v3, with a fallback
|
|
15
|
+
try:
|
|
17
16
|
from MediLink_API_v3 import fetch_payer_name_from_api
|
|
18
|
-
except ImportError:
|
|
17
|
+
except ImportError:
|
|
19
18
|
from MediLink import MediLink_API_v3
|
|
20
19
|
fetch_payer_name_from_api = MediLink_API_v3.fetch_payer_name_from_api
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
# Attempt to import the MediBot_Preprocessor_lib module, with a fallback
|
|
22
|
+
try:
|
|
23
23
|
from MediBot import MediBot_Preprocessor_lib
|
|
24
|
-
except ImportError:
|
|
24
|
+
except ImportError:
|
|
25
25
|
import MediBot_Preprocessor_lib
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
"""
|
|
28
|
+
# TODO This has a bunch of issues that need to be fixed. Notice, the log has repetitive calls to the API that are redundant.
|
|
29
|
+
|
|
30
|
+
PS G:\My Drive\Codes\MediCafe> & C:/Python34/python.exe "g:/My Drive/Codes/MediCafe/MediBot/MediBot_Preprocessor.py" --update-crosswalk
|
|
31
|
+
Updating the crosswalk...
|
|
32
|
+
The 'payer_id' list is empty or missing. Would you like to initialize the crosswalk? (yes/no): yes
|
|
33
|
+
No payer found at AVAILITY for ID 60054M. Response: {'limit': 50, 'offset': 0, 'totalCount': 0, 'payers': [], 'count': 0}
|
|
34
|
+
All endpoints exhausted for Payer ID 60054M.
|
|
35
|
+
WARNING: Invalid Payer ID 60054M (Unknown).
|
|
36
|
+
Enter the correct Payer ID for replacement or type 'FORCE' to continue with the unresolved Payer ID: 60054
|
|
37
|
+
csv_replacements updated: '60054M' -> '60054'.
|
|
38
|
+
No payer found at AVAILITY for ID MCRFL. Response: {'limit': 50, 'offset': 0, 'totalCount': 0, 'payers': [], 'count': 0}
|
|
39
|
+
All endpoints exhausted for Payer ID MCRFL.
|
|
40
|
+
No payer found at AVAILITY for ID BCSFL. Response: {'limit': 50, 'offset': 0, 'totalCount': 0, 'payers': [], 'count': 0}
|
|
41
|
+
All endpoints exhausted for Payer ID BCSFL.
|
|
42
|
+
Payer ID '60054M' has been successfully replaced with '60054'.
|
|
43
|
+
No payer found at AVAILITY for ID MCRFL. Response: {'limit': 50, 'offset': 0, 'totalCount': 0, 'payers': [], 'count': 0}
|
|
44
|
+
All endpoints exhausted for Payer ID MCRFL.
|
|
45
|
+
WARNING: Invalid Payer ID MCRFL (Unknown).
|
|
46
|
+
Enter the correct Payer ID for replacement or type 'FORCE' to continue with the unresolved Payer ID: force
|
|
47
|
+
Payer ID 'MCRFL' has been marked as 'Unknown'.
|
|
48
|
+
No payer found at AVAILITY for ID BCSFL. Response: {'limit': 50, 'offset': 0, 'totalCount': 0, 'payers': [], 'count': 0}
|
|
49
|
+
All endpoints exhausted for Payer ID BCSFL.
|
|
50
|
+
WARNING: Invalid Payer ID BCSFL (Unknown).
|
|
51
|
+
Enter the correct Payer ID for replacement or type 'FORCE' to continue with the unresolved Payer ID: 00590
|
|
52
|
+
csv_replacements updated: 'BCSFL' -> '00590'.
|
|
53
|
+
Payer ID 'BCSFL' has been successfully replaced with '00590'.
|
|
54
|
+
Crosswalk initialized with mappings for 5 payers.
|
|
55
|
+
|
|
56
|
+
"""
|
|
31
57
|
|
|
58
|
+
|
|
59
|
+
def fetch_and_store_payer_name(client, payer_id, crosswalk, config):
|
|
60
|
+
"""
|
|
61
|
+
Fetches the payer name for a given payer ID and stores it in the crosswalk.
|
|
62
|
+
|
|
32
63
|
Args:
|
|
33
|
-
|
|
64
|
+
payer_id (str): The ID of the payer to fetch.
|
|
65
|
+
crosswalk (dict): The crosswalk dictionary to store the payer name.
|
|
66
|
+
config (dict): Configuration settings for logging.
|
|
34
67
|
|
|
35
68
|
Returns:
|
|
36
|
-
|
|
69
|
+
bool: True if the payer name was fetched and stored successfully, False otherwise.
|
|
37
70
|
"""
|
|
38
|
-
|
|
39
|
-
config, crosswalk = MediLink_ConfigLoader.load_configuration(None, config.get('crosswalkPath', 'crosswalk.json'))
|
|
40
|
-
|
|
71
|
+
MediLink_ConfigLoader.log("Attempting to fetch payer name for Payer ID: {}".format(payer_id), config, level="DEBUG")
|
|
41
72
|
try:
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
except KeyError:
|
|
46
|
-
error_message = "The 'payer_id' key does not exist in the crosswalk configuration. \n" \
|
|
47
|
-
"This could be because the crosswalk is not initialized. \n" \
|
|
48
|
-
"Consider running the Crosswalk initializer."
|
|
49
|
-
print(error_message)
|
|
50
|
-
MediLink_ConfigLoader.log(error_message, config, level="ERROR")
|
|
73
|
+
# Fetch the payer name from the API
|
|
74
|
+
payer_name = fetch_payer_name_from_api(client, payer_id, config, primary_endpoint=None)
|
|
75
|
+
MediLink_ConfigLoader.log("Fetched payer name: {} for Payer ID: {}".format(payer_name, payer_id), config, level="DEBUG")
|
|
51
76
|
|
|
52
|
-
#
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
77
|
+
# Ensure the 'payer_id' key exists in the crosswalk
|
|
78
|
+
if 'payer_id' not in crosswalk:
|
|
79
|
+
crosswalk['payer_id'] = {}
|
|
80
|
+
MediLink_ConfigLoader.log("Initialized 'payer_id' in crosswalk.", config, level="DEBUG")
|
|
81
|
+
|
|
82
|
+
# Initialize the payer ID entry if it doesn't exist
|
|
83
|
+
if payer_id not in crosswalk['payer_id']:
|
|
84
|
+
crosswalk['payer_id'][payer_id] = {} # Initialize the entry
|
|
85
|
+
MediLink_ConfigLoader.log("Initialized entry for Payer ID: {}".format(payer_id), config, level="DEBUG")
|
|
86
|
+
|
|
87
|
+
# Store the fetched payer name in the crosswalk
|
|
88
|
+
crosswalk['payer_id'][payer_id]['name'] = payer_name
|
|
89
|
+
message = "Payer ID {} ({}) fetched and stored successfully.".format(payer_id, payer_name)
|
|
90
|
+
MediLink_ConfigLoader.log(message, config, level="INFO")
|
|
91
|
+
print(message)
|
|
92
|
+
return True
|
|
93
|
+
except Exception as e:
|
|
94
|
+
# Log any errors encountered during the fetching process
|
|
95
|
+
MediLink_ConfigLoader.log("Failed to fetch name for Payer ID {}: {}".format(payer_id, e), config, level="WARNING")
|
|
96
|
+
crosswalk['payer_id'][payer_id]['name'] = "Unknown"
|
|
97
|
+
return False
|
|
98
|
+
|
|
99
|
+
def validate_and_correct_payer_ids(client, crosswalk, config, auto_correct=False):
|
|
100
|
+
"""
|
|
101
|
+
Validates and corrects payer IDs in the crosswalk. If a payer ID is invalid, it prompts the user for correction.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
crosswalk (dict): The crosswalk dictionary containing payer IDs.
|
|
105
|
+
config (dict): Configuration settings for logging.
|
|
106
|
+
auto_correct (bool): If True, automatically corrects invalid payer IDs to 'Unknown'.
|
|
107
|
+
"""
|
|
108
|
+
processed_payer_ids = set() # Track processed payer IDs
|
|
109
|
+
payer_ids = list(crosswalk.get('payer_id', {}).keys()) # Static list to prevent modification issues
|
|
60
110
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
111
|
+
for payer_id in payer_ids:
|
|
112
|
+
if payer_id in processed_payer_ids:
|
|
113
|
+
continue # Skip already processed payer IDs
|
|
114
|
+
|
|
115
|
+
# Validate the payer ID by fetching its name
|
|
116
|
+
is_valid = fetch_and_store_payer_name(client, payer_id, crosswalk, config)
|
|
117
|
+
|
|
118
|
+
if not is_valid:
|
|
119
|
+
if auto_correct:
|
|
120
|
+
# Automatically correct invalid payer IDs to 'Unknown'
|
|
121
|
+
crosswalk['payer_id'][payer_id]['name'] = "Unknown"
|
|
122
|
+
MediLink_ConfigLoader.log(
|
|
123
|
+
"Auto-corrected Payer ID {} to 'Unknown'.".format(payer_id),
|
|
124
|
+
config,
|
|
125
|
+
level="WARNING"
|
|
126
|
+
)
|
|
127
|
+
print("Auto-corrected Payer ID '{}' to 'Unknown'.".format(payer_id))
|
|
128
|
+
processed_payer_ids.add(payer_id)
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
# Prompt the user for a corrected payer ID
|
|
132
|
+
current_name = crosswalk['payer_id'].get(payer_id, {}).get('name', 'Unknown')
|
|
133
|
+
corrected_payer_id = input(
|
|
134
|
+
"WARNING: Invalid Payer ID {} ({}).\n"
|
|
135
|
+
"Enter the correct Payer ID for replacement or type 'FORCE' to continue with the unresolved Payer ID: ".format(
|
|
136
|
+
payer_id, current_name)
|
|
137
|
+
).strip()
|
|
138
|
+
|
|
139
|
+
if corrected_payer_id.lower() == 'force':
|
|
140
|
+
# Assign "Unknown" and log the action
|
|
141
|
+
crosswalk['payer_id'][payer_id]['name'] = "Unknown"
|
|
142
|
+
MediLink_ConfigLoader.log(
|
|
143
|
+
"User forced unresolved Payer ID {} to remain as 'Unknown'.".format(payer_id),
|
|
144
|
+
config,
|
|
145
|
+
level="WARNING"
|
|
146
|
+
)
|
|
147
|
+
print("Payer ID '{}' has been marked as 'Unknown'.".format(payer_id))
|
|
148
|
+
processed_payer_ids.add(payer_id)
|
|
149
|
+
continue
|
|
71
150
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
fetch_payer_name_from_api(corrected_payer_id, config, primary_endpoint=None)
|
|
82
|
-
MediLink_ConfigLoader.log("Corrected Payer ID {} validated successfully.".format(corrected_payer_id), config, level="INFO")
|
|
83
|
-
|
|
84
|
-
if update_crosswalk_with_corrected_payer_id(payer_id, corrected_payer_id, config, crosswalk):
|
|
85
|
-
if 'csv_replacements' not in crosswalk:
|
|
86
|
-
crosswalk['csv_replacements'] = {}
|
|
87
|
-
crosswalk['csv_replacements'][payer_id] = corrected_payer_id
|
|
88
|
-
MediLink_ConfigLoader.log("Added replacement filter: {} -> {}".format(payer_id, corrected_payer_id), config, level="INFO")
|
|
89
|
-
else:
|
|
90
|
-
print("Failed to update crosswalk with the corrected Payer ID {}.".format(corrected_payer_id))
|
|
91
|
-
MediLink_ConfigLoader.log("Failed to update crosswalk with the corrected Payer ID {}.".format(corrected_payer_id), config, level="ERROR")
|
|
92
|
-
break
|
|
93
|
-
except Exception as e:
|
|
94
|
-
print("Corrected Payer ID {} validation failed: {}".format(corrected_payer_id, e))
|
|
95
|
-
MediLink_ConfigLoader.log("Corrected Payer ID {} validation failed: {}".format(corrected_payer_id, e), config, level="ERROR")
|
|
151
|
+
if corrected_payer_id:
|
|
152
|
+
# Validate the corrected payer ID
|
|
153
|
+
if fetch_and_store_payer_name(client, corrected_payer_id, crosswalk, config):
|
|
154
|
+
# Replace the old payer ID with the corrected one in the crosswalk
|
|
155
|
+
success = update_crosswalk_with_corrected_payer_id(client, payer_id, corrected_payer_id, config, crosswalk)
|
|
156
|
+
if success:
|
|
157
|
+
print("Payer ID '{}' has been successfully replaced with '{}'.".format(
|
|
158
|
+
payer_id, corrected_payer_id))
|
|
159
|
+
processed_payer_ids.add(corrected_payer_id)
|
|
96
160
|
else:
|
|
97
|
-
|
|
98
|
-
|
|
161
|
+
# Only set to "Unknown" if the corrected payer ID is not valid
|
|
162
|
+
crosswalk['payer_id'][corrected_payer_id] = {'name': "Unknown"}
|
|
163
|
+
MediLink_ConfigLoader.log(
|
|
164
|
+
"Failed to validate corrected Payer ID {}. Set to 'Unknown'.".format(corrected_payer_id),
|
|
165
|
+
config,
|
|
166
|
+
level="ERROR"
|
|
167
|
+
)
|
|
168
|
+
print("Payer ID '{}' has been added with name 'Unknown'.".format(corrected_payer_id))
|
|
169
|
+
processed_payer_ids.add(corrected_payer_id)
|
|
170
|
+
else:
|
|
171
|
+
MediLink_ConfigLoader.log(
|
|
172
|
+
"No correction provided for Payer ID {}. Skipping.".format(payer_id),
|
|
173
|
+
config,
|
|
174
|
+
level="WARNING"
|
|
175
|
+
)
|
|
176
|
+
print("No correction provided for Payer ID '{}'. Skipping.".format(payer_id))
|
|
99
177
|
|
|
100
|
-
def initialize_crosswalk_from_mapat():
|
|
178
|
+
def initialize_crosswalk_from_mapat(client):
|
|
101
179
|
"""
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
Compile these mappings into the crosswalk, setting Payer IDs as keys and corresponding Insurance IDs as values.
|
|
108
|
-
|
|
109
|
-
Output: A fully populated crosswalk.json file that serves as a baseline for future updates.
|
|
180
|
+
Initializes the crosswalk from the MAPAT data source. Loads configuration and data sources,
|
|
181
|
+
validates payer IDs, and saves the crosswalk.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
dict: The payer ID mappings from the initialized crosswalk.
|
|
110
185
|
"""
|
|
111
186
|
config, crosswalk = MediLink_ConfigLoader.load_configuration()
|
|
112
|
-
|
|
113
|
-
# Load historical mappings
|
|
114
187
|
try:
|
|
188
|
+
# Load data sources for patient and payer IDs
|
|
115
189
|
patient_id_to_insurance_id, payer_id_to_patient_ids = MediBot_Preprocessor_lib.load_data_sources(config, crosswalk)
|
|
116
190
|
except ValueError as e:
|
|
117
191
|
print(e)
|
|
118
192
|
sys.exit(1)
|
|
119
193
|
|
|
120
|
-
# Map
|
|
194
|
+
# Map payer IDs to insurance IDs
|
|
121
195
|
payer_id_to_details = MediBot_Preprocessor_lib.map_payer_ids_to_insurance_ids(patient_id_to_insurance_id, payer_id_to_patient_ids)
|
|
122
|
-
|
|
123
|
-
# Update the crosswalk for payer IDs only, retaining other mappings
|
|
124
196
|
crosswalk['payer_id'] = payer_id_to_details
|
|
125
197
|
|
|
126
|
-
# Validate payer IDs
|
|
127
|
-
validate_and_correct_payer_ids(crosswalk, config)
|
|
198
|
+
# Validate and correct payer IDs in the crosswalk
|
|
199
|
+
validate_and_correct_payer_ids(client, crosswalk, config)
|
|
128
200
|
|
|
129
|
-
# Save the
|
|
130
|
-
if save_crosswalk(config, crosswalk):
|
|
201
|
+
# Save the crosswalk and log the result
|
|
202
|
+
if save_crosswalk(client, config, crosswalk):
|
|
131
203
|
message = "Crosswalk initialized with mappings for {} payers.".format(len(crosswalk.get('payer_id', {})))
|
|
132
204
|
print(message)
|
|
133
205
|
MediLink_ConfigLoader.log(message, config, level="INFO")
|
|
134
206
|
else:
|
|
135
207
|
print("Failed to save the crosswalk.")
|
|
136
208
|
sys.exit(1)
|
|
137
|
-
|
|
209
|
+
|
|
210
|
+
return crosswalk['payer_id']
|
|
138
211
|
|
|
139
|
-
def
|
|
212
|
+
def load_and_parse_z_data(config):
|
|
213
|
+
"""
|
|
214
|
+
Loads and parses Z data for patient to insurance name mappings from the specified directory.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
config (dict): Configuration settings for logging.
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
dict: A mapping of patient IDs to insurance names.
|
|
140
221
|
"""
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
222
|
+
patient_id_to_insurance_name = {}
|
|
223
|
+
try:
|
|
224
|
+
z_dat_path = config['MediLink_Config']['Z_DAT_PATH']
|
|
225
|
+
MediLink_ConfigLoader.log("Z_DAT_PATH is set to: {}".format(z_dat_path), config, level="DEBUG")
|
|
226
|
+
|
|
227
|
+
# Get the directory of the Z_DAT_PATH
|
|
228
|
+
directory = os.path.dirname(z_dat_path)
|
|
229
|
+
MediLink_ConfigLoader.log("Looking for .DAT files in directory: {}".format(directory), config, level="DEBUG")
|
|
230
|
+
|
|
231
|
+
# List all .DAT files in the directory, case insensitive
|
|
232
|
+
dat_files = [f for f in os.listdir(directory) if f.lower().endswith('.dat')]
|
|
233
|
+
MediLink_ConfigLoader.log("Found {} .DAT files in the directory.".format(len(dat_files)), config, level="DEBUG")
|
|
234
|
+
|
|
235
|
+
# Load processed files tracking
|
|
236
|
+
processed_files_path = os.path.join(directory, 'processed_files.txt')
|
|
237
|
+
if os.path.exists(processed_files_path):
|
|
238
|
+
with open(processed_files_path, 'r') as f:
|
|
239
|
+
processed_files = set(line.strip() for line in f)
|
|
240
|
+
MediLink_ConfigLoader.log("Loaded processed files: {}.".format(processed_files), config, level="DEBUG")
|
|
241
|
+
else:
|
|
242
|
+
processed_files = set()
|
|
243
|
+
MediLink_ConfigLoader.log("No processed files found, starting fresh.", config, level="DEBUG")
|
|
144
244
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
3. Parse incremental data from Z.dat which contains recent user interactions mapping Patient IDs to Insurance Names.
|
|
149
|
-
4. Update the crosswalk using the loaded and parsed data, ensuring each Payer ID maps to the correct Insurance IDs.
|
|
150
|
-
5. Persist the updated mappings back to the crosswalk file.
|
|
245
|
+
# Filter for new .DAT files that haven't been processed yet, but always include Z.DAT and ZM.DAT
|
|
246
|
+
new_dat_files = [f for f in dat_files if f not in processed_files or f.lower() in ['z.dat', 'zm.dat']]
|
|
247
|
+
MediLink_ConfigLoader.log("Identified {} new .DAT files to process.".format(len(new_dat_files)), config, level="INFO")
|
|
151
248
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
249
|
+
for dat_file in new_dat_files:
|
|
250
|
+
file_path = os.path.join(directory, dat_file)
|
|
251
|
+
MediLink_ConfigLoader.log("Parsing .DAT file: {}".format(file_path), config, level="DEBUG")
|
|
252
|
+
# Parse each .DAT file and accumulate results
|
|
253
|
+
insurance_name_mapping = MediBot_Preprocessor_lib.parse_z_dat(file_path, config['MediLink_Config'])
|
|
254
|
+
if insurance_name_mapping: # Ensure insurance_name_mapping is not empty
|
|
255
|
+
patient_id_to_insurance_name.update(insurance_name_mapping)
|
|
155
256
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
257
|
+
# Mark this file as processed
|
|
258
|
+
with open(processed_files_path, 'a') as f:
|
|
259
|
+
f.write(dat_file + '\n')
|
|
260
|
+
MediLink_ConfigLoader.log("Marked file as processed: {}".format(dat_file), config, level="DEBUG")
|
|
261
|
+
|
|
262
|
+
if not patient_id_to_insurance_name: # Check if the result is empty
|
|
263
|
+
raise ValueError("Parsed Z data is empty, possibly indicating an error in parsing or all files already processed.") # TODO Add differentiator here because this is dumb.
|
|
264
|
+
MediLink_ConfigLoader.log("Successfully parsed Z data with {} mappings found.".format(len(patient_id_to_insurance_name)), config, level="INFO")
|
|
265
|
+
return patient_id_to_insurance_name # Ensure the function returns the mapping
|
|
266
|
+
except Exception as e:
|
|
267
|
+
MediLink_ConfigLoader.log("Error loading and parsing Z data: {}".format(e), config, level="ERROR")
|
|
268
|
+
return {}
|
|
269
|
+
|
|
270
|
+
def crosswalk_update(client, config, crosswalk, skip_known_payers=True): # Upstream of this is only MediBot_Preprocessor.py and MediBot.py
|
|
271
|
+
"""
|
|
272
|
+
Updates the crosswalk with insurance data and historical mappings.
|
|
273
|
+
It loads insurance data, historical payer mappings, and updates the crosswalk accordingly.
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
config (dict): Configuration settings for logging.
|
|
277
|
+
crosswalk (dict): The crosswalk dictionary to update.
|
|
278
|
+
skip_known_payers (bool): If True, skips records with 'name' not equal to 'Unknown'.
|
|
162
279
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
MediLink_ConfigLoader.log("
|
|
167
|
-
|
|
168
|
-
# Load
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
280
|
+
Returns:
|
|
281
|
+
bool: True if the crosswalk was updated successfully, False otherwise.
|
|
282
|
+
"""
|
|
283
|
+
MediLink_ConfigLoader.log("Starting crosswalk update process...", config, level="INFO")
|
|
284
|
+
|
|
285
|
+
# Load insurance data from MAINS
|
|
286
|
+
try:
|
|
287
|
+
MediLink_ConfigLoader.log("Attempting to load insurance data from MAINS...", config, level="DEBUG")
|
|
288
|
+
insurance_name_to_id = MediBot_Preprocessor_lib.load_insurance_data_from_mains(config)
|
|
289
|
+
MediLink_ConfigLoader.log("Loaded insurance data from MAINS with {} entries.".format(len(insurance_name_to_id)), config, level="INFO")
|
|
290
|
+
except Exception as e:
|
|
291
|
+
MediLink_ConfigLoader.log("Error loading insurance data from MAINS: {}".format(e), config, level="ERROR")
|
|
292
|
+
return False
|
|
293
|
+
|
|
294
|
+
# Load historical payer to patient mappings
|
|
295
|
+
try:
|
|
296
|
+
MediLink_ConfigLoader.log("Attempting to load historical payer to patient mappings...", config, level="DEBUG")
|
|
297
|
+
patient_id_to_payer_id = MediBot_Preprocessor_lib.load_historical_payer_to_patient_mappings(config)
|
|
298
|
+
MediLink_ConfigLoader.log("Loaded historical mappings with {} entries.".format(len(patient_id_to_payer_id)), config, level="INFO")
|
|
299
|
+
except Exception as e:
|
|
300
|
+
MediLink_ConfigLoader.log("Error loading historical mappings: {}".format(e), config, level="ERROR")
|
|
301
|
+
return False
|
|
302
|
+
|
|
303
|
+
# Parse Z data for patient to insurance name mappings
|
|
304
|
+
try:
|
|
305
|
+
patient_id_to_insurance_name = load_and_parse_z_data(config)
|
|
306
|
+
mapping_count = len(patient_id_to_insurance_name) if patient_id_to_insurance_name is not None else 0
|
|
307
|
+
MediLink_ConfigLoader.log("Parsed Z data with {} mappings found.".format(mapping_count), config, level="INFO")
|
|
308
|
+
except Exception as e:
|
|
309
|
+
MediLink_ConfigLoader.log("Error parsing Z data in crosswalk update: {}".format(e), config, level="ERROR")
|
|
310
|
+
return False
|
|
311
|
+
|
|
312
|
+
# Check if 'payer_id' key exists and is not empty
|
|
313
|
+
MediLink_ConfigLoader.log("Checking for 'payer_id' key in crosswalk...", config, level="DEBUG")
|
|
314
|
+
if 'payer_id' not in crosswalk or not crosswalk['payer_id']:
|
|
315
|
+
MediLink_ConfigLoader.log("The 'payer_id' list is empty or missing.", config, level="WARNING")
|
|
316
|
+
user_input = input(
|
|
317
|
+
"The 'payer_id' list is empty or missing. Would you like to initialize the crosswalk? (yes/no): "
|
|
318
|
+
).strip().lower()
|
|
319
|
+
if user_input in ['yes', 'y']:
|
|
320
|
+
MediLink_ConfigLoader.log("User chose to initialize the crosswalk.", config, level="INFO")
|
|
321
|
+
initialize_crosswalk_from_mapat(client)
|
|
322
|
+
return True # Indicate that the crosswalk was initialized
|
|
323
|
+
else:
|
|
324
|
+
MediLink_ConfigLoader.log("User opted not to initialize the crosswalk.", config, level="WARNING")
|
|
325
|
+
return False # Indicate that the update was not completed
|
|
326
|
+
|
|
327
|
+
# Update the crosswalk with new payer IDs and insurance IDs
|
|
175
328
|
for patient_id, payer_id in patient_id_to_payer_id.items():
|
|
329
|
+
""" TODO this needs to be implemented at some point so we can skip known entities.
|
|
330
|
+
# Skip known payers if the flag is set
|
|
331
|
+
if skip_known_payers:
|
|
332
|
+
payer_id_str = next(iter(payer_id)) # Extract the single payer_id from the set
|
|
333
|
+
MediLink_ConfigLoader.log("Checking if payer_id '{}' is known...".format(payer_id_str), config, level="DEBUG")
|
|
334
|
+
payer_info = crosswalk['payer_id'].get(payer_id_str, {})
|
|
335
|
+
payer_name = payer_info.get('name', "Unknown")
|
|
336
|
+
MediLink_ConfigLoader.log("Retrieved payer name: '{}' for payer_id '{}'.".format(payer_name, payer_id), config, level="DEBUG")
|
|
337
|
+
|
|
338
|
+
if payer_name != "Unknown":
|
|
339
|
+
MediLink_ConfigLoader.log("Skipping known payer_id: '{}' as it is already in the crosswalk.".format(payer_id), config, level="DEBUG")
|
|
340
|
+
continue # Skip this payer_id
|
|
341
|
+
MediLink_ConfigLoader.log("Skipping known payer_id: {} as it is already in the crosswalk.".format(payer_id), config, level="DEBUG")
|
|
342
|
+
continue # Skip this payer_id
|
|
343
|
+
"""
|
|
344
|
+
|
|
176
345
|
insurance_name = patient_id_to_insurance_name.get(patient_id)
|
|
177
346
|
if insurance_name and insurance_name in insurance_name_to_id:
|
|
178
347
|
insurance_id = insurance_name_to_id[insurance_name]
|
|
179
|
-
|
|
180
|
-
#
|
|
181
|
-
MediLink_ConfigLoader.log("
|
|
348
|
+
|
|
349
|
+
# Log the assembly of data
|
|
350
|
+
MediLink_ConfigLoader.log("Assembling data for patient_id '{}': payer_id '{}', insurance_name '{}', insurance_id '{}'.".format(
|
|
351
|
+
patient_id, payer_id, insurance_name, insurance_id), config, level="INFO")
|
|
352
|
+
# Ensure the 'payer_id' key exists in the crosswalk
|
|
182
353
|
if 'payer_id' not in crosswalk:
|
|
183
354
|
crosswalk['payer_id'] = {}
|
|
355
|
+
MediLink_ConfigLoader.log("Initialized 'payer_id' in crosswalk.", config, level="DEBUG")
|
|
356
|
+
|
|
357
|
+
# Initialize the payer ID entry if it doesn't exist
|
|
184
358
|
if payer_id not in crosswalk['payer_id']:
|
|
185
|
-
#
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
359
|
+
# Prompt the user to select an endpoint name or use the default
|
|
360
|
+
endpoint_options = list(config['MediLink_Config']['endpoints'].keys())
|
|
361
|
+
print("Available endpoints:")
|
|
362
|
+
for idx, key in enumerate(endpoint_options):
|
|
363
|
+
print("{0}: {1}".format(idx + 1, config['MediLink_Config']['endpoints'][key]['name']))
|
|
364
|
+
user_choice = input("Select an endpoint by number (or press Enter to use the default): ").strip()
|
|
365
|
+
|
|
366
|
+
if user_choice.isdigit() and 1 <= int(user_choice) <= len(endpoint_options):
|
|
367
|
+
selected_endpoint = config['MediLink_Config']['endpoints'][endpoint_options[int(user_choice) - 1]]['name']
|
|
368
|
+
else:
|
|
369
|
+
selected_endpoint = config['MediLink_Config']['endpoints'][endpoint_options[0]]['name']
|
|
370
|
+
MediLink_ConfigLoader.log("User opted for default endpoint: {}".format(selected_endpoint), config, level="INFO")
|
|
371
|
+
|
|
372
|
+
crosswalk['payer_id'][payer_id] = {
|
|
373
|
+
'endpoint': selected_endpoint,
|
|
374
|
+
'medisoft_id': set(), # Use set to store multiple IDs
|
|
375
|
+
'medisoft_medicare_id': set()
|
|
376
|
+
}
|
|
377
|
+
MediLink_ConfigLoader.log("Initialized payer ID {} in crosswalk with endpoint '{}'.".format(payer_id, selected_endpoint), config, level="DEBUG")
|
|
378
|
+
|
|
379
|
+
# Add the insurance ID to the payer ID entry
|
|
380
|
+
crosswalk['payer_id'][payer_id]['medisoft_id'].add(str(insurance_id)) # Ensure IDs are strings
|
|
381
|
+
MediLink_ConfigLoader.log(
|
|
382
|
+
"Added new insurance ID {} to payer ID {}.".format(insurance_id, payer_id),
|
|
383
|
+
config,
|
|
384
|
+
level="INFO"
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
# Log the update of the crosswalk
|
|
388
|
+
MediLink_ConfigLoader.log("Updated crosswalk for payer_id '{}': added insurance_id '{}'.".format(payer_id, insurance_id), config, level="DEBUG")
|
|
389
|
+
|
|
390
|
+
# Fetch and store the payer name
|
|
391
|
+
MediLink_ConfigLoader.log("Fetching and storing payer name for payer_id: {}".format(payer_id), config, level="DEBUG")
|
|
392
|
+
fetch_and_store_payer_name(client, payer_id, crosswalk, config)
|
|
393
|
+
MediLink_ConfigLoader.log("Successfully fetched and stored payer name for payer_id: {}".format(payer_id), config, level="INFO")
|
|
201
394
|
|
|
202
|
-
|
|
203
|
-
"
|
|
204
|
-
|
|
395
|
+
# Validate and correct payer IDs in the crosswalk
|
|
396
|
+
MediLink_ConfigLoader.log("Validating and correcting payer IDs in the crosswalk.", config, level="DEBUG")
|
|
397
|
+
validate_and_correct_payer_ids(client, crosswalk, config)
|
|
398
|
+
|
|
399
|
+
# Check for any entries marked as "Unknown" and validate them
|
|
400
|
+
unknown_payers = [
|
|
401
|
+
payer_id for payer_id, details in crosswalk.get('payer_id', {}).items()
|
|
402
|
+
if details.get('name') == "Unknown"
|
|
403
|
+
]
|
|
404
|
+
MediLink_ConfigLoader.log("Found {} unknown payer(s) to validate.".format(len(unknown_payers)), config, level="INFO")
|
|
405
|
+
for payer_id in unknown_payers:
|
|
406
|
+
MediLink_ConfigLoader.log("Fetching and storing payer name for unknown payer_id: {}".format(payer_id), config, level="DEBUG")
|
|
407
|
+
fetch_and_store_payer_name(client, payer_id, crosswalk, config)
|
|
408
|
+
MediLink_ConfigLoader.log("Successfully fetched and stored payer name for unknown payer_id: {}".format(payer_id), config, level="INFO")
|
|
409
|
+
|
|
410
|
+
# Ensure multiple medisoft_id values are preserved by converting sets to sorted lists
|
|
411
|
+
for payer_id, details in crosswalk.get('payer_id', {}).items():
|
|
412
|
+
if isinstance(details.get('medisoft_id'), set):
|
|
413
|
+
crosswalk['payer_id'][payer_id]['medisoft_id'] = sorted(list(details['medisoft_id']))
|
|
414
|
+
MediLink_ConfigLoader.log("Converted medisoft_id for payer ID {} to sorted list.".format(payer_id), config, level="DEBUG")
|
|
415
|
+
if isinstance(details.get('medisoft_medicare_id'), set):
|
|
416
|
+
crosswalk['payer_id'][payer_id]['medisoft_medicare_id'] = sorted(list(details['medisoft_medicare_id']))
|
|
417
|
+
MediLink_ConfigLoader.log("Converted medisoft_medicare_id for payer ID {} to sorted list.".format(payer_id), config, level="DEBUG")
|
|
418
|
+
|
|
419
|
+
MediLink_ConfigLoader.log("Crosswalk update process completed. Processed {} payer IDs.".format(len(patient_id_to_payer_id)), config, level="INFO")
|
|
420
|
+
return save_crosswalk(client, config, crosswalk)
|
|
421
|
+
|
|
422
|
+
def update_crosswalk_with_corrected_payer_id(client, old_payer_id, corrected_payer_id, config=None, crosswalk=None):
|
|
423
|
+
"""
|
|
424
|
+
Updates the crosswalk by replacing an old payer ID with a corrected payer ID.
|
|
425
|
+
|
|
426
|
+
Args:
|
|
427
|
+
old_payer_id (str): The old payer ID to be replaced.
|
|
428
|
+
corrected_payer_id (str): The new payer ID to replace the old one.
|
|
429
|
+
config (dict, optional): Configuration settings for logging.
|
|
430
|
+
crosswalk (dict, optional): The crosswalk dictionary to update.
|
|
431
|
+
|
|
432
|
+
Returns:
|
|
433
|
+
bool: True if the crosswalk was updated successfully, False otherwise.
|
|
434
|
+
"""
|
|
435
|
+
if config is None or crosswalk is None:
|
|
436
|
+
config, crosswalk = MediLink_ConfigLoader.load_configuration()
|
|
437
|
+
MediLink_ConfigLoader.log("Loaded configuration and crosswalk.", config, level="DEBUG")
|
|
438
|
+
|
|
439
|
+
# Convert to a regular dict if crosswalk['payer_id'] is an OrderedDict
|
|
440
|
+
if isinstance(crosswalk['payer_id'], dict) and hasattr(crosswalk['payer_id'], 'items'):
|
|
441
|
+
crosswalk['payer_id'] = dict(crosswalk['payer_id'])
|
|
442
|
+
|
|
443
|
+
MediLink_ConfigLoader.log("Checking if old Payer ID {} exists in crosswalk.".format(old_payer_id), config, level="DEBUG")
|
|
444
|
+
|
|
445
|
+
MediLink_ConfigLoader.log("Attempting to replace old Payer ID {} with corrected Payer ID {}.".format(old_payer_id, corrected_payer_id), config, level="DEBUG")
|
|
446
|
+
|
|
447
|
+
# Check if the old payer ID exists before attempting to replace
|
|
205
448
|
if old_payer_id in crosswalk['payer_id']:
|
|
206
|
-
|
|
207
|
-
|
|
449
|
+
MediLink_ConfigLoader.log("Old Payer ID {} found. Proceeding with replacement.".format(old_payer_id), config, level="DEBUG")
|
|
450
|
+
|
|
451
|
+
# Store the details of the old payer ID
|
|
452
|
+
old_payer_details = crosswalk['payer_id'][old_payer_id]
|
|
453
|
+
MediLink_ConfigLoader.log("Storing details of old Payer ID {}: {}".format(old_payer_id, old_payer_details), config, level="DEBUG")
|
|
454
|
+
|
|
455
|
+
# Replace the old payer ID with the corrected one
|
|
456
|
+
crosswalk['payer_id'][corrected_payer_id] = old_payer_details
|
|
457
|
+
MediLink_ConfigLoader.log("Replaced old Payer ID {} with corrected Payer ID {}.".format(old_payer_id, corrected_payer_id), config, level="INFO")
|
|
458
|
+
|
|
459
|
+
# Remove the old payer ID from the crosswalk
|
|
460
|
+
del crosswalk['payer_id'][old_payer_id]
|
|
461
|
+
MediLink_ConfigLoader.log("Removed old Payer ID {} from crosswalk.".format(old_payer_id), config, level="DEBUG")
|
|
462
|
+
|
|
463
|
+
# Fetch and store the payer name for the corrected ID
|
|
464
|
+
if fetch_and_store_payer_name(client, corrected_payer_id, crosswalk, config):
|
|
465
|
+
MediLink_ConfigLoader.log("Successfully fetched and stored payer name for corrected Payer ID {}.".format(corrected_payer_id), config, level="INFO")
|
|
466
|
+
else:
|
|
467
|
+
MediLink_ConfigLoader.log("Corrected Payer ID {} updated without a valid name.".format(corrected_payer_id), config, level="WARNING")
|
|
468
|
+
|
|
469
|
+
# Update csv_replacements
|
|
470
|
+
crosswalk.setdefault('csv_replacements', {})[old_payer_id] = corrected_payer_id
|
|
471
|
+
MediLink_ConfigLoader.log("Updated csv_replacements: {} -> {}.".format(old_payer_id, corrected_payer_id), config, level="INFO")
|
|
472
|
+
print("csv_replacements updated: '{}' -> '{}'.".format(old_payer_id, corrected_payer_id))
|
|
473
|
+
|
|
474
|
+
return save_crosswalk(client, config, crosswalk)
|
|
208
475
|
else:
|
|
209
|
-
MediLink_ConfigLoader.log("Failed to update crosswalk:
|
|
476
|
+
MediLink_ConfigLoader.log("Failed to update crosswalk: old Payer ID {} not found.".format(old_payer_id), config, level="ERROR")
|
|
477
|
+
print("Failed to update crosswalk: could not find old Payer ID '{}'.".format(old_payer_id))
|
|
210
478
|
return False
|
|
211
479
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
crosswalk['csv_replacements'][old_payer_id] = corrected_payer_id
|
|
216
|
-
MediLink_ConfigLoader.log("Crosswalk csv_replacements updated: added {} -> {}".format(old_payer_id, corrected_payer_id), config, level="INFO")
|
|
480
|
+
def update_crosswalk_with_new_payer_id(client, insurance_name, payer_id, config):
|
|
481
|
+
"""
|
|
482
|
+
Updates the crosswalk with a new payer ID for a given insurance name.
|
|
217
483
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
"""
|
|
484
|
+
Args:
|
|
485
|
+
insurance_name (str): The name of the insurance to associate with the new payer ID.
|
|
486
|
+
payer_id (str): The new payer ID to be added.
|
|
487
|
+
config (dict): Configuration settings for logging.
|
|
488
|
+
"""
|
|
223
489
|
_, crosswalk = MediLink_ConfigLoader.load_configuration(None, config.get('crosswalkPath', 'crosswalk.json'))
|
|
490
|
+
MediLink_ConfigLoader.log("Loaded crosswalk configuration from {}.".format(config.get('crosswalkPath', 'crosswalk.json')), config, level="DEBUG")
|
|
491
|
+
|
|
492
|
+
# Load the Medisoft ID for the given insurance name
|
|
224
493
|
medisoft_id = MediBot_Preprocessor_lib.load_insurance_data_from_mains(config).get(insurance_name)
|
|
494
|
+
MediLink_ConfigLoader.log("Retrieved Medisoft ID for insurance name {}: {}.".format(insurance_name, medisoft_id), config, level="DEBUG")
|
|
225
495
|
|
|
226
496
|
if medisoft_id:
|
|
227
497
|
medisoft_id_str = str(medisoft_id)
|
|
498
|
+
|
|
499
|
+
# Initialize the payer ID entry if it doesn't exist
|
|
228
500
|
if payer_id not in crosswalk['payer_id']:
|
|
229
501
|
crosswalk['payer_id'][payer_id] = {"medisoft_id": [medisoft_id_str], "medisoft_medicare_id": []}
|
|
502
|
+
MediLink_ConfigLoader.log("Initialized new payer ID {} in crosswalk.".format(payer_id), config, level="INFO")
|
|
230
503
|
else:
|
|
231
504
|
crosswalk['payer_id'][payer_id]['medisoft_id'].append(medisoft_id_str)
|
|
232
|
-
|
|
233
|
-
|
|
505
|
+
MediLink_ConfigLoader.log("Appended Medisoft ID {} to existing payer ID {}.".format(medisoft_id_str, payer_id), config, level="INFO")
|
|
506
|
+
|
|
507
|
+
# Fetch and store the payer name for the new payer ID
|
|
508
|
+
if fetch_and_store_payer_name(client, payer_id, crosswalk, config):
|
|
509
|
+
MediLink_ConfigLoader.log("Updated crosswalk with new payer ID {} for insurance name {}.".format(payer_id, insurance_name), config, level="INFO")
|
|
510
|
+
else:
|
|
511
|
+
MediLink_ConfigLoader.log("Added new payer ID {} without a valid name for insurance name {}.".format(payer_id, insurance_name), config, level="WARNING")
|
|
512
|
+
|
|
513
|
+
# Save the updated crosswalk
|
|
514
|
+
save_crosswalk(client, config, crosswalk)
|
|
234
515
|
else:
|
|
235
|
-
message = "Failed to update crosswalk: Medisoft ID not found for insurance name {}".format(insurance_name)
|
|
516
|
+
message = "Failed to update crosswalk: Medisoft ID not found for insurance name {}.".format(insurance_name)
|
|
236
517
|
print(message)
|
|
237
518
|
MediLink_ConfigLoader.log(message, config, level="ERROR")
|
|
238
|
-
|
|
239
|
-
def save_crosswalk(config, crosswalk):
|
|
519
|
+
|
|
520
|
+
def save_crosswalk(client, config, crosswalk):
|
|
240
521
|
"""
|
|
241
|
-
Saves the
|
|
522
|
+
Saves the crosswalk to a JSON file. Ensures that all necessary keys are present and logs the outcome.
|
|
523
|
+
|
|
242
524
|
Args:
|
|
243
|
-
|
|
244
|
-
crosswalk (dict): The
|
|
525
|
+
config (dict): Configuration settings for logging.
|
|
526
|
+
crosswalk (dict): The crosswalk dictionary to save.
|
|
527
|
+
|
|
245
528
|
Returns:
|
|
246
|
-
bool: True if the
|
|
529
|
+
bool: True if the crosswalk was saved successfully, False otherwise.
|
|
247
530
|
"""
|
|
248
|
-
# Attempt to fetch crosswalkPath from MediLink_Config
|
|
249
531
|
try:
|
|
532
|
+
# Determine the path to save the crosswalk
|
|
250
533
|
crosswalk_path = config['MediLink_Config']['crosswalkPath']
|
|
534
|
+
MediLink_ConfigLoader.log("Determined crosswalk path: {}.".format(crosswalk_path), config, level="DEBUG")
|
|
251
535
|
except KeyError:
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
536
|
+
crosswalk_path = config.get('crosswalkPath', 'crosswalk.json')
|
|
537
|
+
MediLink_ConfigLoader.log("Using default crosswalk path: {}.".format(crosswalk_path), config, level="DEBUG")
|
|
538
|
+
|
|
255
539
|
try:
|
|
256
|
-
# Initialize 'payer_id' key if
|
|
257
|
-
if 'payer_id' not in crosswalk:
|
|
540
|
+
# Initialize the 'payer_id' key if it doesn't exist
|
|
541
|
+
if 'payer_id' not in crosswalk:
|
|
258
542
|
print("save_crosswalk is initializing 'payer_id' key...")
|
|
259
543
|
crosswalk['payer_id'] = {}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
544
|
+
MediLink_ConfigLoader.log("Initialized 'payer_id' key in crosswalk.", config, level="INFO")
|
|
545
|
+
|
|
546
|
+
# Ensure all payer IDs have a name and initialize medisoft_id and medisoft_medicare_id as empty lists if they do not exist
|
|
547
|
+
for payer_id in crosswalk['payer_id']:
|
|
548
|
+
if 'name' not in crosswalk['payer_id'][payer_id]:
|
|
549
|
+
fetch_and_store_payer_name(client, payer_id, crosswalk, config)
|
|
550
|
+
MediLink_ConfigLoader.log("Fetched and stored payer name for payer ID: {}.".format(payer_id), config, level="DEBUG")
|
|
551
|
+
|
|
552
|
+
# Initialize medisoft_id and medisoft_medicare_id as empty lists if they do not exist
|
|
553
|
+
if 'medisoft_id' not in crosswalk['payer_id'][payer_id]:
|
|
554
|
+
crosswalk['payer_id'][payer_id]['medisoft_id'] = []
|
|
555
|
+
MediLink_ConfigLoader.log("Initialized 'medisoft_id' for payer ID {} as an empty list.".format(payer_id), config, level="DEBUG")
|
|
556
|
+
if 'medisoft_medicare_id' not in crosswalk['payer_id'][payer_id]:
|
|
557
|
+
crosswalk['payer_id'][payer_id]['medisoft_medicare_id'] = []
|
|
558
|
+
MediLink_ConfigLoader.log("Initialized 'medisoft_medicare_id' for payer ID {} as an empty list.".format(payer_id), config, level="DEBUG")
|
|
559
|
+
|
|
560
|
+
# Convert sets to sorted lists for JSON serialization
|
|
561
|
+
for payer_id, details in crosswalk.get('payer_id', {}).items():
|
|
562
|
+
if isinstance(details.get('medisoft_id'), set):
|
|
563
|
+
crosswalk['payer_id'][payer_id]['medisoft_id'] = sorted(list(details['medisoft_id']))
|
|
564
|
+
MediLink_ConfigLoader.log("Converted medisoft_id for payer ID {} to sorted list.".format(payer_id), config, level="DEBUG")
|
|
565
|
+
if isinstance(details.get('medisoft_medicare_id'), set):
|
|
566
|
+
crosswalk['payer_id'][payer_id]['medisoft_medicare_id'] = sorted(list(details['medisoft_medicare_id']))
|
|
567
|
+
MediLink_ConfigLoader.log("Converted medisoft_medicare_id for payer ID {} to sorted list.".format(payer_id), config, level="DEBUG")
|
|
568
|
+
|
|
569
|
+
# Write the crosswalk to the specified file
|
|
266
570
|
with open(crosswalk_path, 'w') as file:
|
|
267
|
-
json.dump(crosswalk, file, indent=4)
|
|
571
|
+
json.dump(crosswalk, file, indent=4)
|
|
572
|
+
|
|
573
|
+
MediLink_ConfigLoader.log("Crosswalk saved successfully to {}.".format(crosswalk_path), config, level="INFO")
|
|
268
574
|
return True
|
|
269
|
-
|
|
270
575
|
except KeyError as e:
|
|
271
|
-
|
|
272
|
-
|
|
576
|
+
print("Key Error: A required key is missing in the crosswalk data - {}.".format(e))
|
|
577
|
+
MediLink_ConfigLoader.log("Key Error while saving crosswalk: {}.".format(e), config, level="ERROR")
|
|
273
578
|
return False
|
|
274
|
-
|
|
275
579
|
except TypeError as e:
|
|
276
|
-
|
|
277
|
-
|
|
580
|
+
print("Type Error: There was a type issue with the data being saved in the crosswalk - {}.".format(e))
|
|
581
|
+
MediLink_ConfigLoader.log("Type Error while saving crosswalk: {}.".format(e), config, level="ERROR")
|
|
278
582
|
return False
|
|
279
|
-
|
|
280
583
|
except IOError as e:
|
|
281
|
-
|
|
282
|
-
|
|
584
|
+
print("I/O Error: An error occurred while writing to the crosswalk file - {}.".format(e))
|
|
585
|
+
MediLink_ConfigLoader.log("I/O Error while saving crosswalk: {}.".format(e), config, level="ERROR")
|
|
283
586
|
return False
|
|
284
|
-
|
|
285
587
|
except Exception as e:
|
|
286
|
-
|
|
287
|
-
|
|
588
|
+
print("Unexpected crosswalk error: {}.".format(e))
|
|
589
|
+
MediLink_ConfigLoader.log("Unexpected error while saving crosswalk: {}.".format(e), config, level="ERROR")
|
|
288
590
|
return False
|