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.
- MediBot/MediBot.py +11 -4
- MediBot/MediBot_Crosswalk_Library.py +16 -3
- MediBot/MediBot_Crosswalk_Utils.py +12 -2
- MediBot/MediBot_Preprocessor_lib.py +1821 -1728
- MediBot/MediBot_docx_decoder.py +14 -3
- MediBot/__init__.py +1 -1
- MediCafe/MediLink_ConfigLoader.py +12 -1
- MediCafe/__init__.py +1 -1
- MediCafe/api_core.py +116 -14
- MediCafe/core_utils.py +9 -4
- MediCafe/deductible_utils.py +1233 -0
- MediLink/MediLink_837p_encoder_library.py +123 -39
- MediLink/MediLink_Deductible.py +569 -555
- MediLink/MediLink_Deductible_Validator.py +9 -3
- MediLink/MediLink_Display_Utils.py +364 -2
- MediLink/MediLink_UI.py +20 -2
- MediLink/__init__.py +1 -1
- {medicafe-0.250822.2.dist-info → medicafe-0.250909.0.dist-info}/METADATA +1 -1
- {medicafe-0.250822.2.dist-info → medicafe-0.250909.0.dist-info}/RECORD +23 -27
- MediCafe/api_core_backup.py +0 -428
- MediLink/insurance_type_integration_test.py +0 -361
- MediLink/test_cob_library.py +0 -436
- MediLink/test_timing.py +0 -59
- MediLink/test_validation.py +0 -127
- {medicafe-0.250822.2.dist-info → medicafe-0.250909.0.dist-info}/LICENSE +0 -0
- {medicafe-0.250822.2.dist-info → medicafe-0.250909.0.dist-info}/WHEEL +0 -0
- {medicafe-0.250822.2.dist-info → medicafe-0.250909.0.dist-info}/entry_points.txt +0 -0
- {medicafe-0.250822.2.dist-info → medicafe-0.250909.0.dist-info}/top_level.txt +0 -0
@@ -19,6 +19,9 @@ def deep_search_for_value(data, target_value, path="", max_depth=10, current_dep
|
|
19
19
|
if current_depth > max_depth:
|
20
20
|
return []
|
21
21
|
|
22
|
+
if data is None:
|
23
|
+
return []
|
24
|
+
|
22
25
|
found_paths = []
|
23
26
|
|
24
27
|
if isinstance(data, dict):
|
@@ -54,7 +57,7 @@ def extract_legacy_values_for_comparison(legacy_data):
|
|
54
57
|
comparison_values = {}
|
55
58
|
|
56
59
|
if not legacy_data or "memberPolicies" not in legacy_data:
|
57
|
-
return
|
60
|
+
return {}
|
58
61
|
|
59
62
|
for policy in legacy_data.get("memberPolicies", []):
|
60
63
|
# Skip non-medical policies
|
@@ -341,6 +344,9 @@ def analyze_response_structure(data, max_depth=5):
|
|
341
344
|
if depth > max_depth:
|
342
345
|
return
|
343
346
|
|
347
|
+
if obj is None:
|
348
|
+
return
|
349
|
+
|
344
350
|
if isinstance(obj, dict):
|
345
351
|
for key, value in obj.items():
|
346
352
|
current_path = "{}.{}".format(path, key) if path else key
|
@@ -495,10 +501,10 @@ def run_validation_comparison(legacy_data, super_connector_data, output_file_pat
|
|
495
501
|
return validation_report
|
496
502
|
|
497
503
|
# Extract values from legacy response (handles None gracefully)
|
498
|
-
legacy_values = extract_legacy_values_for_comparison(legacy_data)
|
504
|
+
legacy_values = extract_legacy_values_for_comparison(legacy_data or {})
|
499
505
|
|
500
506
|
# Validate Super Connector response (handles None gracefully)
|
501
|
-
validation_report = validate_super_connector_response(legacy_values, super_connector_data)
|
507
|
+
validation_report = validate_super_connector_response(legacy_values, super_connector_data or {})
|
502
508
|
|
503
509
|
# Add API status information
|
504
510
|
if not legacy_data:
|
@@ -91,5 +91,367 @@ def display_file_summary(index, summary):
|
|
91
91
|
insurance_display,
|
92
92
|
source_display,
|
93
93
|
duplicate_flag,
|
94
|
-
effective_endpoint[:20])
|
95
|
-
|
94
|
+
effective_endpoint[:20]))
|
95
|
+
|
96
|
+
def display_enhanced_deductible_table(data, context="pre_api", title=None):
|
97
|
+
"""
|
98
|
+
Enhanced deductible table display with unified philosophy for both pre-API and post-API contexts.
|
99
|
+
|
100
|
+
Args:
|
101
|
+
data: List of patient records (CSV rows for pre_api, or eligibility results for post_api)
|
102
|
+
context: "pre_api" (valid rows identification) or "post_api" (eligibility results)
|
103
|
+
title: Custom title for the table
|
104
|
+
"""
|
105
|
+
if not data:
|
106
|
+
print("No data to display.")
|
107
|
+
return
|
108
|
+
|
109
|
+
# Set default titles based on context
|
110
|
+
if title is None:
|
111
|
+
if context == "pre_api":
|
112
|
+
title = "Valid Patients for Deductible Lookup ({} patients found)".format(len(data))
|
113
|
+
else:
|
114
|
+
title = "Eligibility Lookup Results"
|
115
|
+
|
116
|
+
print("\n{}".format(title))
|
117
|
+
print()
|
118
|
+
|
119
|
+
# Normalize data for consistent processing
|
120
|
+
normalized_data = []
|
121
|
+
for item in data:
|
122
|
+
if context == "pre_api":
|
123
|
+
# Pre-API: working with CSV row data
|
124
|
+
normalized_item = _normalize_pre_api_data(item)
|
125
|
+
else:
|
126
|
+
# Post-API: working with eligibility results
|
127
|
+
normalized_item = _normalize_post_api_data(item)
|
128
|
+
|
129
|
+
if normalized_item:
|
130
|
+
normalized_data.append(normalized_item)
|
131
|
+
|
132
|
+
if not normalized_data:
|
133
|
+
print("No valid data to display after normalization.")
|
134
|
+
return
|
135
|
+
|
136
|
+
# Sort data: by patient name, then by service date
|
137
|
+
normalized_data.sort(key=lambda x: (
|
138
|
+
x.get('patient_name', '').upper(),
|
139
|
+
x.get('service_date_sort', datetime.min),
|
140
|
+
x.get('patient_id', '')
|
141
|
+
))
|
142
|
+
|
143
|
+
# Group by patient for enhanced display
|
144
|
+
grouped_data = _group_by_patient(normalized_data)
|
145
|
+
|
146
|
+
# Calculate column widths for proper alignment
|
147
|
+
col_widths = _calculate_column_widths(normalized_data, context)
|
148
|
+
|
149
|
+
# Display header
|
150
|
+
_display_table_header(col_widths, context)
|
151
|
+
|
152
|
+
# Display data with grouping
|
153
|
+
line_number = 1
|
154
|
+
for patient_id, patient_records in grouped_data.items():
|
155
|
+
for idx, record in enumerate(patient_records):
|
156
|
+
if idx == 0:
|
157
|
+
# Primary line with line number
|
158
|
+
_display_primary_line(record, line_number, col_widths, context)
|
159
|
+
line_number += 1
|
160
|
+
else:
|
161
|
+
# Secondary lines with dashes
|
162
|
+
_display_secondary_line(record, col_widths, context)
|
163
|
+
|
164
|
+
print() # Add blank line after table
|
165
|
+
|
166
|
+
def _normalize_pre_api_data(row):
|
167
|
+
"""Normalize CSV row data for pre-API display"""
|
168
|
+
try:
|
169
|
+
# Extract patient name
|
170
|
+
patient_name = _format_patient_name_from_csv(row)
|
171
|
+
|
172
|
+
# Extract service date
|
173
|
+
service_date_display, service_date_sort = _extract_service_date_from_csv(row)
|
174
|
+
|
175
|
+
# Extract other fields
|
176
|
+
dob = row.get('Patient DOB', row.get('DOB', ''))
|
177
|
+
member_id = row.get('Primary Policy Number', row.get('Ins1 Member ID', '')).strip()
|
178
|
+
payer_id = row.get('Ins1 Payer ID', '')
|
179
|
+
patient_id = row.get('Patient ID #2', row.get('Patient ID', ''))
|
180
|
+
|
181
|
+
return {
|
182
|
+
'patient_id': str(patient_id),
|
183
|
+
'patient_name': patient_name,
|
184
|
+
'dob': dob,
|
185
|
+
'member_id': member_id,
|
186
|
+
'payer_id': str(payer_id),
|
187
|
+
'service_date_display': service_date_display,
|
188
|
+
'service_date_sort': service_date_sort,
|
189
|
+
'status': 'Ready',
|
190
|
+
'insurance_type': '',
|
191
|
+
'policy_status': '',
|
192
|
+
'remaining_amount': ''
|
193
|
+
}
|
194
|
+
except Exception as e:
|
195
|
+
MediLink_ConfigLoader.log("Error normalizing pre-API data: {}".format(e), level="WARNING")
|
196
|
+
return None
|
197
|
+
|
198
|
+
def _normalize_post_api_data(eligibility_result):
|
199
|
+
"""Normalize eligibility result data for post-API display"""
|
200
|
+
try:
|
201
|
+
# Handle the enhanced format that comes from convert_eligibility_to_enhanced_format
|
202
|
+
if isinstance(eligibility_result, dict):
|
203
|
+
return {
|
204
|
+
'patient_id': str(eligibility_result.get('patient_id', '')),
|
205
|
+
'patient_name': str(eligibility_result.get('patient_name', '')),
|
206
|
+
'dob': str(eligibility_result.get('dob', '')),
|
207
|
+
'member_id': str(eligibility_result.get('member_id', '')),
|
208
|
+
'payer_id': str(eligibility_result.get('payer_id', '')),
|
209
|
+
'service_date_display': str(eligibility_result.get('service_date_display', '')),
|
210
|
+
'service_date_sort': eligibility_result.get('service_date_sort', datetime.min),
|
211
|
+
'status': str(eligibility_result.get('status', 'Processed')),
|
212
|
+
'insurance_type': str(eligibility_result.get('insurance_type', '')),
|
213
|
+
'policy_status': str(eligibility_result.get('policy_status', '')),
|
214
|
+
'remaining_amount': str(eligibility_result.get('remaining_amount', '')),
|
215
|
+
'data_source': str(eligibility_result.get('data_source', ''))
|
216
|
+
}
|
217
|
+
else:
|
218
|
+
MediLink_ConfigLoader.log("Unexpected eligibility result format: {}".format(type(eligibility_result)), level="WARNING")
|
219
|
+
return None
|
220
|
+
except Exception as e:
|
221
|
+
MediLink_ConfigLoader.log("Error normalizing post-API data: {}".format(e), level="WARNING")
|
222
|
+
return None
|
223
|
+
|
224
|
+
def _format_patient_name_from_csv(row):
|
225
|
+
"""Format patient name as LAST, FIRST from CSV data"""
|
226
|
+
try:
|
227
|
+
# Check if Patient Name is already constructed
|
228
|
+
if 'Patient Name' in row and row['Patient Name']:
|
229
|
+
return str(row['Patient Name'])[:25] # Limit length
|
230
|
+
|
231
|
+
# Otherwise construct from parts
|
232
|
+
first_name = row.get('Patient First', '').strip()
|
233
|
+
last_name = row.get('Patient Last', '').strip()
|
234
|
+
middle_name = row.get('Patient Middle', '').strip()
|
235
|
+
|
236
|
+
if last_name or first_name:
|
237
|
+
# Format as "LAST, FIRST MIDDLE"
|
238
|
+
name_parts = []
|
239
|
+
if last_name:
|
240
|
+
name_parts.append(last_name)
|
241
|
+
if first_name:
|
242
|
+
if name_parts:
|
243
|
+
name_parts.append(", {}".format(first_name))
|
244
|
+
else:
|
245
|
+
name_parts.append(first_name)
|
246
|
+
if middle_name:
|
247
|
+
name_parts.append(" {}".format(middle_name[:1])) # Just first initial
|
248
|
+
|
249
|
+
return ''.join(name_parts)[:25] # Limit length
|
250
|
+
|
251
|
+
return "Unknown Patient"
|
252
|
+
except Exception:
|
253
|
+
return "Unknown Patient"
|
254
|
+
|
255
|
+
def _extract_service_date_from_csv(row):
|
256
|
+
"""Extract and format service date from CSV data"""
|
257
|
+
try:
|
258
|
+
# Try Surgery Date first
|
259
|
+
surgery_date = row.get('Surgery Date')
|
260
|
+
if surgery_date:
|
261
|
+
if isinstance(surgery_date, datetime):
|
262
|
+
if surgery_date != datetime.min:
|
263
|
+
return surgery_date.strftime('%m-%d'), surgery_date
|
264
|
+
elif isinstance(surgery_date, str) and surgery_date.strip() and surgery_date != 'MISSING':
|
265
|
+
try:
|
266
|
+
# Try to parse common date formats
|
267
|
+
for fmt in ['%m-%d-%Y', '%m/%d/%Y', '%Y-%m-%d']:
|
268
|
+
try:
|
269
|
+
parsed_date = datetime.strptime(surgery_date.strip(), fmt)
|
270
|
+
return parsed_date.strftime('%m-%d'), parsed_date
|
271
|
+
except ValueError:
|
272
|
+
continue
|
273
|
+
except Exception:
|
274
|
+
pass
|
275
|
+
|
276
|
+
# Try other possible date fields
|
277
|
+
for date_field in ['Date of Service', 'Service Date', 'DOS']:
|
278
|
+
date_value = row.get(date_field)
|
279
|
+
if date_value and isinstance(date_value, str) and date_value.strip():
|
280
|
+
try:
|
281
|
+
for fmt in ['%m-%d-%Y', '%m/%d/%Y', '%Y-%m-%d']:
|
282
|
+
try:
|
283
|
+
parsed_date = datetime.strptime(date_value.strip(), fmt)
|
284
|
+
return parsed_date.strftime('%m-%d'), parsed_date
|
285
|
+
except ValueError:
|
286
|
+
continue
|
287
|
+
except Exception:
|
288
|
+
pass
|
289
|
+
|
290
|
+
# Default to unknown
|
291
|
+
return "Unknown", datetime.min
|
292
|
+
except Exception:
|
293
|
+
return "Unknown", datetime.min
|
294
|
+
|
295
|
+
def _group_by_patient(normalized_data):
|
296
|
+
"""Group normalized data by patient ID"""
|
297
|
+
grouped = {}
|
298
|
+
for record in normalized_data:
|
299
|
+
patient_id = record.get('patient_id', 'Unknown')
|
300
|
+
if patient_id not in grouped:
|
301
|
+
grouped[patient_id] = []
|
302
|
+
grouped[patient_id].append(record)
|
303
|
+
return grouped
|
304
|
+
|
305
|
+
def _calculate_column_widths(normalized_data, context):
|
306
|
+
"""Calculate optimal column widths based on data"""
|
307
|
+
widths = {
|
308
|
+
'patient_id': max(10, max(len(str(r.get('patient_id', ''))) for r in normalized_data) if normalized_data else 10),
|
309
|
+
'patient_name': max(20, max(len(str(r.get('patient_name', ''))) for r in normalized_data) if normalized_data else 20),
|
310
|
+
'dob': 10,
|
311
|
+
'member_id': max(12, max(len(str(r.get('member_id', ''))) for r in normalized_data) if normalized_data else 12),
|
312
|
+
'payer_id': 8,
|
313
|
+
'service_date': 10,
|
314
|
+
'status': 8
|
315
|
+
}
|
316
|
+
|
317
|
+
if context == "post_api":
|
318
|
+
widths.update({
|
319
|
+
'insurance_type': max(15, max(len(str(r.get('insurance_type', ''))) for r in normalized_data) if normalized_data else 15),
|
320
|
+
'policy_status': 12,
|
321
|
+
'remaining_amount': 12,
|
322
|
+
'data_source': 10
|
323
|
+
})
|
324
|
+
|
325
|
+
return widths
|
326
|
+
|
327
|
+
def _display_table_header(col_widths, context):
|
328
|
+
"""Display table header based on context"""
|
329
|
+
if context == "pre_api":
|
330
|
+
header_format = "No. {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}}"
|
331
|
+
header = header_format.format(
|
332
|
+
"Patient ID", col_widths['patient_id'],
|
333
|
+
"Patient Name", col_widths['patient_name'],
|
334
|
+
"DOB", col_widths['dob'],
|
335
|
+
"Member ID", col_widths['member_id'],
|
336
|
+
"Payer ID", col_widths['payer_id'],
|
337
|
+
"Service Date", col_widths['service_date'],
|
338
|
+
"Status", col_widths['status']
|
339
|
+
)
|
340
|
+
print(header)
|
341
|
+
print("-" * len(header))
|
342
|
+
else:
|
343
|
+
header_format = "No. {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}}"
|
344
|
+
header = header_format.format(
|
345
|
+
"Patient ID", col_widths['patient_id'],
|
346
|
+
"Patient Name", col_widths['patient_name'],
|
347
|
+
"DOB", col_widths['dob'],
|
348
|
+
"Member ID", col_widths['member_id'],
|
349
|
+
"Payer ID", col_widths['payer_id'],
|
350
|
+
"Service Date", col_widths['service_date'],
|
351
|
+
"Insurance Type", col_widths['insurance_type'],
|
352
|
+
"Policy Status", col_widths['policy_status'],
|
353
|
+
"Remaining Amt", col_widths['remaining_amount']
|
354
|
+
)
|
355
|
+
header_format += " | {:<{}}"
|
356
|
+
header += " | {}".format("Data Source", col_widths.get('data_source', 10))
|
357
|
+
print(header)
|
358
|
+
print("-" * len(header))
|
359
|
+
|
360
|
+
def _display_primary_line(record, line_number, col_widths, context):
|
361
|
+
"""Display primary line with line number"""
|
362
|
+
if context == "pre_api":
|
363
|
+
# Enhanced status display for pre-API context
|
364
|
+
status = record.get('status', '')
|
365
|
+
if status == 'Ready':
|
366
|
+
status_display = '[READY]'
|
367
|
+
else:
|
368
|
+
status_display = '[{}]'.format(status.upper())
|
369
|
+
|
370
|
+
line_format = "{:03d}: {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}}"
|
371
|
+
print(line_format.format(
|
372
|
+
line_number,
|
373
|
+
str(record.get('patient_id', ''))[:col_widths['patient_id']], col_widths['patient_id'],
|
374
|
+
str(record.get('patient_name', ''))[:col_widths['patient_name']], col_widths['patient_name'],
|
375
|
+
str(record.get('dob', ''))[:col_widths['dob']], col_widths['dob'],
|
376
|
+
str(record.get('member_id', ''))[:col_widths['member_id']], col_widths['member_id'],
|
377
|
+
str(record.get('payer_id', ''))[:col_widths['payer_id']], col_widths['payer_id'],
|
378
|
+
str(record.get('service_date_display', ''))[:col_widths['service_date']], col_widths['service_date'],
|
379
|
+
status_display[:col_widths['status']], col_widths['status']
|
380
|
+
))
|
381
|
+
else:
|
382
|
+
# Enhanced status display for post-API context
|
383
|
+
status = record.get('status', '')
|
384
|
+
if status == 'Processed':
|
385
|
+
status_display = '[DONE]'
|
386
|
+
elif status == 'Error':
|
387
|
+
status_display = '[ERROR]'
|
388
|
+
else:
|
389
|
+
status_display = '[{}]'.format(status.upper())
|
390
|
+
|
391
|
+
line_format = "{:03d}: {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}}"
|
392
|
+
print(line_format.format(
|
393
|
+
line_number,
|
394
|
+
str(record.get('patient_id', ''))[:col_widths['patient_id']], col_widths['patient_id'],
|
395
|
+
str(record.get('patient_name', ''))[:col_widths['patient_name']], col_widths['patient_name'],
|
396
|
+
str(record.get('dob', ''))[:col_widths['dob']], col_widths['dob'],
|
397
|
+
str(record.get('member_id', ''))[:col_widths['member_id']], col_widths['member_id'],
|
398
|
+
str(record.get('payer_id', ''))[:col_widths['payer_id']], col_widths['payer_id'],
|
399
|
+
str(record.get('service_date_display', ''))[:col_widths['service_date']], col_widths['service_date'],
|
400
|
+
str(record.get('insurance_type', ''))[:col_widths['insurance_type']], col_widths['insurance_type'],
|
401
|
+
str(record.get('policy_status', ''))[:col_widths['policy_status']], col_widths['policy_status'],
|
402
|
+
str(record.get('remaining_amount', ''))[:col_widths['remaining_amount']], col_widths['remaining_amount'],
|
403
|
+
str(record.get('data_source', ''))[:col_widths['data_source']], col_widths['data_source']
|
404
|
+
))
|
405
|
+
|
406
|
+
def _display_secondary_line(record, col_widths, context):
|
407
|
+
"""Display secondary line with dashes for grouped data"""
|
408
|
+
patient_id_dashes = '-' * min(len(str(record.get('patient_id', ''))), col_widths['patient_id'])
|
409
|
+
patient_name_dashes = '-' * min(len(str(record.get('patient_name', ''))), col_widths['patient_name'])
|
410
|
+
dob_dashes = '-' * min(len(str(record.get('dob', ''))), col_widths['dob'])
|
411
|
+
member_id_dashes = '-' * min(len(str(record.get('member_id', ''))), col_widths['member_id'])
|
412
|
+
payer_id_dashes = '-' * min(len(str(record.get('payer_id', ''))), col_widths['payer_id'])
|
413
|
+
|
414
|
+
if context == "pre_api":
|
415
|
+
# Enhanced status display for pre-API context
|
416
|
+
status = record.get('status', '')
|
417
|
+
if status == 'Ready':
|
418
|
+
status_display = '[READY]'
|
419
|
+
else:
|
420
|
+
status_display = '[{}]'.format(status.upper())
|
421
|
+
|
422
|
+
line_format = " {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}}"
|
423
|
+
print(line_format.format(
|
424
|
+
patient_id_dashes, col_widths['patient_id'],
|
425
|
+
patient_name_dashes, col_widths['patient_name'],
|
426
|
+
dob_dashes, col_widths['dob'],
|
427
|
+
member_id_dashes, col_widths['member_id'],
|
428
|
+
payer_id_dashes, col_widths['payer_id'],
|
429
|
+
str(record.get('service_date_display', ''))[:col_widths['service_date']], col_widths['service_date'],
|
430
|
+
status_display[:col_widths['status']], col_widths['status']
|
431
|
+
))
|
432
|
+
else:
|
433
|
+
insurance_type_dashes = '-' * min(len(str(record.get('insurance_type', ''))), col_widths['insurance_type'])
|
434
|
+
policy_status_dashes = '-' * min(len(str(record.get('policy_status', ''))), col_widths['policy_status'])
|
435
|
+
|
436
|
+
# Enhanced status display for post-API context
|
437
|
+
status = record.get('status', '')
|
438
|
+
if status == 'Processed':
|
439
|
+
status_display = '[DONE]'
|
440
|
+
elif status == 'Error':
|
441
|
+
status_display = '[ERROR]'
|
442
|
+
else:
|
443
|
+
status_display = '[{}]'.format(status.upper())
|
444
|
+
|
445
|
+
line_format = " {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}} | {:<{}}"
|
446
|
+
print(line_format.format(
|
447
|
+
patient_id_dashes, col_widths['patient_id'],
|
448
|
+
patient_name_dashes, col_widths['patient_name'],
|
449
|
+
dob_dashes, col_widths['dob'],
|
450
|
+
member_id_dashes, col_widths['member_id'],
|
451
|
+
payer_id_dashes, col_widths['payer_id'],
|
452
|
+
str(record.get('service_date_display', ''))[:col_widths['service_date']], col_widths['service_date'],
|
453
|
+
insurance_type_dashes, col_widths['insurance_type'],
|
454
|
+
policy_status_dashes, col_widths['policy_status'],
|
455
|
+
str(record.get('remaining_amount', ''))[:col_widths['remaining_amount']], col_widths['remaining_amount'],
|
456
|
+
str(record.get('data_source', ''))[:col_widths['data_source']], col_widths['data_source']
|
457
|
+
))
|
MediLink/MediLink_UI.py
CHANGED
@@ -201,8 +201,26 @@ def select_and_adjust_files(detailed_patient_data, config, crosswalk):
|
|
201
201
|
)
|
202
202
|
if updated_crosswalk:
|
203
203
|
crosswalk = updated_crosswalk
|
204
|
-
#
|
205
|
-
#
|
204
|
+
# STRATEGIC NOTE (Medicare Crossover UI): High-risk implementation requiring strategic decisions
|
205
|
+
#
|
206
|
+
# CRITICAL QUESTIONS FOR IMPLEMENTATION:
|
207
|
+
# 1. **Crossover Detection**: How to detect Medicare crossover failures?
|
208
|
+
# - Automatic from claim status API responses?
|
209
|
+
# - Manual user indication?
|
210
|
+
# - Time-based detection (no crossover after X days)?
|
211
|
+
#
|
212
|
+
# 2. **Secondary Claim Workflow**: How should secondary claim creation be integrated?
|
213
|
+
# - Automatic prompt when crossover failure detected?
|
214
|
+
# - Manual option in patient management interface?
|
215
|
+
# - Batch processing for multiple failed crossovers?
|
216
|
+
#
|
217
|
+
# 3. **Data Requirements**: What data is needed for secondary claims?
|
218
|
+
# - Medicare payment amount (required vs optional)?
|
219
|
+
# - Denial/adjustment reasons from Medicare?
|
220
|
+
# - Secondary payer eligibility verification?
|
221
|
+
#
|
222
|
+
# To implement: Add crossover failure detection and secondary claim creation UI
|
223
|
+
# with proper validation and error handling for Medicare -> Secondary workflow
|
206
224
|
else:
|
207
225
|
print("Invalid selection. Keeping the current endpoint.")
|
208
226
|
data['confirmed_endpoint'] = current_effective_endpoint
|
MediLink/__init__.py
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
MediBot/MediBot.bat,sha256=dWBZ2__t1uPvEuN76ETOD_mDo7368rP3tDrJd4MHCFY,26306
|
2
|
-
MediBot/MediBot.py,sha256=
|
2
|
+
MediBot/MediBot.py,sha256=9kpNZdNg3awxj0Oa5AszSZrcmyqhPZ0FHeYRHOeumBw,48750
|
3
3
|
MediBot/MediBot_Charges.py,sha256=a28if_f_IoazIHiqlaFosFnfEgEoCwb9LQ6aOyk5-D0,10704
|
4
|
-
MediBot/MediBot_Crosswalk_Library.py,sha256=
|
5
|
-
MediBot/MediBot_Crosswalk_Utils.py,sha256=
|
4
|
+
MediBot/MediBot_Crosswalk_Library.py,sha256=6LrpRx2UKVeH3TspS9LpR93iw5M7nTqN6IYpC-6PPGE,26060
|
5
|
+
MediBot/MediBot_Crosswalk_Utils.py,sha256=dFJRB_8q0iiAxZ2GY-2HsMl5Z7FvkXezzwx6LZoAglI,39589
|
6
6
|
MediBot/MediBot_Notepad_Utils.py,sha256=fOsjyfoSpgmQyc8TcnLm53faLMOUUL18cspo5PZqJK4,8719
|
7
7
|
MediBot/MediBot_Post.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
MediBot/MediBot_Preprocessor.py,sha256=gQRVAWbRHx_PMK6a7q93tp7Z-Dhjn5r0lJz3d0wAzeU,19067
|
9
|
-
MediBot/MediBot_Preprocessor_lib.py,sha256=
|
9
|
+
MediBot/MediBot_Preprocessor_lib.py,sha256=ELG0x8DSbByGbnoLOgiztzkYRBekiPb0BmxGw3cic1c,89210
|
10
10
|
MediBot/MediBot_UI.py,sha256=tQISM2gULmQVc4JbeVsn4pjgOYsQZiJpx1_IU407rO8,25870
|
11
11
|
MediBot/MediBot_dataformat_library.py,sha256=D46fdPtxcgfWTzaLBtSvjtozzZBNqNiODgu4vKMZrBg,10746
|
12
12
|
MediBot/MediBot_debug.bat,sha256=F5Lfi3nFEEo4Ddx9EbX94u3fNAMgzMp3wsn-ULyASTM,6017
|
13
|
-
MediBot/MediBot_docx_decoder.py,sha256=
|
13
|
+
MediBot/MediBot_docx_decoder.py,sha256=9BSjV-kB90VHnqfL_5iX4zl5u0HcHvHuL7YNfx3gXpQ,33143
|
14
14
|
MediBot/MediBot_smart_import.py,sha256=Emvz7NwemHGCHvG5kZcUyXMcCheidbGKaPfOTg-YCEs,6684
|
15
|
-
MediBot/__init__.py,sha256=
|
15
|
+
MediBot/__init__.py,sha256=S5Y80QAjAxFKJn6Uz9KNzNHXEHjCU0boj0joB8JcPlc,3192
|
16
16
|
MediBot/clear_cache.bat,sha256=F6-VhETWw6xDdGWG2wUqvtXjCl3lY4sSUFqF90bM8-8,1860
|
17
17
|
MediBot/crash_diagnostic.bat,sha256=j8kUtyBg6NOWbXpeFuEqIRHOkVzgUrLOqO3FBMfNxTo,9268
|
18
18
|
MediBot/f_drive_diagnostic.bat,sha256=4572hZaiwZ5wVAarPcZJQxkOSTwAdDuT_X914noARak,6878
|
@@ -21,14 +21,14 @@ MediBot/get_medicafe_version.py,sha256=uyL_UIE42MyFuJ3SRYxJp8sZx8xjTqlYZ3FdQuxLd
|
|
21
21
|
MediBot/process_csvs.bat,sha256=3tI7h1z9eRj8rUUL4wJ7dy-Qrak20lRmpAPtGbUMbVQ,3489
|
22
22
|
MediBot/update_json.py,sha256=vvUF4mKCuaVly8MmoadDO59M231fCIInc0KI1EtDtPA,3704
|
23
23
|
MediBot/update_medicafe.py,sha256=G1lyvVOHYuho1d-TJQNN6qaB4HBWaJ2PpXqemBoPlRQ,17937
|
24
|
-
MediCafe/MediLink_ConfigLoader.py,sha256=
|
25
|
-
MediCafe/__init__.py,sha256=
|
24
|
+
MediCafe/MediLink_ConfigLoader.py,sha256=zzI3cFe2_TdwgIW_UAVmY_LFFlLLdlmpCokouUqx6u0,10898
|
25
|
+
MediCafe/__init__.py,sha256=U8Vg_cQIvjHI-ynz8513QPOIAUsTvWRlj0aYnbvSAWQ,5721
|
26
26
|
MediCafe/__main__.py,sha256=mRNyk3D9Ilnu2XhgVI_rut7r5Ro7UIKtwV871giAHI8,12992
|
27
|
-
MediCafe/api_core.py,sha256=
|
28
|
-
MediCafe/api_core_backup.py,sha256=Oy_Fqt0SEvGkQN1Oqw5iUPVFxPEokyju5CuPEb9k0OY,18686
|
27
|
+
MediCafe/api_core.py,sha256=yNFfLO70bF91NNBLSUADYWZFkR5yh8NctxnT98fkAxk,78515
|
29
28
|
MediCafe/api_factory.py,sha256=I5AeJoyu6m7oCrjc2OvVvO_4KSBRutTsR1riiWhTZV0,12086
|
30
29
|
MediCafe/api_utils.py,sha256=KWQB0q1k5E6frOFFlKWcFpHNcqfrS7KJ_82672wbupw,14041
|
31
|
-
MediCafe/core_utils.py,sha256=
|
30
|
+
MediCafe/core_utils.py,sha256=XKUpyv7yKjIQ8iNrhD76PIURyt6GZxb98v0daiI7aaw,27303
|
31
|
+
MediCafe/deductible_utils.py,sha256=bsI5YRO8QzaEU-sxi2F5zIx6k4D53rYUt0mlg-6-Jc8,57644
|
32
32
|
MediCafe/graphql_utils.py,sha256=xrREl0mqktEBkV6SZeAImuuDc8Sp2Q80rWxKIh-zD7Q,44499
|
33
33
|
MediCafe/logging_config.py,sha256=auT65LN5oDEXVhkMeLke63kJHTWxYf2o8YihAfQFgzU,5493
|
34
34
|
MediCafe/logging_demo.py,sha256=TwUhzafna5pMdN3zSKGrpUWRqX96F1JGGsSUtr3dygs,1975
|
@@ -38,7 +38,7 @@ MediCafe/submission_index.py,sha256=35gz8Anx1dIqG1I14GvuLY0nTO4dSBr2YsZwof9aIQg,
|
|
38
38
|
MediLink/InsuranceTypeService.py,sha256=FKWC1nRfKV_OtCDUtZustauXNhmCYDFiY9jsAGHPPUM,2178
|
39
39
|
MediLink/MediLink_837p_cob_library.py,sha256=glc7SJBDx0taCGmwmCs81GFJJcvA_D7nycIkTfmIuwE,30650
|
40
40
|
MediLink/MediLink_837p_encoder.py,sha256=lJnly96LsSBnzEgF8Ne-nQTL7cmRhoFL2fJajtpvOcU,32209
|
41
|
-
MediLink/MediLink_837p_encoder_library.py,sha256=
|
41
|
+
MediLink/MediLink_837p_encoder_library.py,sha256=E0jCyiyANZLpmWUW0GKT3-04FnX9yTBLnz7RukaGs5Q,91892
|
42
42
|
MediLink/MediLink_837p_utilities.py,sha256=AJ0F22LoF8du20zPBH4TZXgsdXCD-1qYKBnHJM-mXl0,16260
|
43
43
|
MediLink/MediLink_API_Generator.py,sha256=VZBL9W8yFTMJ4ikSwbUI8ANtaJCLnUyqoF8xQEJQn_E,11176
|
44
44
|
MediLink/MediLink_Azure.py,sha256=Ow70jctiHFIylskBExN7WUoRgrKOvBR6jNTnQMk6lJA,210
|
@@ -46,9 +46,9 @@ MediLink/MediLink_Charges.py,sha256=82fnqHGvT7tfdfjucnFHiLdUE0WhHDXrcS0k_Ln3c8U,
|
|
46
46
|
MediLink/MediLink_ClaimStatus.py,sha256=75LzWfYaxrLWelId-8rHHN_lchHXxAe34pRgvKPdP2o,22118
|
47
47
|
MediLink/MediLink_DataMgmt.py,sha256=9hc5jyWU65nYT66afDybOyYAcW-DvEYuHpWTun96U50,52407
|
48
48
|
MediLink/MediLink_Decoder.py,sha256=1gzdybNg4Vv69s5PNbX8bPNrXT_N_kPpFpt2HpkauWA,16430
|
49
|
-
MediLink/MediLink_Deductible.py,sha256=
|
50
|
-
MediLink/MediLink_Deductible_Validator.py,sha256=
|
51
|
-
MediLink/MediLink_Display_Utils.py,sha256=
|
49
|
+
MediLink/MediLink_Deductible.py,sha256=e_Oi5c55g4fTcPf-2hLnIRJ_Q_pBAyyXnTKiciQULd8,55208
|
50
|
+
MediLink/MediLink_Deductible_Validator.py,sha256=1h5GJ9jbcVarxd6a-lKPEOhJYz4QkeeBlHw0Zdd9vUU,24855
|
51
|
+
MediLink/MediLink_Display_Utils.py,sha256=a0t1VU9Mm_vhsXVTEA1EpUlElrnyie4XaCeif7GwRgw,21213
|
52
52
|
MediLink/MediLink_Down.py,sha256=s4_z-RaqHYanjwbQCl-OSkg4XIpcIQ2Q6jXa8-q_QXw,28111
|
53
53
|
MediLink/MediLink_Gmail.py,sha256=8iQjqcJMSa_Zfr5azR0dShKAQeXqt-9C-s8seYB9pic,23961
|
54
54
|
MediLink/MediLink_Mailer.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -56,25 +56,21 @@ MediLink/MediLink_Parser.py,sha256=eRVZ4ckZ5gDOrcvtCUZP3DOd3Djly66rCIk0aYXLz14,1
|
|
56
56
|
MediLink/MediLink_PatientProcessor.py,sha256=9r2w4p45d30Tn0kbXL3j5574MYOehP83tDirNOw_Aek,19977
|
57
57
|
MediLink/MediLink_Scan.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
58
58
|
MediLink/MediLink_Scheduler.py,sha256=UJvxhDvHraqra2_TlQVlGeh5jRFrrfK6nCVUHnKOEMY,38
|
59
|
-
MediLink/MediLink_UI.py,sha256=
|
59
|
+
MediLink/MediLink_UI.py,sha256=ZEJ14EGh7pDu1XjAdORDFiay4UtTsLNWwNSJ0prHFWg,10381
|
60
60
|
MediLink/MediLink_Up.py,sha256=uB6J63hWOn8Ot8iGtc2_OgcejNWVgnX7Se_e_UWBNho,38082
|
61
61
|
MediLink/MediLink_insurance_utils.py,sha256=g741Fj2K26cMy0JX5d_XavMw9LgkK6hjaUJYfysT7t8,9301
|
62
62
|
MediLink/MediLink_main.py,sha256=ZVK2UsgSxC9UqgIYfgVu95ugULcH6-11l67jsf4vdJc,22132
|
63
63
|
MediLink/MediLink_smart_import.py,sha256=B5SfBn_4bYEWJJDolXbjnwKx_-MaqGZ76LyXQwWDV80,9838
|
64
64
|
MediLink/Soumit_api.py,sha256=5JfOecK98ZC6NpZklZW2AkOzkjvrbYxpJpZNH3rFxDw,497
|
65
|
-
MediLink/__init__.py,sha256=
|
65
|
+
MediLink/__init__.py,sha256=Lr3cT-xyO8eyyoxqaKxcjR2CHxNL340JEdIHe_l1rd4,3888
|
66
66
|
MediLink/gmail_http_utils.py,sha256=gtqCCrzJC7e8JFQzMNrf7EbK8na2h4sfTu-NMaZ_UHc,4006
|
67
67
|
MediLink/gmail_oauth_utils.py,sha256=Ugr-DEqs4_RddRMSCJ_dbgA3TVeaxpbAor-dktcTIgY,3713
|
68
|
-
MediLink/insurance_type_integration_test.py,sha256=pz2OCXitAznqDciYn6OL9M326m9CYU7YiK-ynssdQ5g,15172
|
69
68
|
MediLink/openssl.cnf,sha256=76VdcGCykf0Typyiv8Wd1mMVKixrQ5RraG6HnfKFqTo,887
|
70
69
|
MediLink/test.py,sha256=DM_E8gEbhbVfTAm3wTMiNnK2GCD1e5eH6gwTk89QIc4,3116
|
71
|
-
MediLink/test_cob_library.py,sha256=wUMv0-Y6fNsKcAs8Z9LwfmEBRO7oBzBAfWmmzwoNd1g,13841
|
72
|
-
MediLink/test_timing.py,sha256=yH2b8QPLDlp1Zy5AhgtjzjnDHNGhAD16ZtXtZzzESZw,2042
|
73
|
-
MediLink/test_validation.py,sha256=FJrfdUFK--xRScIzrHCg1JeGdm0uJEoRnq6CgkP2lwM,4154
|
74
70
|
MediLink/webapp.html,sha256=JPKT559aFVBi1r42Hz7C77Jj0teZZRumPhBev8eSOLk,19806
|
75
|
-
medicafe-0.
|
76
|
-
medicafe-0.
|
77
|
-
medicafe-0.
|
78
|
-
medicafe-0.
|
79
|
-
medicafe-0.
|
80
|
-
medicafe-0.
|
71
|
+
medicafe-0.250909.0.dist-info/LICENSE,sha256=65lb-vVujdQK7uMH3RRJSMwUW-WMrMEsc5sOaUn2xUk,1096
|
72
|
+
medicafe-0.250909.0.dist-info/METADATA,sha256=cWgYebKSTCUb2V3c-2TnjmCtUiG0lX8KxVY8g6OlY1g,3414
|
73
|
+
medicafe-0.250909.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
74
|
+
medicafe-0.250909.0.dist-info/entry_points.txt,sha256=m3RBUBjr-xRwEkKJ5W4a7NlqHZP_1rllGtjZnrRqKe8,52
|
75
|
+
medicafe-0.250909.0.dist-info/top_level.txt,sha256=U6-WBJ9RCEjyIs0BlzbQq_PwedCp_IV9n1616NNV5zA,26
|
76
|
+
medicafe-0.250909.0.dist-info/RECORD,,
|