medicafe 0.240716.2__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.

@@ -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, MediLink_UI
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.append(project_dir)
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*2*{}*****{}*{}~".format(submitter_name, submitter_id_qualifier, submitter_id)
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,88 +237,160 @@ 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 resolve_payer_name(payer_id, config, primary_endpoint, insurance_name, parsed_data):
242
- """
243
- Resolves the payer name using the provided payer ID.
244
-
245
- Args:
246
- payer_id (str): The ID of the payer.
247
- config (dict): Configuration settings.
248
- primary_endpoint (str): The primary endpoint for resolving payer information.
249
- insurance_name (str): The name of the insurance.
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\nrouted or fail without intervention.".format(insurance_name))
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, \nor press Enter to pause processing and make corrections: ")
276
- user_decision = user_decision.strip().lower() # Convert to lowercase and remove leading/trailing whitespace
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: # Check if user pressed Enter
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
- confirmation = input("Is the standard insurance name '{}' correct? (yes/no): ".format(resolved_name)).strip().lower()
291
-
292
- if confirmation in ['yes', 'y']:
293
- if MediBot_Crosswalk_Library.update_crosswalk_with_corrected_payer_id(payer_id, corrected_payer_id):
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
- exit(1) # probably needs a different failure direction here.
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) # probably needs a different failure direction here.
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) # probably needs a different failure direction here.
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
- exit(1) # probably needs a different failure direction here.
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
  """
312
- Prompts the user to input the payer ID manually.
378
+ Prompts the user to input the payer ID manually and ensures that a valid ID is provided.
313
379
  """
314
- print("Manual intervention required: No payer ID found for insurance name '{}'.".format(insurance_name))
315
- payer_id = input("Please enter the payer ID manually: ").strip()
316
- return payer_id
380
+ while True:
381
+ print("Manual intervention required: No payer ID found for insurance name '{}'.".format(insurance_name))
382
+ payer_id = input("Please enter the payer ID manually: ").strip()
383
+
384
+ if payer_id:
385
+ return payer_id
386
+ else:
387
+ print("Error: Payer ID cannot be empty. Please try again.")
317
388
 
318
389
  def build_nm1_segment(payer_name, payer_id):
319
390
  # Step 1: Build NM1 segment using payer name and ID
320
391
  return "NM1*PR*2*{}*****PI*{}~".format(payer_name, payer_id)
321
392
 
322
- def map_insurance_name_to_payer_id(insurance_name, config):
393
+ def map_insurance_name_to_payer_id(insurance_name, config, client):
323
394
  """
324
395
  Maps insurance name to payer ID using the crosswalk configuration.
325
396
 
@@ -330,13 +401,15 @@ def map_insurance_name_to_payer_id(insurance_name, config):
330
401
  Returns:
331
402
  str: The payer ID corresponding to the insurance name.
332
403
  """
333
- try:
334
- # Ensure crosswalk is initialized and 'payer_id' key is available
335
- MediBot_Crosswalk_Library.check_and_initialize_crosswalk(config)
336
-
337
- # Load crosswalk configuration
404
+ try:
405
+ # Load crosswalk configuration // BUG This should already be passed in before we get here.
338
406
  _, crosswalk = MediLink_ConfigLoader.load_configuration(None, config.get('crosswalkPath', 'crosswalk.json'))
339
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
+
340
413
  # Load insurance data from MAINS to get insurance ID
341
414
  insurance_to_id = load_insurance_data_from_mains(config)
342
415
 
@@ -345,6 +418,7 @@ def map_insurance_name_to_payer_id(insurance_name, config):
345
418
  if medisoft_id is None:
346
419
  error_message = "No Medisoft ID found for insurance name: {}. Consider checking MAINS directly.".format(insurance_name)
347
420
  MediLink_ConfigLoader.log(error_message, config, level="ERROR")
421
+ # Asking for payer ID here is not the right approach.
348
422
  raise ValueError(error_message)
349
423
 
350
424
  # Convert medisoft_id to string to match the JSON data type
@@ -362,7 +436,7 @@ def map_insurance_name_to_payer_id(insurance_name, config):
362
436
  error_message = "No payer ID found for Medisoft ID: {}".format(medisoft_id)
363
437
  MediLink_ConfigLoader.log(error_message, config, level="ERROR")
364
438
  print(error_message)
365
- payer_id = handle_missing_payer_id(insurance_name, config)
439
+ payer_id = handle_missing_payer_id(insurance_name, config, crosswalk, client)
366
440
 
367
441
  return payer_id
368
442
 
@@ -376,47 +450,6 @@ def map_insurance_name_to_payer_id(insurance_name, config):
376
450
  MediLink_ConfigLoader.log(error_message, config, level="ERROR")
377
451
  raise e
378
452
 
379
- def handle_missing_payer_id(insurance_name, config):
380
- """
381
- Handles cases where the payer ID is not found for a given Medisoft ID.
382
-
383
- """
384
- print("Missing Payer ID for insurance name: {}".format(insurance_name))
385
- MediLink_ConfigLoader.log("Missing Payer ID for insurance name: {}".format(insurance_name), config, level="WARNING")
386
-
387
- # Prompt the user for manual intervention to input the payer ID
388
- payer_id = prompt_user_for_payer_id(insurance_name)
389
-
390
- if not payer_id:
391
- message = "Unable to resolve missing Payer ID. Manual intervention is required."
392
- MediLink_ConfigLoader.log(message, config, level="CRITICAL")
393
- return None
394
-
395
- # Resolve the payer ID to a standard insurance name via API
396
- try:
397
- # primary_endpoint=None should kick to the default in the api function.
398
- standard_insurance_name = resolve_payer_name(payer_id, config, primary_endpoint=None, insurance_name=insurance_name, parsed_data={})
399
- message = "Resolved to standard insurance name: {} for payer ID: {}".format(standard_insurance_name, payer_id)
400
- print(message)
401
- MediLink_ConfigLoader.log(message, config, level="INFO")
402
- except Exception as e:
403
- message = "Failed to resolve payer ID to standard insurance name: {}".format(e)
404
- print(message)
405
- MediLink_ConfigLoader.log(message, config, level="ERROR")
406
- return None
407
-
408
- # Ask for user confirmation
409
- confirmation = input("Is the standard insurance name '{}' correct? (yes/no): ".format(standard_insurance_name)).strip().lower() or 'yes'
410
-
411
- if confirmation in ['yes', 'y']:
412
- # Update the crosswalk with the new payer ID and insurance name mapping
413
- MediBot_Crosswalk_Library.update_crosswalk_with_new_payer_id(insurance_name, payer_id, config)
414
- return payer_id
415
- else:
416
- print("User did not confirm the standard insurance name. Manual intervention is required.")
417
- MediLink_ConfigLoader.log("User did not confirm the standard insurance name. Manual intervention is required.", config, level="CRITICAL")
418
- return None
419
-
420
453
  def create_nm1_payto_address_segments(config):
421
454
  """
422
455
  Constructs the NM1 segment for the Pay-To Address, N3 for street address, and N4 for city, state, and ZIP.
@@ -627,7 +660,7 @@ def format_claim_number(chart_number, date_of_service):
627
660
  return formatted_claim_number
628
661
 
629
662
  # Constructs the CLM and related segments based on parsed data and configuration.
630
- def create_clm_and_related_segments(parsed_data, config):
663
+ def create_clm_and_related_segments(parsed_data, config, crosswalk):
631
664
  """
632
665
  Insert the claim information (2300 loop),
633
666
  ensuring that details such as claim ID, total charge amount,and service date are included.
@@ -653,9 +686,23 @@ def create_clm_and_related_segments(parsed_data, config):
653
686
  parsed_data['TOS']))
654
687
 
655
688
  # HI - Health Care Diagnosis Code
656
- # The code value should be preceded by the qualifier "ABK" or "BK" to specify the type of
657
- # diagnosis code being used. "ABK" typically indicates ICD-10 codes, while "BK" indicates ICD-9 codes.
658
- segments.append("HI*ABK:H{}~".format(''.join(char for char in parsed_data['DIAG'] if char.isalnum() or char.isdigit())))
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))
659
706
 
660
707
  # (2310C Loop) Service Facility Location NPI and Address Information
661
708
  segments.extend(create_service_facility_location_npi_segment(config))
@@ -675,7 +722,10 @@ def create_clm_and_related_segments(parsed_data, config):
675
722
  # DTP - Date
676
723
  segments.append("DTP*472*D8*{}~".format(convert_date_format(parsed_data['DATE'])))
677
724
 
678
- # 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
679
729
 
680
730
  return segments
681
731
 
@@ -847,10 +897,17 @@ def winscp_validate_output_directory(output_directory):
847
897
 
848
898
  def get_output_directory(config):
849
899
  # Retrieve desired default output file path from config
850
- output_directory = config.get('outputFilePath', '')
900
+ output_directory = config.get('outputFilePath', '').strip()
851
901
  # BUG (Low SFTP) Add WinSCP validation because of the mishandling of spaces in paths. (This shouldn't need to exist.)
902
+ if not output_directory:
903
+ print("Output file path is not specified in the configuration.")
904
+ output_directory = input("Please enter a valid output directory path: ").strip()
905
+
906
+ # Validate the directory path (checks for spaces and existence)
852
907
  output_directory = winscp_validate_output_directory(output_directory)
908
+
853
909
  if not os.path.isdir(output_directory):
854
- print("Output directory does not exist. Please check the configuration.")
910
+ print("Output directory does not exist or is not accessible. Please check the configuration.")
855
911
  return None
912
+
856
913
  return output_directory
@@ -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):