medicafe 0.250814.3__py3-none-any.whl → 0.250814.4__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.
MediBot/MediBot.py CHANGED
@@ -12,6 +12,55 @@ except ImportError:
12
12
  msvcrt = None # Not available on non-Windows systems
13
13
  from collections import OrderedDict
14
14
 
15
+ # ============================================================================
16
+ # MINIMAL PROTECTION: Import State Validation
17
+ # ============================================================================
18
+
19
+ def validate_critical_imports():
20
+ """Validate that critical imports are in expected state before proceeding"""
21
+ critical_modules = {
22
+ 'MediBot_Preprocessor': None,
23
+ 'MediBot_Preprocessor_lib': None,
24
+ 'MediBot_UI': None,
25
+ 'MediBot_Crosswalk_Library': None
26
+ }
27
+
28
+ # Test imports and capture state
29
+ try:
30
+ print("Testing MediCafe.core_utils import...")
31
+ from MediCafe.core_utils import import_medibot_module_with_debug
32
+ print("MediCafe.core_utils import successful")
33
+
34
+ for module_name in critical_modules.keys():
35
+ print("Testing {} import...".format(module_name))
36
+ try:
37
+ module = import_medibot_module_with_debug(module_name)
38
+ critical_modules[module_name] = module
39
+ if module is None:
40
+ print(" WARNING: {} import returned None".format(module_name))
41
+ else:
42
+ print(" SUCCESS: {} import successful".format(module_name))
43
+ except Exception as e:
44
+ print(" ERROR: {} import failed with exception: {}".format(module_name, e))
45
+ critical_modules[module_name] = None
46
+ except Exception as e:
47
+ print("CRITICAL: Failed to import core utilities: {}".format(e))
48
+ return False, critical_modules
49
+
50
+ # Check for None imports (the specific failure pattern)
51
+ failed_imports = []
52
+ for module_name, module in critical_modules.items():
53
+ if module is None:
54
+ failed_imports.append(module_name)
55
+
56
+ if failed_imports:
57
+ print("CRITICAL: Import failures detected:")
58
+ for failed in failed_imports:
59
+ print(" - {}: Import returned None".format(failed))
60
+ return False, critical_modules
61
+
62
+ return True, critical_modules
63
+
15
64
  # Use core utilities for standardized imports
16
65
  from MediCafe.core_utils import (
17
66
  import_medibot_module_with_debug,
@@ -512,6 +561,19 @@ if __name__ == "__main__":
512
561
  try:
513
562
  if PERFORMANCE_LOGGING:
514
563
  print("Initializing. Loading configuration and preparing environment...")
564
+
565
+ # PROTECTION: Validate critical imports before proceeding
566
+ print("Validating critical imports...")
567
+ import_valid, import_state = validate_critical_imports()
568
+ if not import_valid:
569
+ print("CRITICAL: Import validation failed. Cannot continue.")
570
+ print("This indicates a fundamental system configuration issue.")
571
+ print("Please check:")
572
+ print(" 1. All MediBot modules exist in the MediBot directory")
573
+ print(" 2. Python path is correctly configured")
574
+ print(" 3. No syntax errors in MediBot modules")
575
+ sys.exit(1)
576
+
515
577
  # Use MediCafe configuration system
516
578
  try:
517
579
  config_loader = get_config_loader_with_fallback()
@@ -553,6 +615,22 @@ if __name__ == "__main__":
553
615
  print("Starting CSV preprocessing at: {}".format(time.strftime("%H:%M:%S")))
554
616
  MediLink_ConfigLoader.log("Starting CSV preprocessing at: {}".format(time.strftime("%H:%M:%S")), level="INFO")
555
617
 
618
+ # PROTECTION: Validate MediBot_Preprocessor before calling preprocess_csv_data
619
+ if MediBot_Preprocessor is None:
620
+ print("CRITICAL: MediBot_Preprocessor is None when trying to call preprocess_csv_data")
621
+ print("This indicates the import failed silently during execution.")
622
+ print("Import state at failure:")
623
+ for module_name, module in import_state.items():
624
+ status = "None" if module is None else "OK"
625
+ print(" - {}: {}".format(module_name, status))
626
+ print("Please check for syntax errors or missing dependencies in MediBot modules.")
627
+ sys.exit(1)
628
+
629
+ if not hasattr(MediBot_Preprocessor, 'preprocess_csv_data'):
630
+ print("CRITICAL: MediBot_Preprocessor missing preprocess_csv_data function")
631
+ print("Available functions: {}".format([attr for attr in dir(MediBot_Preprocessor) if not attr.startswith('_')]))
632
+ sys.exit(1)
633
+
556
634
  MediBot_Preprocessor.preprocess_csv_data(csv_data, e_state.crosswalk)
557
635
 
558
636
  # TIMING: End CSV preprocessing timing
@@ -623,7 +701,16 @@ if __name__ == "__main__":
623
701
 
624
702
  # Create entries for each surgery date with its specific diagnosis code
625
703
  for surgery_date in all_surgery_dates:
626
- diagnosis_code = surgery_date_to_diagnosis.get(surgery_date, 'N/A')
704
+ # Convert surgery_date to string format for consistent lookup (XP SP3 + Py3.4.4 compatible)
705
+ try:
706
+ if hasattr(surgery_date, 'strftime'):
707
+ surgery_date_str = surgery_date.strftime('%m-%d-%Y')
708
+ else:
709
+ surgery_date_str = str(surgery_date)
710
+ except Exception:
711
+ surgery_date_str = str(surgery_date)
712
+
713
+ diagnosis_code = surgery_date_to_diagnosis.get(surgery_date_str, 'N/A')
627
714
  patient_info.append((surgery_date, patient_name, patient_id, diagnosis_code, patient_row))
628
715
 
629
716
  except Exception as e:
@@ -655,7 +742,16 @@ if __name__ == "__main__":
655
742
 
656
743
  # Create entries for each surgery date with its specific diagnosis code
657
744
  for surgery_date in all_surgery_dates:
658
- diagnosis_code = surgery_date_to_diagnosis.get(surgery_date, 'N/A')
745
+ # Convert surgery_date to string format for consistent lookup (XP SP3 + Py3.4.4 compatible)
746
+ try:
747
+ if hasattr(surgery_date, 'strftime'):
748
+ surgery_date_str = surgery_date.strftime('%m-%d-%Y')
749
+ else:
750
+ surgery_date_str = str(surgery_date)
751
+ except Exception:
752
+ surgery_date_str = str(surgery_date)
753
+
754
+ diagnosis_code = surgery_date_to_diagnosis.get(surgery_date_str, 'N/A')
659
755
  new_patient_info.append((surgery_date, patient_name, patient_id, diagnosis_code, row))
660
756
 
661
757
  # Display new patients table using the enhanced display function
@@ -695,7 +791,41 @@ if __name__ == "__main__":
695
791
  if e_state:
696
792
  interaction_mode = 'error' # Switch to error mode
697
793
  error_message = str(e) # Capture the error message
698
- print("An error occurred while running MediBot: {}".format(e))
794
+
795
+ # ENHANCED ERROR DIAGNOSTICS
796
+ print("=" * 60)
797
+ print("MEDIBOT EXECUTION FAILURE")
798
+ print("=" * 60)
799
+ print("Error: {}".format(e))
800
+ print("Error type: {}".format(type(e).__name__))
801
+
802
+ # Check for the specific failure pattern
803
+ if "'NoneType' object has no attribute" in str(e):
804
+ print("DIAGNOSIS: This is the import failure pattern.")
805
+ print("A module import returned None, causing a method call to fail.")
806
+ print("This typically indicates:")
807
+ print(" 1. Syntax error in a MediBot module")
808
+ print(" 2. Missing dependency")
809
+ print(" 3. Import path issue")
810
+ print(" 4. Circular import problem")
811
+
812
+ # Show current import state
813
+ print("Current import state:")
814
+ try:
815
+ import_state = {
816
+ 'MediBot_Preprocessor': MediBot_Preprocessor,
817
+ 'MediBot_Preprocessor_lib': MediBot_Preprocessor_lib,
818
+ 'MediBot_UI': MediBot_UI,
819
+ 'MediBot_Crosswalk_Library': MediBot_Crosswalk_Library
820
+ }
821
+ for module_name, module in import_state.items():
822
+ status = "None" if module is None else "OK"
823
+ print(" - {}: {}".format(module_name, status))
824
+ except Exception as diag_e:
825
+ print(" - Unable to diagnose import state: {}".format(diag_e))
826
+
827
+ print("=" * 60)
828
+
699
829
  # Handle the error by calling user interaction with the error information
700
830
  if 'identified_fields' in locals():
701
831
  _ = user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
@@ -1160,17 +1160,51 @@ def update_diagnosis_codes(csv_data):
1160
1160
  MediLink_ConfigLoader.log("Patient ID: {}, Surgery Date: {}".format(patient_id, surgery_date_str), level="DEBUG")
1161
1161
 
1162
1162
  if surgery_date_str in all_patient_data[patient_id]:
1163
- diagnosis_code, left_or_right_eye, femto_yes_or_no = all_patient_data[patient_id][surgery_date_str]
1163
+ diagnosis_data = all_patient_data[patient_id][surgery_date_str]
1164
+ # XP SP3 + Py3.4.4 compatible tuple unpacking with safety check
1165
+ try:
1166
+ if isinstance(diagnosis_data, (list, tuple)) and len(diagnosis_data) >= 3:
1167
+ diagnosis_code, left_or_right_eye, femto_yes_or_no = diagnosis_data
1168
+ else:
1169
+ # Handle case where diagnosis_data is not a proper tuple
1170
+ diagnosis_code = diagnosis_data if diagnosis_data else None
1171
+ left_or_right_eye = None
1172
+ femto_yes_or_no = None
1173
+ except Exception as e:
1174
+ MediLink_ConfigLoader.log("Error unpacking diagnosis data for Patient ID: {}, Surgery Date: {}: {}".format(
1175
+ patient_id, surgery_date_str, str(e)), level="WARNING")
1176
+ diagnosis_code = None
1177
+ left_or_right_eye = None
1178
+ femto_yes_or_no = None
1179
+
1164
1180
  MediLink_ConfigLoader.log("Found diagnosis data for Patient ID: {}, Surgery Date: {}".format(patient_id, surgery_date_str), level="DEBUG")
1165
1181
 
1166
- # Convert diagnosis code to Medisoft shorthand format.
1167
- medisoft_shorthand = diagnosis_to_medisoft.get(diagnosis_code, None)
1168
- if medisoft_shorthand is None and diagnosis_code:
1169
- # Use fallback logic for missing mapping
1170
- defaulted_code = diagnosis_code.lstrip('H').lstrip('T8').replace('.', '')[-5:]
1171
- medisoft_shorthand = defaulted_code
1172
- MediLink_ConfigLoader.log("Missing diagnosis mapping for '{}', using fallback code '{}'".format(
1173
- diagnosis_code, medisoft_shorthand), level="WARNING")
1182
+ # Convert diagnosis code to Medisoft shorthand format.
1183
+ # XP SP3 + Py3.4.4 compatible null check
1184
+ if diagnosis_code is None:
1185
+ medisoft_shorthand = 'N/A'
1186
+ MediLink_ConfigLoader.log("Diagnosis code is None for Patient ID: {}, Surgery Date: {}".format(
1187
+ patient_id, surgery_date_str), level="WARNING")
1188
+ else:
1189
+ medisoft_shorthand = diagnosis_to_medisoft.get(diagnosis_code, None)
1190
+ if medisoft_shorthand is None and diagnosis_code:
1191
+ # Use fallback logic for missing mapping (XP SP3 + Py3.4.4 compatible)
1192
+ try:
1193
+ defaulted_code = diagnosis_code.lstrip('H').lstrip('T8').replace('.', '')[-5:]
1194
+ # Basic validation: ensure code is not empty and has reasonable length
1195
+ if defaulted_code and len(defaulted_code) >= 3:
1196
+ medisoft_shorthand = defaulted_code
1197
+ MediLink_ConfigLoader.log("Missing diagnosis mapping for '{}', using fallback code '{}'".format(
1198
+ diagnosis_code, medisoft_shorthand), level="WARNING")
1199
+ else:
1200
+ medisoft_shorthand = 'N/A'
1201
+ MediLink_ConfigLoader.log("Fallback diagnosis code validation failed for '{}', using 'N/A'".format(
1202
+ diagnosis_code), level="WARNING")
1203
+ except Exception as e:
1204
+ medisoft_shorthand = 'N/A'
1205
+ MediLink_ConfigLoader.log("Error in fallback diagnosis code generation for '{}': {}".format(
1206
+ diagnosis_code, str(e)), level="WARNING")
1207
+
1174
1208
  MediLink_ConfigLoader.log("Converted diagnosis code to Medisoft shorthand: {}".format(medisoft_shorthand), level="DEBUG")
1175
1209
 
1176
1210
  surgery_date_to_diagnosis[surgery_date_str] = medisoft_shorthand
@@ -1488,12 +1522,28 @@ def capitalize_all_fields(csv_data):
1488
1522
  Returns:
1489
1523
  None: The function modifies the csv_data in place.
1490
1524
  """
1491
- # PERFORMANCE FIX: Optimize uppercase conversion using dict comprehension
1525
+ # PERFORMANCE FIX: Optimize uppercase conversion while preserving complex types
1492
1526
  for row in csv_data:
1493
- # Single-pass update using dict comprehension
1494
- row.update({
1495
- key: (value.upper() if isinstance(value, str)
1496
- else str(value).upper() if value is not None and not isinstance(value, datetime)
1497
- else value)
1498
- for key, value in row.items()
1499
- })
1527
+ updated_row = {}
1528
+ for key, value in row.items():
1529
+ # Preserve internal/derived fields intact (e.g., `_all_surgery_dates`, `_surgery_date_to_diagnosis`)
1530
+ if isinstance(key, str) and key.startswith('_'):
1531
+ updated_row[key] = value
1532
+ continue
1533
+ # Uppercase plain strings
1534
+ if isinstance(value, str):
1535
+ updated_row[key] = value.upper()
1536
+ continue
1537
+ # Preserve complex containers; optionally uppercase their string contents
1538
+ if isinstance(value, list):
1539
+ updated_row[key] = [elem.upper() if isinstance(elem, str) else elem for elem in value]
1540
+ continue
1541
+ if isinstance(value, dict):
1542
+ updated_row[key] = {k: (v.upper() if isinstance(v, str) else v) for k, v in value.items()}
1543
+ continue
1544
+ # Leave datetimes as-is; coerce simple scalars to string upper for consistency
1545
+ if isinstance(value, datetime):
1546
+ updated_row[key] = value
1547
+ else:
1548
+ updated_row[key] = str(value).upper() if value is not None else value
1549
+ row.update(updated_row)
MediBot/MediBot_UI.py CHANGED
@@ -43,64 +43,87 @@ def display_enhanced_patient_table(patient_info, title, show_line_numbers=True):
43
43
  print(title)
44
44
  print()
45
45
 
46
- # Sort by surgery date first and then by patient name
47
- patient_info.sort(key=lambda x: (x[0], x[1]))
46
+ # Normalize data to avoid None and unexpected container types in sort key
47
+ normalized_info = []
48
+ for surgery_date, patient_name, patient_id, diagnosis_code, patient_row in patient_info:
49
+ # Normalize date into comparable key and display string
50
+ display_date = None
51
+ sort_key = None
52
+ try:
53
+ if hasattr(surgery_date, 'strftime'):
54
+ display_date = surgery_date.strftime('%m-%d')
55
+ sort_key = surgery_date
56
+ elif isinstance(surgery_date, str):
57
+ # Date strings may be MM-DD-YYYY or already MM-DD
58
+ parts = surgery_date.split('-') if surgery_date else []
59
+ if len(parts) == 3 and all(parts):
60
+ display_date = "{}-{}".format(parts[0], parts[1])
61
+ else:
62
+ display_date = surgery_date or 'Unknown Date'
63
+ # Use the raw string as sort key fallback
64
+ sort_key = surgery_date or ''
65
+ else:
66
+ display_date = str(surgery_date) if surgery_date is not None else 'Unknown Date'
67
+ sort_key = display_date
68
+ except Exception:
69
+ display_date = str(surgery_date) if surgery_date is not None else 'Unknown Date'
70
+ sort_key = display_date
71
+
72
+ # Normalize diagnosis display: only show "-Not Found-" when explicitly flagged as N/A
73
+ # XP SP3 + Py3.4.4 compatible error handling
74
+ display_diagnosis = diagnosis_code
75
+ try:
76
+ if diagnosis_code == "N/A":
77
+ display_diagnosis = "-Not Found-"
78
+ elif diagnosis_code is None:
79
+ display_diagnosis = "-Not Found-"
80
+ elif isinstance(diagnosis_code, str) and diagnosis_code.strip() == "":
81
+ display_diagnosis = "-Not Found-"
82
+ else:
83
+ display_diagnosis = str(diagnosis_code)
84
+ except (TypeError, ValueError) as e:
85
+ # Log the specific error for debugging (ASCII-only compatible)
86
+ try:
87
+ error_msg = "Error converting diagnosis code to string: {}".format(str(e))
88
+ MediLink_ConfigLoader.log(error_msg, level="WARNING")
89
+ except Exception:
90
+ # Fallback logging if string formatting fails
91
+ MediLink_ConfigLoader.log("Error converting diagnosis code to string", level="WARNING")
92
+ display_diagnosis = "-Not Found-"
93
+
94
+ normalized_info.append((sort_key, display_date, str(patient_name or ''), str(patient_id or ''), display_diagnosis))
95
+
96
+ # Sort by normalized sort key then patient name
97
+ normalized_info.sort(key=lambda x: (x[0], x[2]))
48
98
 
49
99
  # Calculate column widths for proper alignment
50
- max_patient_id_len = max(len(str(pid)) for _, _, pid, _, _ in patient_info)
51
- max_patient_name_len = max(len(pname) for _, pname, _, _, _ in patient_info)
52
- max_diagnosis_len = max(len(dcode) for _, _, _, dcode, _ in patient_info)
100
+ max_patient_id_len = max(len(pid) for _, _, _, pid, _ in normalized_info)
101
+ max_patient_name_len = max(len(pname) for _, _, pname, _, _ in normalized_info)
102
+ max_diagnosis_len = max(len(dcode) for _, _, _, _, dcode in normalized_info)
53
103
 
54
104
  # Ensure minimum widths for readability
55
105
  max_patient_id_len = max(max_patient_id_len, 5) # 5-digit ID max
56
106
  max_patient_name_len = max(max_patient_name_len, 12) # "Patient Name" header
57
107
  max_diagnosis_len = max(max_diagnosis_len, 10) # "Diagnosis" header
58
108
 
59
- # Print the sorted patient info with multiple surgery dates
60
109
  current_patient = None
61
110
  line_number = 1
62
111
 
63
- for surgery_date, patient_name, patient_id, diagnosis_code, patient_row in patient_info:
64
- # Format surgery_date safely whether it's a datetime/date or a string
65
- try:
66
- if isinstance(surgery_date, datetime):
67
- formatted_date = surgery_date.strftime('%m-%d')
68
- else:
69
- # Handle string dates - this should be the Surgery Date Display field
70
- formatted_date = str(surgery_date)
71
- # If it's a date string like "12-25-2023", format it as "12-25"
72
- if '-' in formatted_date and len(formatted_date.split('-')) == 3:
73
- try:
74
- parts = formatted_date.split('-')
75
- formatted_date = "{}-{}".format(parts[0], parts[1])
76
- except:
77
- pass # Use original string if parsing fails
78
- except Exception:
79
- formatted_date = str(surgery_date)
80
-
81
- # Transform diagnosis code display: show "-Not Found-" instead of "N/A"
82
- display_diagnosis = "-Not Found-" if diagnosis_code == "N/A" else diagnosis_code
83
-
84
- # Check if this is the same patient as the previous line
112
+ for sort_key, formatted_date, patient_name, patient_id, display_diagnosis in normalized_info:
85
113
  if current_patient == patient_id:
86
- # Secondary surgery date - indent and show dashes for patient info
87
- # Use exact character count matching for dashes
88
- patient_id_dashes = '-' * len(str(patient_id))
114
+ patient_id_dashes = '-' * len(patient_id)
89
115
  patient_name_dashes = '-' * len(patient_name)
90
-
91
116
  secondary_format = " {:<6} | {:<" + str(max_patient_id_len) + "} | {:<" + str(max_patient_name_len) + "} | {:<" + str(max_diagnosis_len) + "}"
92
117
  print(secondary_format.format(formatted_date, patient_id_dashes, patient_name_dashes, display_diagnosis))
93
118
  else:
94
- # New patient - show full patient info
95
119
  current_patient = patient_id
96
120
  if show_line_numbers:
97
121
  primary_format = "{:03d}: {:<6} | {:<" + str(max_patient_id_len) + "} | {:<" + str(max_patient_name_len) + "} | {:<" + str(max_diagnosis_len) + "}"
98
- print(primary_format.format(line_number, formatted_date, str(patient_id), patient_name, display_diagnosis))
122
+ print(primary_format.format(line_number, formatted_date, patient_id, patient_name, display_diagnosis))
99
123
  line_number += 1
100
124
  else:
101
- # For existing patients, don't show line numbers
102
125
  primary_format = " {:<6} | {:<" + str(max_patient_id_len) + "} | {:<" + str(max_patient_name_len) + "} | {:<" + str(max_diagnosis_len) + "}"
103
- print(primary_format.format(formatted_date, str(patient_id), patient_name, display_diagnosis))
126
+ print(primary_format.format(formatted_date, patient_id, patient_name, display_diagnosis))
104
127
 
105
128
  # Function to check if a specific key is pressed
106
129
  def _get_vk_codes():
MediBot/__init__.py CHANGED
@@ -19,7 +19,7 @@ Smart Import Integration:
19
19
  medibot_main = get_components('medibot_main')
20
20
  """
21
21
 
22
- __version__ = "0.250814.3"
22
+ __version__ = "0.250814.4"
23
23
  __author__ = "Daniel Vidaud"
24
24
  __email__ = "daniel@personalizedtransformation.com"
25
25
 
@@ -1,5 +1,24 @@
1
1
  #update_medicafe.py
2
- # Version: 1.0.0
2
+ # Version: 1.1.0 - Fixed upgrade sequence issues
3
+ #
4
+ # CRITICAL FIXES IMPLEMENTED (2025):
5
+ # 1. REMOVED RACE CONDITION: Eliminated double-check logic in get_latest_version()
6
+ # that caused inconsistent behavior between first and second runs
7
+ # 2. IMPROVED CACHE CLEARING: Added aggressive pkg_resources cache clearing for
8
+ # XP SP3 + Python 3.4.4 compatibility
9
+ # 3. FIXED VERIFICATION: Improved version comparison logic to properly detect
10
+ # upgrade success/failure instead of considering mismatched versions as "successful"
11
+ # 4. XP TIMING: Increased delays from 2-3s to 3-5s to accommodate XP's slower
12
+ # file system operations
13
+ # 5. ERROR HANDLING: Standardized error messages and exit codes throughout
14
+ #
15
+ # DEPLOYMENT NOTES:
16
+ # - This file exists in two locations for legacy compatibility:
17
+ # * MediBot/update_medicafe.py (primary)
18
+ # * MediBot/MediBot/update_medicafe.py (legacy fallback)
19
+ # - Both files must remain identical - the batch script copies between them
20
+ # - Designed for Windows XP SP3 + Python 3.4.4 + ASCII-only environments
21
+ #
3
22
  import subprocess, sys, time, platform, os, shutil, random
4
23
 
5
24
  # Safe import for pkg_resources with fallback
@@ -94,8 +113,45 @@ def print_final_result(success, message):
94
113
  time.sleep(5)
95
114
  sys.exit(0 if success else 1)
96
115
 
116
+ def clear_pkg_resources_cache():
117
+ """
118
+ Aggressively clear pkg_resources cache for XP compatibility.
119
+
120
+ CRITICAL FIX (2025): On XP SP3 + Python 3.4.4, pkg_resources caching is particularly
121
+ problematic and can cause version detection to fail after package updates. This function
122
+ aggressively clears all known cache locations to ensure reliable version detection.
123
+
124
+ Called before every version check to prevent stale cache issues.
125
+ """
126
+ if not pkg_resources:
127
+ return False
128
+
129
+ try:
130
+ # Clear working set cache
131
+ pkg_resources.working_set = pkg_resources.WorkingSet()
132
+
133
+ # Clear distribution cache
134
+ if hasattr(pkg_resources, '_dist_cache'):
135
+ pkg_resources._dist_cache.clear()
136
+
137
+ # Clear working set cache
138
+ if hasattr(pkg_resources, '_ws_cache'):
139
+ pkg_resources._ws_cache.clear()
140
+
141
+ # Force reload of distributions
142
+ pkg_resources.require = pkg_resources.Requirement.parse
143
+
144
+ return True
145
+ except Exception as e:
146
+ print("Warning: Could not clear pkg_resources cache: {}".format(e))
147
+ return False
148
+
97
149
  def get_installed_version(package):
150
+ """Get installed version with improved cache clearing for XP."""
98
151
  try:
152
+ # Clear cache before checking version
153
+ clear_pkg_resources_cache()
154
+
99
155
  # First try using pkg_resources directly (more reliable for Python 3.4)
100
156
  if pkg_resources:
101
157
  try:
@@ -126,6 +182,14 @@ def get_installed_version(package):
126
182
  def get_latest_version(package, retries=3, delay=1):
127
183
  """
128
184
  Fetch the latest version of the specified package from PyPI with retries.
185
+
186
+ CRITICAL FIX (2025): Removed problematic double-check logic that caused race conditions.
187
+ The original code would check if current_version == latest_version and then make a
188
+ second API call, which created inconsistent behavior:
189
+ - First run: Script thinks it needs update, attempts upgrade, version detection fails
190
+ - Second run: Script detects same version, incorrectly assumes already up-to-date
191
+
192
+ Now simply returns the latest version immediately without double-checking.
129
193
  """
130
194
  if not requests:
131
195
  print("Error: requests module not available. Cannot fetch latest version.")
@@ -144,18 +208,8 @@ def get_latest_version(package, retries=3, delay=1):
144
208
  else:
145
209
  print("Latest available version: {} ({} attempt)".format(latest_version, attempt))
146
210
 
147
- # Check if the latest version is different from the current version
148
- current_version = get_installed_version(package)
149
- if current_version and compare_versions(latest_version, current_version) == 0:
150
- # If the versions are the same, perform a second request to ensure we have the latest
151
- time.sleep(delay)
152
- response = requests.get("https://pypi.org/pypi/{}/json".format(package), timeout=10)
153
- response.raise_for_status()
154
- data = response.json()
155
- latest_version = data['info']['version']
156
- print("Double-checked latest version: {}".format(latest_version))
211
+ return latest_version # Return the version immediately - no double-checking
157
212
 
158
- return latest_version # Return the version after the check
159
213
  except requests.RequestException as e:
160
214
  print("Attempt {}: Error fetching latest version: {}".format(attempt, e))
161
215
  if attempt < retries:
@@ -163,8 +217,6 @@ def get_latest_version(package, retries=3, delay=1):
163
217
  time.sleep(delay)
164
218
  return None
165
219
 
166
-
167
-
168
220
  def check_internet_connection():
169
221
  try:
170
222
  requests.get("http://www.google.com", timeout=5)
@@ -291,9 +343,16 @@ def compare_versions(version1, version2):
291
343
  v2_parts = list(map(int, version2.split(".")))
292
344
  return (v1_parts > v2_parts) - (v1_parts < v2_parts)
293
345
 
294
- def upgrade_package(package, retries=4, delay=2, target_version=None): # Updated retries to 4
346
+ def upgrade_package(package, retries=4, delay=2, target_version=None):
295
347
  """
296
348
  Attempts to upgrade the package multiple times with escalating techniques.
349
+
350
+ CRITICAL FIX (2025): Improved version verification logic to properly detect upgrade
351
+ success/failure. The original code would consider an upgrade "successful" even when
352
+ there was a version mismatch, leading to inconsistent behavior.
353
+
354
+ Now properly compares expected vs actual versions and only returns True if the
355
+ upgrade actually succeeded with the correct version.
297
356
  """
298
357
  if not check_internet_connection():
299
358
  print_status("No internet connection detected. Please check your internet connection and try again.", "ERROR")
@@ -306,6 +365,9 @@ def upgrade_package(package, retries=4, delay=2, target_version=None): # Update
306
365
  def get_installed_version_fresh(package):
307
366
  """Get installed version using a fresh subprocess to avoid pkg_resources cache issues."""
308
367
  try:
368
+ # Clear cache first
369
+ clear_pkg_resources_cache()
370
+
309
371
  # First try pip show
310
372
  process = subprocess.Popen(
311
373
  [sys.executable, '-m', 'pip', 'show', package],
@@ -353,39 +415,41 @@ def upgrade_package(package, retries=4, delay=2, target_version=None): # Update
353
415
  if process.returncode == 0:
354
416
  print(stdout.decode().strip())
355
417
  # Add longer delay to allow file system and package metadata to settle
418
+ # FIXED: Increased delay for XP compatibility
356
419
  print("Waiting for package metadata to update...")
357
- time.sleep(3)
420
+ time.sleep(5) # Increased from 3 to 5 seconds
358
421
 
359
422
  # Try multiple times to get the new version with increasing delays
360
423
  new_version = None
361
424
  for retry in range(3):
362
425
  # Clear pkg_resources cache before each attempt
363
- if pkg_resources:
364
- try:
365
- pkg_resources.working_set = pkg_resources.WorkingSet()
366
- except Exception:
367
- pass
426
+ clear_pkg_resources_cache()
368
427
 
369
428
  new_version = get_installed_version_fresh(package)
370
429
  if new_version:
371
430
  print("Detected new version: {}".format(new_version))
372
431
  break
373
432
  print("Version detection attempt {} failed, retrying...".format(retry + 1))
374
- time.sleep(2)
433
+ time.sleep(3) # Increased from 2 to 3 seconds
375
434
 
376
435
  expected_version = target_version or get_latest_version(package)
377
436
 
378
- if expected_version and new_version and compare_versions(new_version, expected_version) >= 0:
379
- print_status("Attempt {}: Upgrade succeeded with {}!".format(attempt, strategy_name), "SUCCESS")
380
- return True
437
+ # FIXED: Improved version verification logic
438
+ if expected_version and new_version:
439
+ version_comparison = compare_versions(new_version, expected_version)
440
+ if version_comparison >= 0:
441
+ print_status("Attempt {}: Upgrade succeeded with {}!".format(attempt, strategy_name), "SUCCESS")
442
+ return True
443
+ else:
444
+ print_status("Upgrade failed: Version mismatch. Current: {} Expected: {}".format(
445
+ new_version, expected_version), "ERROR")
446
+ return False
381
447
  elif new_version:
382
- print_status("Upgrade may have succeeded but version mismatch. Current: {} Expected: {}".format(
383
- new_version, expected_version), "WARNING")
384
- # If we got a new version but it doesn't match expected, still consider it a success
385
- # as the package was updated
448
+ # If we got a new version but can't verify expected, still consider success
449
+ print_status("Upgrade succeeded but version verification unclear. New version: {}".format(new_version), "WARNING")
386
450
  return True
387
451
  else:
388
- print_status("Upgrade incomplete. Could not detect new version.", "WARNING")
452
+ print_status("Upgrade incomplete. Could not detect new version.", "ERROR")
389
453
  return False
390
454
  else:
391
455
  print(stderr.decode().strip())
@@ -542,7 +606,7 @@ def main():
542
606
  # Enable debug mode if requested via CLI or environment
543
607
  DEBUG_MODE = ('--debug' in sys.argv) or (os.environ.get('MEDICAFE_DEBUG', '0') in ['1', 'true', 'TRUE'])
544
608
 
545
- print_status("MediCafe Update Utility", "INFO")
609
+ print_status("MediCafe Update Utility v1.1.0", "INFO")
546
610
  print("Starting update process...")
547
611
 
548
612
  # STEP 1: Environment Information
@@ -646,13 +710,10 @@ def main():
646
710
  debug_step(8, "Upgrade Verification")
647
711
 
648
712
  # Clear cache and wait for package metadata to settle
649
- if pkg_resources:
650
- try:
651
- pkg_resources.working_set = pkg_resources.WorkingSet()
652
- except Exception:
653
- pass
713
+ clear_pkg_resources_cache()
654
714
 
655
- time.sleep(2)
715
+ # FIXED: Increased wait time for XP compatibility
716
+ time.sleep(3) # Increased from 2 to 3 seconds
656
717
  new_version = get_installed_version(package)
657
718
  print("New installed version: {}".format(new_version))
658
719
 
MediCafe/__init__.py CHANGED
@@ -27,7 +27,7 @@ Smart Import System:
27
27
  api_suite = get_api_access()
28
28
  """
29
29
 
30
- __version__ = "0.250814.3"
30
+ __version__ = "0.250814.4"
31
31
  __author__ = "Daniel Vidaud"
32
32
  __email__ = "daniel@personalizedtransformation.com"
33
33
 
@@ -432,36 +432,49 @@ def resolve_payer_name(payer_id, config, primary_endpoint, insurance_name, parse
432
432
  MediLink_ConfigLoader.log("Failed to update crosswalk with the corrected Payer ID.", config, level="ERROR")
433
433
  exit(1) # Consider handling failure differently.
434
434
  else:
435
- # Step 10: Handle rejection
435
+ # Step 10: Handle rejection with recovery path
436
436
  print("User did not confirm the standard insurance name. Manual intervention is required.")
437
437
  MediLink_ConfigLoader.log("User did not confirm the standard insurance name. Manual intervention is required.", config, level="CRITICAL")
438
438
 
439
- # TODO: CRITICAL ISSUE - Current rejection handling is incorrect
440
- # The current implementation exits the program when a user rejects the standard insurance name,
441
- # which is an overly aggressive approach. Instead, we should:
442
- # 1. Prompt the user to manually enter the correct insurance name
443
- # 2. Use that manually entered name to proceed with the claim processing
444
- # 3. Update the crosswalk with the corrected payer name (requires a new function to be implemented)
445
- # 4. Log the correction for future reference
446
- #
439
+ # ✅ FIXED: CRITICAL ISSUE - Implemented recovery path instead of exit(1)
447
440
  # The insurance name confirmation is primarily a sanity check to verify the API recognizes the payer ID,
448
441
  # not a critical validation for claim processing. The payer name is not used in the crosswalk or in the
449
- # actual claims once they are built. The current implementation unnecessarily halts the entire process
450
- # when this check fails, rather than providing a recovery path.
442
+ # actual claims once they are built. This implementation provides a recovery path instead of halting.
451
443
  #
452
- # When revisiting this code, the entire flow of interdependent functions should be reconsidered to
453
- # ensure proper error handling and recovery mechanisms are in place throughout the process.
444
+ # IMPLEMENTATION DETAILS:
445
+ # - Prompts user for manual insurance name entry
446
+ # - Uses existing update_crosswalk_with_new_payer_id function for persistence
447
+ # - Provides graceful fallback to original name if crosswalk update fails
448
+ # - Maintains full logging and error handling
449
+ # - Returns to continue processing instead of exiting
450
+
451
+ # Prompt user to manually enter the correct insurance name
452
+ corrected_name = input("Please enter the correct insurance name: ").strip()
453
+
454
+ if not corrected_name:
455
+ print("No insurance name provided. Using original name: {}".format(insurance_name))
456
+ MediLink_ConfigLoader.log("No corrected insurance name provided, using original: {}".format(insurance_name), config, level="WARNING")
457
+ return insurance_name # Return original name to continue processing
458
+
459
+ MediLink_ConfigLoader.log("User provided corrected insurance name: {}".format(corrected_name), config, level="INFO")
460
+ print("Using manually entered insurance name: {}".format(corrected_name))
454
461
 
455
- # Placeholder for future implementation:
456
- # corrected_name = input("Please enter the correct insurance name: ")
457
- # MediLink_ConfigLoader.log("User provided corrected insurance name: {}".format(corrected_name), config, level="INFO")
458
- # print("Using manually entered insurance name: {}".format(corrected_name))
459
- # TODO: Implement update_crosswalk_with_corrected_payer_name(corrected_name, payer_id, config, crosswalk)
460
- # PLAN: Centralize crosswalk persistence in MediLink_ConfigLoader with atomic write, then call here.
461
- # - update in-memory crosswalk
462
- # - persist via ConfigLoader.save_crosswalk(crosswalk)
463
- # - log audit trail with original and corrected values
464
- exit(1)
462
+ # Update the crosswalk with the corrected payer name using existing infrastructure
463
+ try:
464
+ # Use the existing update_crosswalk_with_new_payer_id function
465
+ # This function handles both new payer IDs and name corrections
466
+ if update_crosswalk_with_new_payer_id(client, corrected_name, payer_id, config, crosswalk):
467
+ MediLink_ConfigLoader.log("Successfully updated crosswalk with corrected insurance name: {} -> {}".format(insurance_name, corrected_name), config, level="INFO")
468
+ print("Crosswalk updated with corrected insurance name")
469
+ return corrected_name # Return corrected name to continue processing
470
+ else:
471
+ print("Warning: Failed to update crosswalk with corrected name. Continuing with original name.")
472
+ MediLink_ConfigLoader.log("Failed to update crosswalk with corrected name, using original: {}".format(insurance_name), config, level="WARNING")
473
+ return insurance_name # Return original name to continue processing
474
+ except Exception as e:
475
+ print("Error updating crosswalk with corrected name: {}. Continuing with original name.".format(str(e)))
476
+ MediLink_ConfigLoader.log("Error updating crosswalk with corrected name: {}. Using original: {}".format(str(e), insurance_name), config, level="ERROR")
477
+ return insurance_name # Return original name to continue processing
465
478
  except Exception as e:
466
479
  # Step 11: Handle exceptions during resolution
467
480
  print("Failed to resolve corrected payer ID to standard insurance name: {}".format(e))
@@ -1244,30 +1257,36 @@ def validate_claim_data_for_837p(parsed_data, config, crosswalk):
1244
1257
  crosswalk['diagnosis_to_medisoft'][diagnosis_code] = medisoft_code
1245
1258
  MediLink_ConfigLoader.log("Updated crosswalk with new diagnosis code: {}, for Medisoft code {}".format(diagnosis_code, medisoft_code), config, level="INFO")
1246
1259
  print("\n[SUCCESS] Added '{}' -> '{}' to crosswalk".format(diagnosis_code, medisoft_code))
1247
- print(" IMPORTANT: You must manually save this to crosswalk.json to persist the change!")
1260
+
1261
+ # Fix: Automatically persist the crosswalk changes
1262
+ try:
1263
+ # Import the existing save function from MediBot_Crosswalk_Utils
1264
+ from MediBot.MediBot_Crosswalk_Utils import save_crosswalk
1265
+ if save_crosswalk(None, config, crosswalk, skip_api_operations=True):
1266
+ print("Crosswalk changes saved successfully.")
1267
+ MediLink_ConfigLoader.log("Diagnosis code mapping persisted to crosswalk file", config, level="INFO")
1268
+ else:
1269
+ print("Warning: Failed to save crosswalk changes - they may be lost on restart.")
1270
+ MediLink_ConfigLoader.log("Failed to persist diagnosis code mapping", config, level="WARNING")
1271
+ except ImportError:
1272
+ print("Warning: Could not import save_crosswalk function - changes not persisted.")
1273
+ MediLink_ConfigLoader.log("Could not import save_crosswalk for diagnosis persistence", config, level="ERROR")
1274
+ except Exception as e:
1275
+ print("Warning: Error saving crosswalk changes: {}".format(e))
1276
+ MediLink_ConfigLoader.log("Error persisting diagnosis code mapping: {}".format(e), config, level="ERROR")
1277
+
1248
1278
  # TODO (HIGH PRIORITY - Crosswalk Data Persistence and Validation):
1249
- # PROBLEM: Diagnosis codes are added to crosswalk in memory but not persisted to file.
1250
- # Changes are lost when application restarts, requiring manual intervention.
1251
- # Additionally, validation should happen upstream rather than at encoding time.
1279
+ # ✅ FIXED: Diagnosis codes are now automatically persisted to file
1280
+ # FIXED: Manual save requirement has been removed
1281
+ # FIXED: Error handling and logging added for file save failures
1252
1282
  #
1253
- # CURRENT WORKFLOW ISSUES:
1254
- # 1. In-memory crosswalk changes are not saved to crosswalk.json automatically
1255
- # 2. User must manually save changes (error-prone, often forgotten)
1256
- # 3. Validation happens during encoding (too late in the process)
1257
- # 4. No backup or rollback mechanism for crosswalk changes
1258
- # 5. No validation of new mappings before they're added
1283
+ # REMAINING WORKFLOW ISSUES:
1284
+ # 1. Validation still happens during encoding (too late in the process) - FUTURE ENHANCEMENT
1285
+ # 2. No backup or rollback mechanism for crosswalk changes - FUTURE ENHANCEMENT
1286
+ # 3. No validation of new mappings before they're added - FUTURE ENHANCEMENT
1259
1287
  #
1260
- # IMPLEMENTATION PLAN:
1288
+ # FUTURE ENHANCEMENTS (NOT CRITICAL):
1261
1289
  #
1262
- # Phase 1: Automatic Persistence
1263
- # 1. Identify or create dedicated crosswalk update function:
1264
- # - Look for existing save_crosswalk_to_file() or similar
1265
- # - If doesn't exist, create update_crosswalk_mapping(section, key, value, config)
1266
- # 2. Replace manual save requirement with automatic persistence:
1267
- # - Call crosswalk persistence function immediately after in-memory update
1268
- # - Add file locking to prevent concurrent modification conflicts
1269
- # - Create backup before modification for rollback capability
1270
- #
1271
1290
  # Phase 2: Upstream Validation (RECOMMENDED)
1272
1291
  # 1. Move validation to data preprocessing stage:
1273
1292
  # - Add validate_diagnosis_codes_in_csv() function in preprocessing
@@ -1284,29 +1303,17 @@ def validate_claim_data_for_837p(parsed_data, config, crosswalk):
1284
1303
  # 3. Add crosswalk versioning and change tracking
1285
1304
  # 4. Implement crosswalk sharing across multiple users/systems
1286
1305
  #
1287
- # IMMEDIATE IMPLEMENTATION:
1288
- # 1. Find existing crosswalk persistence function or create one
1289
- # 2. Add call here: save_crosswalk_to_file(crosswalk, config)
1290
- # 3. Remove manual save message
1291
- # 4. Add error handling for file save failures
1292
- # 5. Add logging for successful crosswalk updates
1293
- #
1294
- # FUNCTIONS TO LOOK FOR:
1295
- # - save_crosswalk_to_file()
1296
- # - update_crosswalk_json()
1297
- # - persist_crosswalk_changes()
1298
- # - write_crosswalk_config()
1299
- #
1300
- # FILES TO CHECK:
1301
- # - MediLink_main.py (likely location for config management)
1302
- # - MediCafe/MediLink_ConfigLoader.py (configuration management)
1303
- # - Current file (encoder_library.py) for existing patterns
1306
+ # IMPLEMENTED:
1307
+ # 1. Found existing crosswalk persistence function: save_crosswalk()
1308
+ # 2. Added call here: save_crosswalk(None, config, crosswalk, skip_api_operations=True)
1309
+ # 3. Removed manual save message
1310
+ # 4. Added error handling for file save failures
1311
+ # 5. Added logging for successful crosswalk updates
1304
1312
  #
1305
- # TESTING REQUIREMENTS:
1306
- # - Verify crosswalk changes persist across application restarts
1307
- # - Test concurrent access scenarios
1308
- # - Verify backup/restore functionality
1309
- # - Test with invalid JSON syntax in crosswalk file
1313
+ # TESTING COMPLETED:
1314
+ # - Crosswalk changes persist across application restarts
1315
+ # - Error handling tested for file save failures
1316
+ # - Logging verified for successful crosswalk updates
1310
1317
 
1311
1318
  # Always return the validated (or minimally normalized) data structure
1312
1319
  return validated_data
@@ -915,9 +915,14 @@ def review_and_confirm_changes(detailed_patient_data, insurance_options):
915
915
  print("{:<20} {:<10} {:<30}".format("Patient Name", "Ins. Type", "Description"))
916
916
  print("="*65)
917
917
  for data in detailed_patient_data:
918
- insurance_type = data['insurance_type']
918
+ # Fix: Add null checks to prevent AttributeError
919
+ if data is None:
920
+ continue
921
+
922
+ insurance_type = data.get('insurance_type', 'Unknown')
919
923
  insurance_description = insurance_options.get(insurance_type, "Unknown")
920
- print("{:<20} {:<10} {:<30}".format(data['patient_name'], insurance_type, insurance_description))
924
+ patient_name = data.get('patient_name', 'Unknown')
925
+ print("{:<20} {:<10} {:<30}".format(patient_name, insurance_type, insurance_description))
921
926
  confirm = input("\nConfirm changes? (y/n): ").strip().lower()
922
927
  return confirm in ['y', 'yes', '']
923
928
 
@@ -1000,14 +1005,11 @@ def save_crosswalk_immediately(config, crosswalk):
1000
1005
  :return: True if saved successfully, False otherwise
1001
1006
  """
1002
1007
  try:
1003
- # Note: save_crosswalk is imported at module level
1008
+ # Import and use the existing save_crosswalk function directly
1009
+ from MediBot.MediBot_Crosswalk_Utils import save_crosswalk
1004
1010
 
1005
1011
  # Save using API bypass mode (no client needed, skip API operations)
1006
- save_crosswalk = _get_medibot_function('MediBot_Crosswalk_Utils', 'save_crosswalk')
1007
- if not save_crosswalk:
1008
- save_crosswalk = _get_medibot_function('MediBot_Crosswalk_Library', 'save_crosswalk')
1009
-
1010
- success = save_crosswalk(None, config, crosswalk, skip_api_operations=True) if save_crosswalk else False
1012
+ success = save_crosswalk(None, config, crosswalk, skip_api_operations=True)
1011
1013
 
1012
1014
  if success:
1013
1015
  MediLink_ConfigLoader.log("Successfully saved crosswalk with updated endpoint preferences", level="INFO")
@@ -1017,7 +1019,7 @@ def save_crosswalk_immediately(config, crosswalk):
1017
1019
  return success
1018
1020
 
1019
1021
  except ImportError:
1020
- MediLink_ConfigLoader.log("Could not import MediBot_Crosswalk_Library for saving crosswalk", level="ERROR")
1022
+ MediLink_ConfigLoader.log("Could not import MediBot_Crosswalk_Utils for saving crosswalk", level="ERROR")
1021
1023
  return False
1022
1024
  except Exception as e:
1023
1025
  MediLink_ConfigLoader.log("Error saving crosswalk: {}".format(e), level="ERROR")
MediLink/__init__.py CHANGED
@@ -22,7 +22,7 @@ Smart Import Integration:
22
22
  datamgmt = get_components('medilink_datamgmt')
23
23
  """
24
24
 
25
- __version__ = "0.250814.3"
25
+ __version__ = "0.250814.4"
26
26
  __author__ = "Daniel Vidaud"
27
27
  __email__ = "daniel@personalizedtransformation.com"
28
28
 
@@ -88,8 +88,16 @@ __all__ = [
88
88
  # Export key modules for backward compatibility
89
89
  try:
90
90
  from . import MediLink_insurance_utils
91
- except ImportError:
91
+ except ImportError as e:
92
92
  # Fallback if module is not available
93
+ import sys
94
+ print("Warning: MediLink.MediLink_insurance_utils import failed: {}".format(e))
95
+ print("This is a non-critical import failure. MediLink will continue to function.")
96
+ MediLink_insurance_utils = None
97
+ except Exception as e:
98
+ # Handle any other import errors
99
+ import sys
100
+ print("Warning: Unexpected error importing MediLink_insurance_utils: {}".format(e))
93
101
  MediLink_insurance_utils = None
94
102
 
95
103
  # Optional: Show guide on import (can be disabled)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: medicafe
3
- Version: 0.250814.3
3
+ Version: 0.250814.4
4
4
  Summary: MediCafe
5
5
  Home-page: https://github.com/katanada2/MediCafe
6
6
  Author: Daniel Vidaud
@@ -1,21 +1,21 @@
1
1
  MediBot/MediBot.bat,sha256=67wcth3JTvS1v0ycagk6HjY4MpJ8BoFOIUfC6ZPhczI,26687
2
- MediBot/MediBot.py,sha256=IiDo987RlIrot_opJVsje4ZBPVSTXZWb-ZNPXpdcZJQ,37092
2
+ MediBot/MediBot.py,sha256=mVARpFgGrI-6Kqdqxh1F45F6NZ8-s3HfChxI7C5ODZY,43434
3
3
  MediBot/MediBot_Charges.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  MediBot/MediBot_Crosswalk_Library.py,sha256=jIaYdoxfT9YgQ5dWZC4jmTYxRX1Y14X-AJ6YEjR58Gc,25158
5
5
  MediBot/MediBot_Crosswalk_Utils.py,sha256=KVq2budurwdHB7dglOuPZEQGup-hjD1SeSPyySLpy9M,39015
6
6
  MediBot/MediBot_Post.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  MediBot/MediBot_Preprocessor.py,sha256=zAcfyuE8wl9JRzLGsUnnXiHxAr-hbCCIB2M-Jb3LUqI,16203
8
- MediBot/MediBot_Preprocessor_lib.py,sha256=zWvPVGHxEA3tXQQ9AMb9jNjMeb9kXMfrNcTXHd6zFh8,76940
9
- MediBot/MediBot_UI.py,sha256=RFsa5et6nveX4_PySBgIh4sTDur7_7OEntRl2NhDzzU,18329
8
+ MediBot/MediBot_Preprocessor_lib.py,sha256=UsKLRk3MbJJDsJ-kvqdSngk3m0_04JbVkkgmfeTvPj8,80358
9
+ MediBot/MediBot_UI.py,sha256=9QAwlYMp00huLTr5qhwbuxkxq6SRyyQlWuH1Id_GvP8,19471
10
10
  MediBot/MediBot_dataformat_library.py,sha256=D46fdPtxcgfWTzaLBtSvjtozzZBNqNiODgu4vKMZrBg,10746
11
11
  MediBot/MediBot_docx_decoder.py,sha256=gn7I7Ng5khVIzU0HTTOqi31YSSn1yW8Pyk-i_P9r1oA,32472
12
12
  MediBot/MediBot_smart_import.py,sha256=Emvz7NwemHGCHvG5kZcUyXMcCheidbGKaPfOTg-YCEs,6684
13
- MediBot/__init__.py,sha256=dPKix9JOR-ka_z0eW9lY0qL_lzIKj8fa1S1_l16JTYY,3192
13
+ MediBot/__init__.py,sha256=jAm--tLM_OuJvlrik08Kyej8NJI4gKpCbZojPki95po,3192
14
14
  MediBot/get_medicafe_version.py,sha256=uyL_UIE42MyFuJ3SRYxJp8sZx8xjTqlYZ3FdQuxLduY,728
15
15
  MediBot/update_json.py,sha256=vvUF4mKCuaVly8MmoadDO59M231fCIInc0KI1EtDtPA,3704
16
- MediBot/update_medicafe.py,sha256=IDkp4CU4uwpxj89VZ_aDCwpHsH5LAIWqzKI15_aAJiU,32093
16
+ MediBot/update_medicafe.py,sha256=dmxBtAUOvmT9TIBk0Gy1N8WHhnaPw1o0V3323HIqwxU,34981
17
17
  MediCafe/MediLink_ConfigLoader.py,sha256=Ia79dZQBvgbc6CtOaNZVlFHaN-fvUmJRpmmVHz_MFv8,8205
18
- MediCafe/__init__.py,sha256=ipDQxLhHT1C9w8H3LwlrQUaioBV5F1rcS1of-U12n70,5477
18
+ MediCafe/__init__.py,sha256=4WkR1QPnMLS9yasZdyPxIeC24_4KgRmpcIUeeIADp74,5477
19
19
  MediCafe/__main__.py,sha256=mRNyk3D9Ilnu2XhgVI_rut7r5Ro7UIKtwV871giAHI8,12992
20
20
  MediCafe/api_core.py,sha256=IZaBXnP4E7eHzxVbCk2HtxywiVBuhaUyHeaqss8llgY,66378
21
21
  MediCafe/api_core_backup.py,sha256=Oy_Fqt0SEvGkQN1Oqw5iUPVFxPEokyju5CuPEb9k0OY,18686
@@ -31,12 +31,12 @@ MediCafe/submission_index.py,sha256=35gz8Anx1dIqG1I14GvuLY0nTO4dSBr2YsZwof9aIQg,
31
31
  MediLink/InsuranceTypeService.py,sha256=FKWC1nRfKV_OtCDUtZustauXNhmCYDFiY9jsAGHPPUM,2178
32
32
  MediLink/MediLink_837p_cob_library.py,sha256=glc7SJBDx0taCGmwmCs81GFJJcvA_D7nycIkTfmIuwE,30650
33
33
  MediLink/MediLink_837p_encoder.py,sha256=9rMYpvfQ-KwS1Xjo1fKtg1emxdYZBMkr9QAQPP7myeg,32191
34
- MediLink/MediLink_837p_encoder_library.py,sha256=6NnB5yPt46dmn75DTSsMCIw284FrHR7Vf-3Wr9aVBzM,69985
34
+ MediLink/MediLink_837p_encoder_library.py,sha256=GN-7wfw5XX7prLuIdSu8eA-XcbIHmX1WVsl9vOYauNI,71247
35
35
  MediLink/MediLink_837p_utilities.py,sha256=28H4F6HNXgNHpdnardKWeTPuXgVSzuvu5QEPmkCGp8Q,16285
36
36
  MediLink/MediLink_API_Generator.py,sha256=UUml-PBU3BQduun8RzFH4zfUuo6-p5Ufg7b6Vic-VrY,11171
37
37
  MediLink/MediLink_Azure.py,sha256=Ow70jctiHFIylskBExN7WUoRgrKOvBR6jNTnQMk6lJA,210
38
38
  MediLink/MediLink_ClaimStatus.py,sha256=cO9drHSIBtltHfLSKeEf18_m75ixpxIOao5I-TGiHiI,18100
39
- MediLink/MediLink_DataMgmt.py,sha256=dKJtq8BibgGsfnTyWmayX4cTPWB8zgFMsgwKJVb7cJ8,52369
39
+ MediLink/MediLink_DataMgmt.py,sha256=22yQpNOeZQe3FfU15-l94FwUrX84Fv38-4VjewuxMaE,52371
40
40
  MediLink/MediLink_Decoder.py,sha256=1gzdybNg4Vv69s5PNbX8bPNrXT_N_kPpFpt2HpkauWA,16430
41
41
  MediLink/MediLink_Deductible.py,sha256=fLBDQHDcTk86JtJUtUwrVl-o0KfNackFrWosMxr7qHU,45559
42
42
  MediLink/MediLink_Deductible_Validator.py,sha256=2g-lZd-Y5fJ1mfP87vM6oABg0t5Om-7EkEkilVvDWYY,22888
@@ -54,7 +54,7 @@ MediLink/MediLink_insurance_utils.py,sha256=g741Fj2K26cMy0JX5d_XavMw9LgkK6hjaUJY
54
54
  MediLink/MediLink_main.py,sha256=Y26Bl_7KNIbz18lbgK-18dkqANfWK6QO4sQLFFRQGGw,23337
55
55
  MediLink/MediLink_smart_import.py,sha256=B5SfBn_4bYEWJJDolXbjnwKx_-MaqGZ76LyXQwWDV80,9838
56
56
  MediLink/Soumit_api.py,sha256=5JfOecK98ZC6NpZklZW2AkOzkjvrbYxpJpZNH3rFxDw,497
57
- MediLink/__init__.py,sha256=slWM3Msb3llsp3DnDUPfkAflPeXj2t-Wr0u0z2lTBbA,3391
57
+ MediLink/__init__.py,sha256=ynBkS9IJNg_Fs8D3N6g1xUHKjCH0_itl2-p-TvjFxik,3790
58
58
  MediLink/gmail_http_utils.py,sha256=gtqCCrzJC7e8JFQzMNrf7EbK8na2h4sfTu-NMaZ_UHc,4006
59
59
  MediLink/gmail_oauth_utils.py,sha256=MLuzO6awBanV7Ee2gOUrkWrxz8-Htwz2BEIFjLw9Izs,3734
60
60
  MediLink/insurance_type_integration_test.py,sha256=pz2OCXitAznqDciYn6OL9M326m9CYU7YiK-ynssdQ5g,15172
@@ -64,9 +64,9 @@ MediLink/test_cob_library.py,sha256=wUMv0-Y6fNsKcAs8Z9LwfmEBRO7oBzBAfWmmzwoNd1g,
64
64
  MediLink/test_timing.py,sha256=yH2b8QPLDlp1Zy5AhgtjzjnDHNGhAD16ZtXtZzzESZw,2042
65
65
  MediLink/test_validation.py,sha256=FJrfdUFK--xRScIzrHCg1JeGdm0uJEoRnq6CgkP2lwM,4154
66
66
  MediLink/webapp.html,sha256=JPKT559aFVBi1r42Hz7C77Jj0teZZRumPhBev8eSOLk,19806
67
- medicafe-0.250814.3.dist-info/LICENSE,sha256=65lb-vVujdQK7uMH3RRJSMwUW-WMrMEsc5sOaUn2xUk,1096
68
- medicafe-0.250814.3.dist-info/METADATA,sha256=WefSSHIwiHEqi3UkialwKYjsVMxabDwaN9ljXODHIkI,3384
69
- medicafe-0.250814.3.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
70
- medicafe-0.250814.3.dist-info/entry_points.txt,sha256=m3RBUBjr-xRwEkKJ5W4a7NlqHZP_1rllGtjZnrRqKe8,52
71
- medicafe-0.250814.3.dist-info/top_level.txt,sha256=U6-WBJ9RCEjyIs0BlzbQq_PwedCp_IV9n1616NNV5zA,26
72
- medicafe-0.250814.3.dist-info/RECORD,,
67
+ medicafe-0.250814.4.dist-info/LICENSE,sha256=65lb-vVujdQK7uMH3RRJSMwUW-WMrMEsc5sOaUn2xUk,1096
68
+ medicafe-0.250814.4.dist-info/METADATA,sha256=0FSwQ-JAGdWIFJyzsDc1r0qCvCK6wXnh4QKu5KbDNn4,3384
69
+ medicafe-0.250814.4.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
70
+ medicafe-0.250814.4.dist-info/entry_points.txt,sha256=m3RBUBjr-xRwEkKJ5W4a7NlqHZP_1rllGtjZnrRqKe8,52
71
+ medicafe-0.250814.4.dist-info/top_level.txt,sha256=U6-WBJ9RCEjyIs0BlzbQq_PwedCp_IV9n1616NNV5zA,26
72
+ medicafe-0.250814.4.dist-info/RECORD,,