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,13 +1,11 @@
|
|
|
1
|
+
# MediLink_837p_encoder_library.py
|
|
1
2
|
from datetime import datetime
|
|
2
|
-
import sys
|
|
3
|
-
from MediLink import MediLink_ConfigLoader
|
|
4
|
-
|
|
5
|
-
# Add parent directory of the project to the Python path
|
|
6
|
-
import sys
|
|
7
|
-
import os
|
|
3
|
+
import sys, os
|
|
4
|
+
from MediLink import MediLink_ConfigLoader
|
|
8
5
|
|
|
9
6
|
project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
10
|
-
sys.path
|
|
7
|
+
if project_dir not in sys.path:
|
|
8
|
+
sys.path.append(project_dir)
|
|
11
9
|
|
|
12
10
|
from MediBot import MediBot_Preprocessor_lib
|
|
13
11
|
load_insurance_data_from_mains = MediBot_Preprocessor_lib.load_insurance_data_from_mains
|
|
@@ -154,9 +152,10 @@ def create_1000A_submitter_name_segment(patient_data, config, endpoint):
|
|
|
154
152
|
# Submitter contact details
|
|
155
153
|
contact_name = config.get('submitter_name', 'NONE')
|
|
156
154
|
contact_telephone_number = config.get('submitter_tel', 'NONE')
|
|
155
|
+
entity_type_qualifier = '2' # if contact_name else '1' BUG - 1 if submitter_first_name is not empty.
|
|
157
156
|
|
|
158
157
|
# Construct NM1 segment for the submitter
|
|
159
|
-
nm1_segment = "NM1*41*
|
|
158
|
+
nm1_segment = "NM1*41*{}*{}*****{}*{}~".format(entity_type_qualifier, submitter_name, submitter_id_qualifier, submitter_id)
|
|
160
159
|
|
|
161
160
|
# Construct PER segment for the submitter's contact information
|
|
162
161
|
per_segment = "PER*IC*{}*TE*{}~".format(contact_name, contact_telephone_number)
|
|
@@ -182,7 +181,7 @@ def create_1000B_receiver_name_segment(config, endpoint):
|
|
|
182
181
|
receiver_edi=receiver_edi
|
|
183
182
|
)
|
|
184
183
|
|
|
185
|
-
def payer_id_to_payer_name(parsed_data, config, endpoint):
|
|
184
|
+
def payer_id_to_payer_name(parsed_data, config, endpoint, crosswalk, client):
|
|
186
185
|
"""
|
|
187
186
|
Preprocesses payer information from parsed data and enriches parsed_data with the payer name and ID.
|
|
188
187
|
|
|
@@ -198,7 +197,7 @@ def payer_id_to_payer_name(parsed_data, config, endpoint):
|
|
|
198
197
|
insurance_name = parsed_data.get('INAME', '')
|
|
199
198
|
|
|
200
199
|
# Step 2: Map insurance name to payer ID
|
|
201
|
-
payer_id = map_insurance_name_to_payer_id(insurance_name, config)
|
|
200
|
+
payer_id = map_insurance_name_to_payer_id(insurance_name, config, client)
|
|
202
201
|
|
|
203
202
|
# Step 3: Validate payer_id
|
|
204
203
|
if payer_id is None:
|
|
@@ -207,7 +206,7 @@ def payer_id_to_payer_name(parsed_data, config, endpoint):
|
|
|
207
206
|
raise ValueError(error_message)
|
|
208
207
|
|
|
209
208
|
# Step 4: Resolve payer name using payer ID
|
|
210
|
-
payer_name = resolve_payer_name(payer_id, config, endpoint, insurance_name, parsed_data)
|
|
209
|
+
payer_name = resolve_payer_name(payer_id, config, endpoint, insurance_name, parsed_data, crosswalk, client)
|
|
211
210
|
|
|
212
211
|
# Enrich parsed_data with payer name and payer ID
|
|
213
212
|
parsed_data['payer_name'] = payer_name
|
|
@@ -238,74 +237,141 @@ def create_2010BB_payer_information_segment(parsed_data):
|
|
|
238
237
|
# Build NM1 segment using provided payer name and payer ID
|
|
239
238
|
return build_nm1_segment(payer_name, payer_id)
|
|
240
239
|
|
|
241
|
-
def
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
parsed_data (dict): Parsed data containing patient information.
|
|
251
|
-
|
|
252
|
-
Returns:
|
|
253
|
-
str: The resolved payer name.
|
|
254
|
-
"""
|
|
240
|
+
def get_user_confirmation(prompt_message):
|
|
241
|
+
while True:
|
|
242
|
+
response = input(prompt_message).strip().lower()
|
|
243
|
+
if response in ['yes', 'y']:
|
|
244
|
+
return True
|
|
245
|
+
elif response in ['no', 'n']:
|
|
246
|
+
return False
|
|
247
|
+
else:
|
|
248
|
+
print("Please respond with 'yes' or 'no'.")
|
|
255
249
|
|
|
250
|
+
def resolve_payer_name(payer_id, config, primary_endpoint, insurance_name, parsed_data, crosswalk, client):
|
|
251
|
+
# Check if the payer_id is in the crosswalk with a name already attached to it.
|
|
252
|
+
if payer_id in crosswalk.get('payer_id', {}):
|
|
253
|
+
payer_info = crosswalk['payer_id'][payer_id]
|
|
254
|
+
MediLink_ConfigLoader.log("Payer ID {} found in crosswalk with name: {}".format(payer_id, payer_info['name']), level="DEBUG")
|
|
255
|
+
return payer_info['name'] # Return the name from the crosswalk directly.
|
|
256
|
+
|
|
256
257
|
# Step 1: Attempt to fetch payer name from API using primary endpoint
|
|
257
258
|
MediLink_ConfigLoader.log("Attempting to resolve Payer ID {} via API.".format(payer_id), level="INFO")
|
|
258
259
|
try:
|
|
259
|
-
return fetch_payer_name_from_api(payer_id, config, primary_endpoint)
|
|
260
|
+
return fetch_payer_name_from_api(client, payer_id, config, primary_endpoint)
|
|
260
261
|
except Exception as api_error:
|
|
261
262
|
# Step 2: Log API resolution failure and initiate user intervention
|
|
262
263
|
MediLink_ConfigLoader.log("API resolution failed for {}: {}. Initiating user intervention.".format(payer_id, str(api_error)), config, level="WARNING")
|
|
263
264
|
|
|
264
265
|
# Step 3: Print warning message for user intervention
|
|
265
266
|
print("\n\nWARNING: Unable to verify Payer ID '{}' for patient '{}'!".format(payer_id, parsed_data.get('CHART', 'unknown')))
|
|
266
|
-
print(" Claims for '{}' may be incorrectly
|
|
267
|
-
print("\nACTION REQUIRED: Please verify the internet connection and the Payer ID by searching for it")
|
|
268
|
-
print("at the expected endpoint's website or using Google.")
|
|
267
|
+
print(" Claims for '{}' may be incorrectly routed or fail without intervention.".format(insurance_name))
|
|
268
|
+
print("\nACTION REQUIRED: Please verify the internet connection and the Payer ID by searching for it at the expected endpoint's website or using Google.")
|
|
269
269
|
print("\nNote: If the Payer ID '{}' is incorrect for '{}', \nit may need to be manually corrected.".format(payer_id, insurance_name))
|
|
270
270
|
print("If the Payer ID appears correct, you may skip the correction and force-continue with this one.")
|
|
271
271
|
print("\nPlease check the Payer ID in the Crosswalk and the initial \ndata source (e.g., Carol's CSV) as needed.")
|
|
272
272
|
print("If unsure, llamar a Dani for guidance on manual corrections.")
|
|
273
|
-
|
|
273
|
+
|
|
274
274
|
# Step 4: Integrate user input logic
|
|
275
|
-
user_decision = input("\nType 'FORCE' to force-continue with the Medisoft name,
|
|
276
|
-
|
|
275
|
+
user_decision = input("\nType 'FORCE' to force-continue with the Medisoft name, or press Enter to pause processing and make corrections: ").strip().lower()
|
|
276
|
+
|
|
277
277
|
if user_decision == 'force':
|
|
278
278
|
# Step 5: Fallback to truncated insurance name
|
|
279
279
|
truncated_name = insurance_name[:10] # Temporary fallback
|
|
280
280
|
MediLink_ConfigLoader.log("Using truncated insurance name '{}' as a fallback for {}".format(truncated_name, payer_id), config, level="WARNING")
|
|
281
281
|
return truncated_name
|
|
282
|
-
elif not user_decision:
|
|
282
|
+
elif not user_decision:
|
|
283
|
+
# Step 6: Prompt user for corrected payer ID
|
|
283
284
|
corrected_payer_id = prompt_user_for_payer_id(insurance_name)
|
|
284
285
|
if corrected_payer_id:
|
|
285
286
|
try:
|
|
286
|
-
resolved_name = fetch_payer_name_from_api(corrected_payer_id, config, primary_endpoint)
|
|
287
|
+
resolved_name = fetch_payer_name_from_api(client, corrected_payer_id, config, primary_endpoint)
|
|
287
288
|
print("API resolved to insurance name: {}".format(resolved_name))
|
|
288
289
|
MediLink_ConfigLoader.log("API Resolved to standard insurance name: {} for corrected payer ID: {}".format(resolved_name, corrected_payer_id), config, level="INFO")
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
if
|
|
293
|
-
|
|
290
|
+
|
|
291
|
+
# Step 7: Ask for user confirmation using the helper
|
|
292
|
+
confirmation_prompt = "Is the standard insurance name '{}' correct? (yes/no): ".format(resolved_name)
|
|
293
|
+
if get_user_confirmation(confirmation_prompt):
|
|
294
|
+
# Step 8: Load crosswalk
|
|
295
|
+
try:
|
|
296
|
+
config, crosswalk = MediLink_ConfigLoader.load_configuration()
|
|
297
|
+
except Exception as e:
|
|
298
|
+
print("Failed to load configuration and crosswalk: {}".format(e))
|
|
299
|
+
MediLink_ConfigLoader.log("Failed to load configuration and crosswalk: {}".format(e), config, level="ERROR")
|
|
300
|
+
exit(1)
|
|
301
|
+
|
|
302
|
+
# Step 9: Update the crosswalk with the corrected Payer ID
|
|
303
|
+
if MediBot_Crosswalk_Library.update_crosswalk_with_corrected_payer_id(client, payer_id, corrected_payer_id, config, crosswalk):
|
|
294
304
|
return resolved_name
|
|
295
305
|
else:
|
|
296
306
|
print("Failed to update crosswalk with the corrected Payer ID.")
|
|
297
|
-
|
|
307
|
+
MediLink_ConfigLoader.log("Failed to update crosswalk with the corrected Payer ID.", config, level="ERROR")
|
|
308
|
+
exit(1) # Consider handling failure differently.
|
|
298
309
|
else:
|
|
310
|
+
# Step 10: Handle rejection
|
|
299
311
|
print("User did not confirm the standard insurance name. Manual intervention is required.")
|
|
300
312
|
MediLink_ConfigLoader.log("User did not confirm the standard insurance name. Manual intervention is required.", config, level="CRITICAL")
|
|
301
|
-
exit(1)
|
|
313
|
+
exit(1) # Consider handling differently.
|
|
302
314
|
except Exception as e:
|
|
315
|
+
# Step 11: Handle exceptions during resolution
|
|
303
316
|
print("Failed to resolve corrected payer ID to standard insurance name: {}".format(e))
|
|
304
317
|
MediLink_ConfigLoader.log("Failed to resolve corrected payer ID to standard insurance name: {}".format(e), config, level="ERROR")
|
|
305
|
-
exit(1)
|
|
318
|
+
exit(1) # Consider handling differently.
|
|
306
319
|
else:
|
|
320
|
+
# Step 12: Handle absence of corrected payer ID
|
|
307
321
|
print("Exiting script. Please make the necessary corrections and retry.")
|
|
308
|
-
|
|
322
|
+
MediLink_ConfigLoader.log("Exiting script due to absence of corrected Payer ID.", config, level="CRITICAL")
|
|
323
|
+
exit(1) # Consider handling differently.
|
|
324
|
+
else:
|
|
325
|
+
# Optional: Handle unexpected user input
|
|
326
|
+
print("Invalid input. Manual intervention is required.")
|
|
327
|
+
MediLink_ConfigLoader.log("Invalid user input during payer name resolution.", config, level="CRITICAL")
|
|
328
|
+
exit(1) # Consider handling differently.
|
|
329
|
+
|
|
330
|
+
def handle_missing_payer_id(insurance_name, config, crosswalk, client):
|
|
331
|
+
# Step 1: Inform about the missing Payer ID
|
|
332
|
+
print("Missing Payer ID for insurance name: {}".format(insurance_name))
|
|
333
|
+
MediLink_ConfigLoader.log("Missing Payer ID for insurance name: {}".format(insurance_name), config, level="WARNING")
|
|
334
|
+
|
|
335
|
+
# Step 2: Prompt the user for manual payer ID input
|
|
336
|
+
payer_id = prompt_user_for_payer_id(insurance_name)
|
|
337
|
+
|
|
338
|
+
if not payer_id:
|
|
339
|
+
# Step 3: Handle absence of payer ID input
|
|
340
|
+
message = "Unable to resolve missing Payer ID. Manual intervention is required."
|
|
341
|
+
MediLink_ConfigLoader.log(message, config, level="CRITICAL")
|
|
342
|
+
print(message)
|
|
343
|
+
return None
|
|
344
|
+
|
|
345
|
+
# Step 4: Resolve the payer ID to a standard insurance name via API
|
|
346
|
+
try:
|
|
347
|
+
# primary_endpoint=None should kick to the default in the API function.
|
|
348
|
+
standard_insurance_name = resolve_payer_name(payer_id, config, primary_endpoint=None, insurance_name=insurance_name, parsed_data={}, crosswalk=crosswalk, client=client)
|
|
349
|
+
message = "Resolved to standard insurance name: {} for payer ID: {}".format(standard_insurance_name, payer_id)
|
|
350
|
+
print(message)
|
|
351
|
+
MediLink_ConfigLoader.log(message, config, level="INFO")
|
|
352
|
+
except Exception as e:
|
|
353
|
+
# Step 5: Handle exceptions during resolution
|
|
354
|
+
message = "Failed to resolve payer ID to standard insurance name: {}".format(e)
|
|
355
|
+
print(message)
|
|
356
|
+
MediLink_ConfigLoader.log(message, config, level="ERROR")
|
|
357
|
+
return None
|
|
358
|
+
|
|
359
|
+
# Step 6: Ask for user confirmation
|
|
360
|
+
confirmation_prompt = "Is the standard insurance name '{}' correct? (yes/no): ".format(standard_insurance_name)
|
|
361
|
+
if get_user_confirmation(confirmation_prompt):
|
|
362
|
+
# Step 7: Update the crosswalk with the new payer ID and insurance name mapping
|
|
363
|
+
try:
|
|
364
|
+
MediBot_Crosswalk_Library.update_crosswalk_with_new_payer_id(insurance_name, payer_id, config)
|
|
365
|
+
return payer_id
|
|
366
|
+
except Exception as e:
|
|
367
|
+
print("Failed to update crosswalk with new Payer ID: {}".format(e))
|
|
368
|
+
MediLink_ConfigLoader.log("Failed to update crosswalk with new Payer ID: {}".format(e), config, level="ERROR")
|
|
369
|
+
return None
|
|
370
|
+
else:
|
|
371
|
+
# Step 8: Handle rejection
|
|
372
|
+
print("User did not confirm the standard insurance name. Manual intervention is required.")
|
|
373
|
+
MediLink_ConfigLoader.log("User did not confirm the standard insurance name. Manual intervention is required.", config, level="CRITICAL")
|
|
374
|
+
return None
|
|
309
375
|
|
|
310
376
|
def prompt_user_for_payer_id(insurance_name):
|
|
311
377
|
"""
|
|
@@ -324,7 +390,7 @@ def build_nm1_segment(payer_name, payer_id):
|
|
|
324
390
|
# Step 1: Build NM1 segment using payer name and ID
|
|
325
391
|
return "NM1*PR*2*{}*****PI*{}~".format(payer_name, payer_id)
|
|
326
392
|
|
|
327
|
-
def map_insurance_name_to_payer_id(insurance_name, config):
|
|
393
|
+
def map_insurance_name_to_payer_id(insurance_name, config, client):
|
|
328
394
|
"""
|
|
329
395
|
Maps insurance name to payer ID using the crosswalk configuration.
|
|
330
396
|
|
|
@@ -335,13 +401,15 @@ def map_insurance_name_to_payer_id(insurance_name, config):
|
|
|
335
401
|
Returns:
|
|
336
402
|
str: The payer ID corresponding to the insurance name.
|
|
337
403
|
"""
|
|
338
|
-
try:
|
|
339
|
-
#
|
|
340
|
-
MediBot_Crosswalk_Library.check_and_initialize_crosswalk(config)
|
|
341
|
-
|
|
342
|
-
# Load crosswalk configuration
|
|
404
|
+
try:
|
|
405
|
+
# Load crosswalk configuration // BUG This should already be passed in before we get here.
|
|
343
406
|
_, crosswalk = MediLink_ConfigLoader.load_configuration(None, config.get('crosswalkPath', 'crosswalk.json'))
|
|
344
407
|
|
|
408
|
+
# Ensure crosswalk is initialized and 'payer_id' key is available
|
|
409
|
+
if 'payer_id' not in crosswalk:
|
|
410
|
+
print("Crosswalk 'payer_id' not found. Please run MediBot_Preprocessor.py with the --update-crosswalk argument.")
|
|
411
|
+
exit() # BUG Halting the script execution here for now, should be handled in the preprocessor script.
|
|
412
|
+
|
|
345
413
|
# Load insurance data from MAINS to get insurance ID
|
|
346
414
|
insurance_to_id = load_insurance_data_from_mains(config)
|
|
347
415
|
|
|
@@ -350,6 +418,7 @@ def map_insurance_name_to_payer_id(insurance_name, config):
|
|
|
350
418
|
if medisoft_id is None:
|
|
351
419
|
error_message = "No Medisoft ID found for insurance name: {}. Consider checking MAINS directly.".format(insurance_name)
|
|
352
420
|
MediLink_ConfigLoader.log(error_message, config, level="ERROR")
|
|
421
|
+
# Asking for payer ID here is not the right approach.
|
|
353
422
|
raise ValueError(error_message)
|
|
354
423
|
|
|
355
424
|
# Convert medisoft_id to string to match the JSON data type
|
|
@@ -367,7 +436,7 @@ def map_insurance_name_to_payer_id(insurance_name, config):
|
|
|
367
436
|
error_message = "No payer ID found for Medisoft ID: {}".format(medisoft_id)
|
|
368
437
|
MediLink_ConfigLoader.log(error_message, config, level="ERROR")
|
|
369
438
|
print(error_message)
|
|
370
|
-
payer_id = handle_missing_payer_id(insurance_name, config)
|
|
439
|
+
payer_id = handle_missing_payer_id(insurance_name, config, crosswalk, client)
|
|
371
440
|
|
|
372
441
|
return payer_id
|
|
373
442
|
|
|
@@ -381,47 +450,6 @@ def map_insurance_name_to_payer_id(insurance_name, config):
|
|
|
381
450
|
MediLink_ConfigLoader.log(error_message, config, level="ERROR")
|
|
382
451
|
raise e
|
|
383
452
|
|
|
384
|
-
def handle_missing_payer_id(insurance_name, config):
|
|
385
|
-
"""
|
|
386
|
-
Handles cases where the payer ID is not found for a given Medisoft ID.
|
|
387
|
-
|
|
388
|
-
"""
|
|
389
|
-
print("Missing Payer ID for insurance name: {}".format(insurance_name))
|
|
390
|
-
MediLink_ConfigLoader.log("Missing Payer ID for insurance name: {}".format(insurance_name), config, level="WARNING")
|
|
391
|
-
|
|
392
|
-
# Prompt the user for manual intervention to input the payer ID
|
|
393
|
-
payer_id = prompt_user_for_payer_id(insurance_name)
|
|
394
|
-
|
|
395
|
-
if not payer_id:
|
|
396
|
-
message = "Unable to resolve missing Payer ID. Manual intervention is required."
|
|
397
|
-
MediLink_ConfigLoader.log(message, config, level="CRITICAL")
|
|
398
|
-
return None
|
|
399
|
-
|
|
400
|
-
# Resolve the payer ID to a standard insurance name via API
|
|
401
|
-
try:
|
|
402
|
-
# primary_endpoint=None should kick to the default in the api function.
|
|
403
|
-
standard_insurance_name = resolve_payer_name(payer_id, config, primary_endpoint=None, insurance_name=insurance_name, parsed_data={})
|
|
404
|
-
message = "Resolved to standard insurance name: {} for payer ID: {}".format(standard_insurance_name, payer_id)
|
|
405
|
-
print(message)
|
|
406
|
-
MediLink_ConfigLoader.log(message, config, level="INFO")
|
|
407
|
-
except Exception as e:
|
|
408
|
-
message = "Failed to resolve payer ID to standard insurance name: {}".format(e)
|
|
409
|
-
print(message)
|
|
410
|
-
MediLink_ConfigLoader.log(message, config, level="ERROR")
|
|
411
|
-
return None
|
|
412
|
-
|
|
413
|
-
# Ask for user confirmation
|
|
414
|
-
confirmation = input("Is the standard insurance name '{}' correct? (yes/no): ".format(standard_insurance_name)).strip().lower() or 'yes'
|
|
415
|
-
# BUG There is duplication of code here.
|
|
416
|
-
if confirmation in ['yes', 'y']:
|
|
417
|
-
# Update the crosswalk with the new payer ID and insurance name mapping
|
|
418
|
-
MediBot_Crosswalk_Library.update_crosswalk_with_new_payer_id(insurance_name, payer_id, config)
|
|
419
|
-
return payer_id
|
|
420
|
-
else:
|
|
421
|
-
print("User did not confirm the standard insurance name. Manual intervention is required.")
|
|
422
|
-
MediLink_ConfigLoader.log("User did not confirm the standard insurance name. Manual intervention is required.", config, level="CRITICAL")
|
|
423
|
-
return None
|
|
424
|
-
|
|
425
453
|
def create_nm1_payto_address_segments(config):
|
|
426
454
|
"""
|
|
427
455
|
Constructs the NM1 segment for the Pay-To Address, N3 for street address, and N4 for city, state, and ZIP.
|
|
@@ -632,7 +660,7 @@ def format_claim_number(chart_number, date_of_service):
|
|
|
632
660
|
return formatted_claim_number
|
|
633
661
|
|
|
634
662
|
# Constructs the CLM and related segments based on parsed data and configuration.
|
|
635
|
-
def create_clm_and_related_segments(parsed_data, config):
|
|
663
|
+
def create_clm_and_related_segments(parsed_data, config, crosswalk):
|
|
636
664
|
"""
|
|
637
665
|
Insert the claim information (2300 loop),
|
|
638
666
|
ensuring that details such as claim ID, total charge amount,and service date are included.
|
|
@@ -658,9 +686,23 @@ def create_clm_and_related_segments(parsed_data, config):
|
|
|
658
686
|
parsed_data['TOS']))
|
|
659
687
|
|
|
660
688
|
# HI - Health Care Diagnosis Code
|
|
661
|
-
#
|
|
662
|
-
|
|
663
|
-
|
|
689
|
+
# Hardcoding "ABK" for ICD-10 codes as they are the only ones used now.
|
|
690
|
+
medisoft_code = ''.join(filter(str.isalnum, parsed_data['DIAG']))
|
|
691
|
+
diagnosis_code = next((key for key, value in crosswalk.get('diagnosis_to_medisoft', {}).items() if value == medisoft_code), None)
|
|
692
|
+
|
|
693
|
+
if diagnosis_code is None:
|
|
694
|
+
error_message = "Diagnosis code is empty for chart number: {}. Please verify. Medisoft code is {}".format(chart_number, medisoft_code)
|
|
695
|
+
MediLink_ConfigLoader.log(error_message, config, level="CRITICAL")
|
|
696
|
+
print(error_message)
|
|
697
|
+
diagnosis_code = input("Enter the complete diagnosis code: ")
|
|
698
|
+
# Update the crosswalk dictionary with the new pairing of diagnosis_code and medisoft_code.
|
|
699
|
+
crosswalk['diagnosis_to_medisoft'][diagnosis_code] = medisoft_code
|
|
700
|
+
MediLink_ConfigLoader.log("Updated crosswalk with new diagnosis code: {}, for Medisoft code {}".format(diagnosis_code, medisoft_code), config, level="INFO")
|
|
701
|
+
# TODO This needs to actually save the .json though which right now I'd like to route through the dedicated function for updating the crosswalk.
|
|
702
|
+
# TODO This should have been a validation exercise upstream and not a last minute check like this.
|
|
703
|
+
|
|
704
|
+
cleaned_diagnosis_code = ''.join(char for char in diagnosis_code if char.isalnum())
|
|
705
|
+
segments.append("HI*ABK:{}~".format(cleaned_diagnosis_code))
|
|
664
706
|
|
|
665
707
|
# (2310C Loop) Service Facility Location NPI and Address Information
|
|
666
708
|
segments.extend(create_service_facility_location_npi_segment(config))
|
|
@@ -680,7 +722,10 @@ def create_clm_and_related_segments(parsed_data, config):
|
|
|
680
722
|
# DTP - Date
|
|
681
723
|
segments.append("DTP*472*D8*{}~".format(convert_date_format(parsed_data['DATE'])))
|
|
682
724
|
|
|
683
|
-
# Is there REF - Line Item Control Number missing here?
|
|
725
|
+
# Is there REF - Line Item Control Number missing here? Private insurance doesn't need it, but Medicare does?
|
|
726
|
+
# segments.append("REF*6R*1~") # REF01, Reference Identification Qualifier; REF02, Line Item Control Number.
|
|
727
|
+
# 6R - Provider Control Number (Number assigned by information provider company for tracking and billing purposes)
|
|
728
|
+
# 1 - Reference information as defined for a particular Transaction Set or as specified by the Reference Identification Qualifier
|
|
684
729
|
|
|
685
730
|
return segments
|
|
686
731
|
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
# This script requires Python 3.11 and is to be used for intalling new API clients.
|
|
2
|
-
import os
|
|
3
|
-
import time
|
|
4
|
-
import subprocess
|
|
5
|
-
import shutil
|
|
6
|
-
import tempfile
|
|
2
|
+
import os, time, subprocess, shutil, tempfile, shlex, re
|
|
7
3
|
from pathlib import Path
|
|
8
4
|
from watchdog.observers import Observer
|
|
9
5
|
from watchdog.events import FileSystemEventHandler
|
|
10
6
|
from MediLink_API_v3 import ConfigLoader
|
|
11
|
-
import shlex
|
|
12
|
-
import re
|
|
13
7
|
|
|
14
8
|
class SwaggerHandler(FileSystemEventHandler):
|
|
15
9
|
def __init__(self, json_folder):
|