medicafe 0.250728.9__py3-none-any.whl → 0.250805.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.

Potentially problematic release.


This version of medicafe might be problematic. Click here for more details.

Files changed (57) hide show
  1. MediBot/MediBot.bat +233 -19
  2. MediBot/MediBot.py +138 -46
  3. MediBot/MediBot_Crosswalk_Library.py +127 -623
  4. MediBot/MediBot_Crosswalk_Utils.py +618 -0
  5. MediBot/MediBot_Preprocessor.py +72 -17
  6. MediBot/MediBot_Preprocessor_lib.py +470 -76
  7. MediBot/MediBot_UI.py +32 -17
  8. MediBot/MediBot_dataformat_library.py +68 -20
  9. MediBot/MediBot_docx_decoder.py +120 -19
  10. MediBot/MediBot_smart_import.py +180 -0
  11. MediBot/__init__.py +89 -0
  12. MediBot/get_medicafe_version.py +25 -0
  13. MediBot/update_json.py +35 -6
  14. MediBot/update_medicafe.py +19 -1
  15. MediCafe/MediLink_ConfigLoader.py +160 -0
  16. MediCafe/__init__.py +171 -0
  17. MediCafe/__main__.py +222 -0
  18. MediCafe/api_core.py +1098 -0
  19. MediCafe/api_core_backup.py +427 -0
  20. MediCafe/api_factory.py +306 -0
  21. MediCafe/api_utils.py +356 -0
  22. MediCafe/core_utils.py +450 -0
  23. MediCafe/graphql_utils.py +445 -0
  24. MediCafe/logging_config.py +123 -0
  25. MediCafe/logging_demo.py +61 -0
  26. MediCafe/migration_helpers.py +463 -0
  27. MediCafe/smart_import.py +436 -0
  28. MediLink/MediLink_837p_cob_library.py +28 -28
  29. MediLink/MediLink_837p_encoder.py +33 -34
  30. MediLink/MediLink_837p_encoder_library.py +226 -150
  31. MediLink/MediLink_837p_utilities.py +129 -5
  32. MediLink/MediLink_API_Generator.py +83 -60
  33. MediLink/MediLink_API_v3.py +1 -1
  34. MediLink/MediLink_ClaimStatus.py +177 -31
  35. MediLink/MediLink_DataMgmt.py +378 -63
  36. MediLink/MediLink_Decoder.py +20 -1
  37. MediLink/MediLink_Deductible.py +155 -28
  38. MediLink/MediLink_Display_Utils.py +72 -0
  39. MediLink/MediLink_Down.py +127 -5
  40. MediLink/MediLink_Gmail.py +712 -653
  41. MediLink/MediLink_PatientProcessor.py +257 -0
  42. MediLink/MediLink_UI.py +85 -71
  43. MediLink/MediLink_Up.py +28 -4
  44. MediLink/MediLink_insurance_utils.py +227 -230
  45. MediLink/MediLink_main.py +248 -0
  46. MediLink/MediLink_smart_import.py +264 -0
  47. MediLink/__init__.py +93 -1
  48. MediLink/insurance_type_integration_test.py +13 -3
  49. MediLink/test.py +1 -1
  50. MediLink/test_timing.py +59 -0
  51. {medicafe-0.250728.9.dist-info → medicafe-0.250805.0.dist-info}/METADATA +1 -1
  52. medicafe-0.250805.0.dist-info/RECORD +81 -0
  53. medicafe-0.250805.0.dist-info/entry_points.txt +2 -0
  54. {medicafe-0.250728.9.dist-info → medicafe-0.250805.0.dist-info}/top_level.txt +1 -0
  55. medicafe-0.250728.9.dist-info/RECORD +0 -59
  56. {medicafe-0.250728.9.dist-info → medicafe-0.250805.0.dist-info}/LICENSE +0 -0
  57. {medicafe-0.250728.9.dist-info → medicafe-0.250805.0.dist-info}/WHEEL +0 -0
@@ -1,24 +1,86 @@
1
1
  # MediLink_ClaimStatus.py
2
2
  from datetime import datetime, timedelta
3
- import os
4
- import time
5
- import json
6
- import MediLink_API_v3
3
+ import os, sys
7
4
 
5
+ # Import centralized logging configuration
8
6
  try:
9
- from MediLink import MediLink_ConfigLoader
7
+ from MediCafe.logging_config import DEBUG, PERFORMANCE_LOGGING
10
8
  except ImportError:
11
- import MediLink_ConfigLoader
9
+ # Fallback to local flags if centralized config is not available
10
+ DEBUG = False
11
+ PERFORMANCE_LOGGING = False
12
12
 
13
- # Load configuration
14
- config, _ = MediLink_ConfigLoader.load_configuration()
13
+ # Set up project paths first
14
+ project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
15
+ if project_dir not in sys.path:
16
+ sys.path.insert(0, project_dir)
17
+
18
+ # Use core utilities for standardized imports
19
+ try:
20
+ from MediCafe.core_utils import get_shared_config_loader, get_api_client, create_config_cache
21
+ MediLink_ConfigLoader = get_shared_config_loader()
22
+ except ImportError:
23
+ print("Error: Unable to import MediCafe.core_utils. Please ensure MediCafe package is properly installed.")
24
+ sys.exit(1)
25
+
26
+ # Import api_core for claim operations
27
+ try:
28
+ from MediCafe import api_core
29
+ except ImportError:
30
+ api_core = None
31
+
32
+ # Calculate start_date and end_date for the API:
33
+ # Official API documentation requires last date less than 31 days from the First Date
34
+ # Use a conservative 30-day range to stay within the 31-day limit
35
+ current_date = datetime.today()
36
+ end_date = current_date - timedelta(days=1) # Yesterday (avoid future dates)
37
+ start_date = end_date - timedelta(days=29) # 29 days before end date (30-day range total)
38
+
39
+ # Validate date range according to official API documentation
40
+ def validate_date_range(start_date, end_date):
41
+ """Validate date range according to official API documentation"""
42
+ current_date = datetime.today()
43
+
44
+ if end_date > current_date:
45
+ raise ValueError("End date cannot be in the future")
46
+
47
+ date_diff = (end_date - start_date).days
48
+ if date_diff > 30: # Official docs say "less than 31 days"
49
+ raise ValueError("Date range must not exceed 30 days (official API limit)")
50
+
51
+ if date_diff < 0:
52
+ raise ValueError("Start date must be before end date")
53
+
54
+ # Check if dates are within reasonable range (last 24 months as per swagger)
55
+ max_start_date = current_date - timedelta(days=730) # 24 months
56
+ if start_date < max_start_date:
57
+ raise ValueError("Start date must be within last 24 months")
58
+
59
+ # Validate the calculated date range
60
+ try:
61
+ validate_date_range(start_date, end_date)
62
+ except ValueError as e:
63
+ print("Date validation error: {}".format(e))
64
+ # Fallback to a safe date range within 30 days
65
+ end_date = current_date - timedelta(days=1)
66
+ start_date = end_date - timedelta(days=15) # 15-day range as fallback
15
67
 
16
- # Calculate start_date as 60 days before today's date and end_date as today's date
17
- end_date = datetime.today()
18
- start_date = end_date - timedelta(days=60)
19
68
  end_date_str = end_date.strftime('%m/%d/%Y')
20
69
  start_date_str = start_date.strftime('%m/%d/%Y')
21
70
 
71
+ # Inline commentary: The official API documentation requires last date less than 31 days
72
+ # from the First Date, so we use a 30-day range to stay within this limit.
73
+ if DEBUG:
74
+ print("Using date range for API compliance (30-day range, up to yesterday)")
75
+ print(" Start Date: {}".format(start_date_str))
76
+ print(" End Date: {}".format(end_date_str))
77
+
78
+ # Use latest core_utils configuration cache for better performance
79
+ _get_config, (_config_cache, _crosswalk_cache) = create_config_cache()
80
+
81
+ # Load configuration using latest core_utils pattern
82
+ config, _ = _get_config()
83
+
22
84
  # Get billing provider TIN from configuration
23
85
  billing_provider_tin = config['MediLink_Config'].get('billing_provider_tin')
24
86
 
@@ -26,8 +88,18 @@ billing_provider_tin = config['MediLink_Config'].get('billing_provider_tin')
26
88
  payer_ids = ['87726', '03432', '96385', '95467', '86050', '86047', '95378', '37602']
27
89
  # Allowed payer id's for UHC 87726, 03432, 96385, 95467, 86050, 86047, 95378, 37602. This api does not support payerId 06111.
28
90
 
29
- # Initialize the API client
30
- client = MediLink_API_v3.APIClient()
91
+ # Initialize the API client via factory
92
+ client = get_api_client()
93
+ if client is None:
94
+ if DEBUG:
95
+ print("Warning: API client not available via factory")
96
+ # Fallback to direct instantiation
97
+ try:
98
+ from MediCafe import api_core
99
+ client = api_core.APIClient()
100
+ except ImportError:
101
+ print("Error: Unable to create API client")
102
+ client = None
31
103
 
32
104
  class ClaimCache:
33
105
  """In-memory cache for API responses"""
@@ -132,32 +204,89 @@ def extract_claim_data(claim):
132
204
  'claim_xwalk_data': claim['claimSummary']['clmXWalkData']
133
205
  }
134
206
 
207
+ def handle_api_error(error, payer_id):
208
+ """Handle specific API errors according to official documentation"""
209
+ error_message = str(error)
210
+
211
+ # Handle specific error codes from official documentation
212
+ if "LCLM_PS_102" in error_message:
213
+ return "Mandatory element missing in request (tin, firstServiceDt, lastServiceDt, or payerId)"
214
+ elif "LCLM_PS_105" in error_message or "LCLM_PS_202" in error_message:
215
+ return "Authorization error: Payer ID {} not allowed".format(payer_id)
216
+ elif "LCLM_PS_106" in error_message:
217
+ return "Invalid parameter combination: must use (firstServiceDt,lastServiceDt) or (transactionId)"
218
+ elif "LCLM_PS_107" in error_message:
219
+ return "Date range must be within last 24 months"
220
+ elif "LCLM_PS_108" in error_message or "LCLM_PS_111" in error_message:
221
+ return "Incorrect date format: use MM/dd/yyyy"
222
+ elif "LCLM_PS_112" in error_message:
223
+ return "Date range exceeds 30 days limit (official API constraint)"
224
+ elif "LCLM_PS_201" in error_message:
225
+ return "No data found with given request parameters"
226
+ elif "LCLM_PS_306" in error_message:
227
+ return "Search exceeds 500 claims limit - narrow date range"
228
+ elif "LCLM_PS_500" in error_message:
229
+ return "Server error: Exception from Claims 360 - try again later"
230
+ elif "401" in error_message:
231
+ return "Authentication error: check credentials"
232
+ elif "403" in error_message:
233
+ return "Authorization error: insufficient permissions"
234
+ elif "500" in error_message:
235
+ return "Server error: internal system failure"
236
+ else:
237
+ return "Unknown error: {}".format(error_message)
238
+
135
239
  def process_claims_with_payer_rotation(billing_provider_tin, start_date_str, end_date_str,
136
240
  payer_ids, cache, consolidated_claims):
137
241
  """
138
242
  Process claims across multiple payer IDs with caching and consolidation
139
243
  """
140
- client = MediLink_API_v3.APIClient()
244
+ from MediCafe.core_utils import get_api_client
245
+ client = get_api_client()
246
+ if client is None:
247
+ if DEBUG:
248
+ print("Warning: API client not available via factory")
249
+ # Fallback to direct instantiation
250
+ try:
251
+ from MediCafe import api_core
252
+ client = api_core.APIClient()
253
+ except ImportError:
254
+ print("Error: Unable to create API client")
255
+ return
141
256
 
142
257
  for payer_id in payer_ids:
143
- print("Processing Payer ID: {}".format(payer_id))
258
+ if DEBUG:
259
+ print("Processing Payer ID: {}".format(payer_id))
144
260
 
145
261
  # Generate cache key
146
262
  cache_key = cache.get_cache_key(billing_provider_tin, start_date_str, end_date_str, payer_id)
147
263
 
148
264
  # Check cache first
149
265
  if cache.is_cached(cache_key):
150
- print(" Using cached response for Payer ID: {}".format(payer_id))
266
+ if DEBUG:
267
+ print(" Using cached response for Payer ID: {}".format(payer_id))
151
268
  claim_summary = cache.get_cached_response(cache_key)
152
269
  else:
153
- print(" Making API call for Payer ID: {}".format(payer_id))
270
+ if DEBUG:
271
+ print(" Making API call for Payer ID: {}".format(payer_id))
154
272
  try:
155
- claim_summary = MediLink_API_v3.get_claim_summary_by_provider(
156
- client, billing_provider_tin, start_date_str, end_date_str, payer_id=payer_id
273
+ # Import api_core locally to ensure it's available
274
+ from MediCafe import api_core
275
+ claim_summary = api_core.get_claim_summary_by_provider(
276
+ client, billing_provider_tin, start_date_str, end_date_str,
277
+ payer_id=payer_id
157
278
  )
158
279
  cache.cache_response(cache_key, claim_summary, payer_id)
159
280
  except Exception as e:
160
- print(" Error processing Payer ID {}: {}".format(payer_id, e))
281
+ error_msg = handle_api_error(e, payer_id)
282
+ print(" Error processing Payer ID {}: {}".format(payer_id, error_msg))
283
+
284
+ # Log the error for debugging (file only, not console)
285
+ MediLink_ConfigLoader.log(
286
+ "API Error for Payer ID {}: {}".format(payer_id, error_msg),
287
+ level="ERROR",
288
+ console_output=False
289
+ )
161
290
  continue
162
291
 
163
292
  # Process claims from this payer
@@ -219,14 +348,16 @@ def display_consolidated_claims(consolidated_claims, output_file):
219
348
  clm508Cd = xwalk['clm508Cd']
220
349
  clm508CdDesc = xwalk['clm508CdDesc']
221
350
  clmIcnSufxCd = xwalk['clmIcnSufxCd']
222
- print(" 507: {} ({}) | 508: {} ({}) | ICN Suffix: {}".format(
223
- clm507Cd, clm507CdDesc, clm508Cd, clm508CdDesc, clmIcnSufxCd))
351
+ if DEBUG:
352
+ print(" 507: {} ({}) | 508: {} ({}) | ICN Suffix: {}".format(
353
+ clm507Cd, clm507CdDesc, clm508Cd, clm508CdDesc, clmIcnSufxCd))
224
354
 
225
355
  # Display duplicate warnings (terminal and log only, not file)
226
356
  if consolidated_claims.duplicate_warnings:
227
- print("\n" + "="*80)
228
- print("DUPLICATE CLAIM WARNINGS:")
229
- print("="*80)
357
+ if DEBUG:
358
+ print("\n" + "="*80)
359
+ print("DUPLICATE CLAIM WARNINGS:")
360
+ print("="*80)
230
361
 
231
362
  for warning in consolidated_claims.duplicate_warnings:
232
363
  warning_msg = (
@@ -244,12 +375,14 @@ def display_consolidated_claims(consolidated_claims, output_file):
244
375
  warning['new_data']['total_paid_amount']
245
376
  )
246
377
  )
247
- print(warning_msg)
378
+ if DEBUG:
379
+ print(warning_msg)
248
380
 
249
- # Log the warning
381
+ # Log the warning (file only, not console)
250
382
  MediLink_ConfigLoader.log(
251
383
  "Duplicate claim warning: {}".format(warning_msg),
252
- level="WARNING"
384
+ level="WARNING",
385
+ console_output=False
253
386
  )
254
387
 
255
388
  # Initialize cache and consolidated claims
@@ -262,12 +395,25 @@ process_claims_with_payer_rotation(
262
395
  )
263
396
 
264
397
  # Display consolidated results
265
- output_file_path = os.path.join(os.getenv('TEMP'), 'claim_summary_report.txt')
398
+ temp_dir = os.getenv('TEMP') or os.getenv('TMP') or '/tmp' # Cross-platform temp directory
399
+ output_file_path = os.path.join(temp_dir, 'claim_summary_report.txt')
266
400
  with open(output_file_path, 'w') as output_file:
267
401
  display_consolidated_claims(consolidated_claims, output_file)
268
402
 
269
403
  # Clear cache after consolidated table is generated
270
404
  cache.clear_cache()
271
405
 
272
- # Open the generated file in Notepad
273
- os.startfile(output_file_path) # Use os.startfile for better handling
406
+ # Open the generated file (cross-platform approach)
407
+ try:
408
+ if os.name == 'nt': # Windows
409
+ os.startfile(output_file_path)
410
+ elif os.name == 'posix': # Unix/Linux/MacOS
411
+ import subprocess
412
+ subprocess.call(['xdg-open', output_file_path])
413
+ else:
414
+ if DEBUG:
415
+ print("File saved to: {}".format(output_file_path))
416
+ except Exception as e:
417
+ if DEBUG:
418
+ print("File saved to: {}".format(output_file_path))
419
+ print("Could not open file automatically: {}".format(e))