medicafe 0.250822.2__py3-none-any.whl → 0.250909.0__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.
@@ -80,7 +80,7 @@ _DAY_MAP = {
80
80
  }
81
81
 
82
82
 
83
- def parse_docx(filepath, surgery_dates): # Accept surgery_dates as a parameter
83
+ def parse_docx(filepath, surgery_dates, capture_schedule_positions=False): # Accept surgery_dates as a parameter
84
84
  if Document is None:
85
85
  MediLink_ConfigLoader.log("docx module not available, cannot parse .docx files", level="WARNING")
86
86
  return {}
@@ -99,6 +99,7 @@ def parse_docx(filepath, surgery_dates): # Accept surgery_dates as a parameter
99
99
  return {}
100
100
 
101
101
  patient_data = OrderedDict() # Initialize OrderedDict to store data
102
+ schedule_positions = {} # NEW: Track patient order in schedule
102
103
  MediLink_ConfigLoader.log("Extracting Date of Service from {}".format(filepath), level="DEBUG")
103
104
 
104
105
  # TIMING: Start date extraction
@@ -134,7 +135,7 @@ def parse_docx(filepath, surgery_dates): # Accept surgery_dates as a parameter
134
135
 
135
136
  for table in doc.tables: # Iterate over tables in the document
136
137
  tables_processed += 1
137
- for row in table.rows:
138
+ for row_idx, row in enumerate(table.rows):
138
139
  rows_processed += 1
139
140
  cells = [cell.text.strip() for cell in row.cells]
140
141
  if len(cells) > 4 and cells[3].startswith('#'):
@@ -152,6 +153,12 @@ def parse_docx(filepath, surgery_dates): # Accept surgery_dates as a parameter
152
153
  MediLink_ConfigLoader.log("Duplicate entry for patient ID {} on date {}. Skipping.".format(patient_id, date_of_service), level="WARNING")
153
154
  else:
154
155
  patient_data[patient_id][date_of_service] = [diagnosis_code, left_or_right_eye, femto_yes_or_no]
156
+
157
+ # NEW: Store schedule position if requested
158
+ if capture_schedule_positions:
159
+ if patient_id not in schedule_positions:
160
+ schedule_positions[patient_id] = {}
161
+ schedule_positions[patient_id][date_of_service] = row_idx
155
162
  except Exception as e:
156
163
  MediLink_ConfigLoader.log("Error processing row: {}. Error: {}".format(cells, e), level="ERROR")
157
164
 
@@ -183,7 +190,11 @@ def parse_docx(filepath, surgery_dates): # Accept surgery_dates as a parameter
183
190
  print(" * Validation: {:.3f}s".format(validation_duration))
184
191
  print(" * Total: {:.3f}s".format(total_duration))
185
192
 
186
- return patient_data
193
+ # Return both data structures if schedule positions were captured
194
+ if capture_schedule_positions:
195
+ return patient_data, schedule_positions
196
+ else:
197
+ return patient_data
187
198
 
188
199
 
189
200
  def validate_unknown_entries(patient_data):
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.250822.2"
22
+ __version__ = "0.250909.0"
23
23
  __author__ = "Daniel Vidaud"
24
24
  __email__ = "daniel@personalizedtransformation.com"
25
25
 
@@ -32,7 +32,18 @@ def get_default_config():
32
32
  'logging': {
33
33
  'level': 'INFO',
34
34
  'console_output': True
35
- }
35
+ },
36
+ # STRATEGIC NOTE (COB Configuration): COB library is fully implemented and ready
37
+ # To enable COB functionality, add the following configuration:
38
+ # 'cob_settings': {
39
+ # 'enabled': False, # Set to True to activate COB processing
40
+ # 'medicare_payer_ids': ['00850', 'MEDICARE', 'CMS', 'MCARE'],
41
+ # 'cob_mode': 'single_payer_only', # or 'multi_payer_supported'
42
+ # 'validation_level': 3, # SNIP level 3+ recommended for COB
43
+ # 'medicare_advantage_identifiers': ['MA', 'MC'],
44
+ # 'default_medicare_type': 'MB',
45
+ # 'require_835_validation': False # Set True for production
46
+ # }
36
47
  }
37
48
  }
38
49
 
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.250822.2"
30
+ __version__ = "0.250909.0"
31
31
  __author__ = "Daniel Vidaud"
32
32
  __email__ = "daniel@personalizedtransformation.com"
33
33
 
MediCafe/api_core.py CHANGED
@@ -118,10 +118,107 @@ except ImportError:
118
118
  class TokenCache:
119
119
  def __init__(self):
120
120
  self.tokens = {}
121
- def get(self, endpoint_name, current_time):
122
- return None
123
- def set(self, endpoint_name, access_token, expires_in, current_time):
124
- pass
121
+
122
+ # -----------------------------------------------------------------------------
123
+ # Endpoint-specific payer ID management (crosswalk-backed with hardcoded default)
124
+ # -----------------------------------------------------------------------------
125
+ # Intent:
126
+ # - Validate payer IDs against the endpoint actually being called.
127
+ # - Persist endpoint-specific payer ID lists into the crosswalk so they can be
128
+ # updated over time without changing code.
129
+ # - For OPTUMAI: use the augmented list (includes LIFE1, WELM2, etc.).
130
+ # - For UHCAPI (including its Super Connector fallback): strictly enforce the
131
+ # known-good UHC payer IDs only.
132
+ # - Future: OPTUMAI will expose a dedicated endpoint that returns its current
133
+ # valid payer list. When available, this function should fetch and refresh the
134
+ # crosswalk entry automatically (likely weekly/monthly), replacing the
135
+ # hardcoded default below. The UHCAPI Super Connector will eventually be
136
+ # deprecated; when removed, cleanup the UHC-specific paths accordingly.
137
+
138
+ try:
139
+ # Prefer using existing crosswalk persistence utilities
140
+ from MediBot.MediBot_Crosswalk_Utils import ensure_full_config_loaded, save_crosswalk
141
+ except Exception:
142
+ ensure_full_config_loaded = None
143
+ save_crosswalk = None
144
+
145
+ def _get_default_endpoint_payer_ids(endpoint_name):
146
+ """
147
+ Return hardcoded default payer IDs for a given endpoint.
148
+
149
+ NOTE: Defaults are used when crosswalk does not yet contain a list.
150
+ """
151
+ # UHC-only list – keep STRICT. Do not augment with non-UHC payers.
152
+ uhc_payer_ids = [
153
+ "87726", "03432", "96385", "95467", "86050", "86047", "95378", "06111", "37602"
154
+ ]
155
+
156
+ # OPTUMAI – augmented list (subject to growth once the API adds a payer-list endpoint)
157
+ optumai_payer_ids = [
158
+ "87726", "06111", "25463", "37602", "39026", "74227", "65088", "81400",
159
+ "03432", "86050", "86047", "95378", "95467", "LIFE1", "WELM2"
160
+ ]
161
+
162
+ if endpoint_name == 'OPTUMAI':
163
+ return optumai_payer_ids
164
+ # Default to UHCAPI for any other endpoint name
165
+ return uhc_payer_ids
166
+
167
+ def get_valid_payer_ids_for_endpoint(client, endpoint_name):
168
+ """
169
+ Resolve the valid payer IDs for a specific endpoint using crosswalk storage
170
+ with a safe fallback to hardcoded defaults.
171
+
172
+ Behavior:
173
+ - Attempts to read crosswalk['endpoint_payer_ids'][endpoint_name].
174
+ - If missing, initializes with hardcoded defaults and persists to crosswalk
175
+ (non-interactive) so that future sessions use the saved list.
176
+ - Future: For OPTUMAI, replace the hardcoded default by calling the API's
177
+ payer-list endpoint once available, then update the crosswalk.
178
+ """
179
+ try:
180
+ # Load full config + crosswalk (non-destructive)
181
+ base_config = None
182
+ crosswalk = None
183
+ if ensure_full_config_loaded is not None:
184
+ base_config, crosswalk = ensure_full_config_loaded(
185
+ getattr(client, 'config', None),
186
+ getattr(client, 'crosswalk', None)
187
+ )
188
+ else:
189
+ # Fallback: attempt to load via MediLink_ConfigLoader directly
190
+ # If we reach this fallback, it means ensure_full_config_loaded is not available.
191
+ # This is unexpected in normal operation and should be alerted.
192
+ print("Warning: IN api_core, ensure_full_config_loaded is not available; falling back to MediLink_ConfigLoader.load_configuration().")
193
+ MediLink_ConfigLoader.log(
194
+ "Fallback: ensure_full_config_loaded not available in get_valid_payer_ids_for_endpoint; using MediLink_ConfigLoader.load_configuration().",
195
+ level="WARNING"
196
+ )
197
+ base_config, crosswalk = MediLink_ConfigLoader.load_configuration()
198
+
199
+ # Extract any existing stored list
200
+ cw_ep = crosswalk.get('endpoint_payer_ids', {}) if isinstance(crosswalk, dict) else {}
201
+ existing = cw_ep.get(endpoint_name)
202
+ if isinstance(existing, list) and len(existing) > 0:
203
+ return existing
204
+
205
+ # Initialize from defaults and persist to crosswalk
206
+ defaults = _get_default_endpoint_payer_ids(endpoint_name)
207
+ if isinstance(crosswalk, dict):
208
+ if 'endpoint_payer_ids' not in crosswalk:
209
+ crosswalk['endpoint_payer_ids'] = {}
210
+ crosswalk['endpoint_payer_ids'][endpoint_name] = list(defaults)
211
+
212
+ # Persist without interactive prompts; ignore errors silently to avoid breaking flows
213
+ if save_crosswalk is not None:
214
+ try:
215
+ save_crosswalk(client, base_config, crosswalk, skip_api_operations=True)
216
+ except Exception:
217
+ pass
218
+ return defaults
219
+ except Exception:
220
+ # As a last resort, return a safe default for the endpoint
221
+ return _get_default_endpoint_payer_ids(endpoint_name)
125
222
 
126
223
  class BaseAPIClient:
127
224
  def __init__(self, config):
@@ -792,12 +889,14 @@ def get_eligibility_v3(client, payer_id, provider_last_name, search_option, date
792
889
  if not all([client, payer_id, provider_last_name, search_option, date_of_birth, member_id, npi]):
793
890
  raise ValueError("All required parameters must have values: client, payer_id, provider_last_name, search_option, date_of_birth, member_id, npi")
794
891
 
795
- # Validate payer_id
796
- valid_payer_ids = ["87726", "06111", "25463", "37602", "39026", "74227", "65088", "81400", "03432", "86050", "86047", "95378", "95467"]
797
- if payer_id not in valid_payer_ids:
798
- raise ValueError("Invalid payer_id: {}. Must be one of: {}".format(payer_id, ", ".join(valid_payer_ids)))
799
-
892
+ # Endpoint is UHCAPI for this v3 REST call
800
893
  endpoint_name = 'UHCAPI'
894
+
895
+ # Validate payer_id strictly against UHC list
896
+ valid_payer_ids = get_valid_payer_ids_for_endpoint(client, endpoint_name)
897
+ if payer_id not in valid_payer_ids:
898
+ raise ValueError("Invalid payer_id: {} for endpoint {}. Must be one of: {}".format(
899
+ payer_id, endpoint_name, ", ".join(valid_payer_ids)))
801
900
  from MediCafe.core_utils import extract_medilink_config
802
901
  medi = extract_medilink_config(client.config)
803
902
  url_extension = medi.get('endpoints', {}).get(endpoint_name, {}).get('additional_endpoints', {}).get('eligibility_v3', '')
@@ -856,11 +955,6 @@ def get_eligibility_super_connector(client, payer_id, provider_last_name, search
856
955
  if not all([client, payer_id, provider_last_name, search_option, date_of_birth, member_id, npi]):
857
956
  raise ValueError("All required parameters must have values: client, payer_id, provider_last_name, search_option, date_of_birth, member_id, npi")
858
957
 
859
- # Validate payer_id
860
- valid_payer_ids = ["87726", "06111", "25463", "37602", "39026", "74227", "65088", "81400", "03432", "86050", "86047", "95378", "95467"]
861
- if payer_id not in valid_payer_ids:
862
- raise ValueError("Invalid payer_id: {}. Must be one of: {}".format(payer_id, ", ".join(valid_payer_ids)))
863
-
864
958
  # Prefer OPTUMAI endpoint if configured, otherwise fall back to legacy UHCAPI super connector
865
959
  try:
866
960
  endpoints_cfg = client.config['MediLink_Config']['endpoints']
@@ -889,6 +983,14 @@ def get_eligibility_super_connector(client, payer_id, provider_last_name, search
889
983
  except Exception:
890
984
  url_extension = None
891
985
 
986
+ # Validate payer_id against the selected endpoint's list
987
+ # - If OPTUMAI is used, allow the augmented list (includes LIFE1, WELM2, etc.).
988
+ # - If UHCAPI fallback is used, enforce strict UHC list only.
989
+ valid_payer_ids = get_valid_payer_ids_for_endpoint(client, endpoint_name)
990
+ if payer_id not in valid_payer_ids:
991
+ raise ValueError("Invalid payer_id: {} for endpoint {}. Must be one of: {}".format(
992
+ payer_id, endpoint_name, ", ".join(valid_payer_ids)))
993
+
892
994
  if not url_extension:
893
995
  raise ValueError("Eligibility endpoint not configured for {}".format(endpoint_name))
894
996
 
MediCafe/core_utils.py CHANGED
@@ -499,9 +499,7 @@ def get_api_client_factory():
499
499
  """
500
500
  # Try multiple import paths for factory
501
501
  import_specs = [
502
- ('MediCafe.api_factory', 'APIClientFactory'),
503
- ('MediLink.MediLink_API_Factory', 'APIClientFactory'), # Legacy fallback
504
- ('MediLink_API_Factory', 'APIClientFactory') # Legacy fallback
502
+ ('MediCafe.api_factory', 'APIClientFactory')
505
503
  ]
506
504
 
507
505
  APIClientFactory = import_with_alternatives(import_specs)
@@ -728,4 +726,11 @@ def check_ascii_files(paths):
728
726
  except Exception:
729
727
  # If a failure occurs mid-scan, return what we have so far
730
728
  return problematic
731
- return problematic
729
+ return problematic
730
+
731
+ def sanitize_log(message):
732
+ # Simple masking: replace DOB-like with ****-**-**, IDs with last4
733
+ import re
734
+ message = re.sub(r'\d{4}-\d{2}-\d{2}', '****-**-**', message) # DOB
735
+ message = re.sub(r'\d{9,}', lambda m: '***' + m.group(0)[-4:], message) # IDs
736
+ return message