medicafe 0.250728.9__py3-none-any.whl → 0.250805.2__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.
- MediBot/MediBot.bat +233 -19
- MediBot/MediBot.py +138 -46
- MediBot/MediBot_Crosswalk_Library.py +127 -623
- MediBot/MediBot_Crosswalk_Utils.py +618 -0
- MediBot/MediBot_Preprocessor.py +72 -17
- MediBot/MediBot_Preprocessor_lib.py +470 -76
- MediBot/MediBot_UI.py +32 -17
- MediBot/MediBot_dataformat_library.py +68 -20
- MediBot/MediBot_docx_decoder.py +120 -19
- MediBot/MediBot_smart_import.py +180 -0
- MediBot/__init__.py +89 -0
- MediBot/get_medicafe_version.py +25 -0
- MediBot/update_json.py +35 -6
- MediBot/update_medicafe.py +19 -1
- MediCafe/MediLink_ConfigLoader.py +160 -0
- MediCafe/__init__.py +171 -0
- MediCafe/__main__.py +314 -0
- MediCafe/api_core.py +1098 -0
- MediCafe/api_core_backup.py +427 -0
- MediCafe/api_factory.py +306 -0
- MediCafe/api_utils.py +356 -0
- MediCafe/core_utils.py +450 -0
- MediCafe/graphql_utils.py +445 -0
- MediCafe/logging_config.py +123 -0
- MediCafe/logging_demo.py +61 -0
- MediCafe/migration_helpers.py +463 -0
- MediCafe/smart_import.py +436 -0
- MediLink/MediLink_837p_cob_library.py +28 -28
- MediLink/MediLink_837p_encoder.py +33 -34
- MediLink/MediLink_837p_encoder_library.py +226 -150
- MediLink/MediLink_837p_utilities.py +129 -5
- MediLink/MediLink_API_Generator.py +83 -60
- MediLink/MediLink_API_v3.py +1 -1
- MediLink/MediLink_ClaimStatus.py +177 -31
- MediLink/MediLink_DataMgmt.py +378 -63
- MediLink/MediLink_Decoder.py +20 -1
- MediLink/MediLink_Deductible.py +155 -28
- MediLink/MediLink_Display_Utils.py +72 -0
- MediLink/MediLink_Down.py +127 -5
- MediLink/MediLink_Gmail.py +720 -653
- MediLink/MediLink_PatientProcessor.py +257 -0
- MediLink/MediLink_UI.py +85 -71
- MediLink/MediLink_Up.py +28 -4
- MediLink/MediLink_insurance_utils.py +227 -230
- MediLink/MediLink_main.py +248 -0
- MediLink/MediLink_smart_import.py +264 -0
- MediLink/__init__.py +93 -1
- MediLink/insurance_type_integration_test.py +13 -3
- MediLink/test.py +1 -1
- MediLink/test_timing.py +59 -0
- {medicafe-0.250728.9.dist-info → medicafe-0.250805.2.dist-info}/METADATA +1 -1
- medicafe-0.250805.2.dist-info/RECORD +81 -0
- medicafe-0.250805.2.dist-info/entry_points.txt +2 -0
- {medicafe-0.250728.9.dist-info → medicafe-0.250805.2.dist-info}/top_level.txt +1 -0
- medicafe-0.250728.9.dist-info/RECORD +0 -59
- {medicafe-0.250728.9.dist-info → medicafe-0.250805.2.dist-info}/LICENSE +0 -0
- {medicafe-0.250728.9.dist-info → medicafe-0.250805.2.dist-info}/WHEEL +0 -0
MediCafe/smart_import.py
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MediCafe Smart Import System
|
|
3
|
+
|
|
4
|
+
This module provides intelligent import management for the entire MediCafe ecosystem,
|
|
5
|
+
allowing MediBot and MediLink modules to request components without worrying about
|
|
6
|
+
circular imports or complex dependency management.
|
|
7
|
+
|
|
8
|
+
Usage Examples:
|
|
9
|
+
# Simple component requests
|
|
10
|
+
from MediCafe.smart_import import get_components
|
|
11
|
+
api_core, logging_config = get_components('api_core', 'logging_config')
|
|
12
|
+
|
|
13
|
+
# Get everything for a specific module type
|
|
14
|
+
from MediCafe.smart_import import setup_for_medibot
|
|
15
|
+
components = setup_for_medibot('preprocessor')
|
|
16
|
+
|
|
17
|
+
# Use components
|
|
18
|
+
api_core = components['api_core']
|
|
19
|
+
logging = components['logging_config']
|
|
20
|
+
|
|
21
|
+
# Get API suite for any module
|
|
22
|
+
from MediCafe.smart_import import get_api_access
|
|
23
|
+
api_suite = get_api_access()
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
import sys
|
|
27
|
+
import importlib
|
|
28
|
+
import inspect
|
|
29
|
+
# from typing import Any, Dict, List, Optional, Union, Tuple, Set # Removed for Python 3.4.4 compatibility
|
|
30
|
+
# from functools import lru_cache # Removed as not used
|
|
31
|
+
import threading
|
|
32
|
+
# from pathlib import Path # Replaced with os.path for Python 3.4.4 compatibility
|
|
33
|
+
import os
|
|
34
|
+
import warnings
|
|
35
|
+
|
|
36
|
+
# Define typing aliases for Python 3.4.4 compatibility
|
|
37
|
+
try:
|
|
38
|
+
from typing import Any, Dict, List, Optional, Union, Tuple, Set
|
|
39
|
+
except ImportError:
|
|
40
|
+
# Python 3.4.4 compatibility - define as object
|
|
41
|
+
Any = object
|
|
42
|
+
Dict = dict
|
|
43
|
+
List = list
|
|
44
|
+
Optional = object
|
|
45
|
+
Union = object
|
|
46
|
+
Tuple = tuple
|
|
47
|
+
Set = set
|
|
48
|
+
|
|
49
|
+
class ComponentRegistry:
|
|
50
|
+
"""Registry for managing all available components and their dependencies."""
|
|
51
|
+
|
|
52
|
+
def __init__(self):
|
|
53
|
+
self._components = {}
|
|
54
|
+
self._modules = {}
|
|
55
|
+
self._dependencies = {}
|
|
56
|
+
self._loading_stack = []
|
|
57
|
+
self._lock = threading.RLock()
|
|
58
|
+
self._module_configs = {}
|
|
59
|
+
self._failed_loads = set()
|
|
60
|
+
|
|
61
|
+
def register_component(self, name, component, dependencies=None):
|
|
62
|
+
"""Register a component with optional dependencies."""
|
|
63
|
+
with self._lock:
|
|
64
|
+
self._components[name] = component
|
|
65
|
+
self._dependencies[name] = dependencies or []
|
|
66
|
+
|
|
67
|
+
def register_module_config(self, module_name, config):
|
|
68
|
+
"""Register configuration for a specific module's needs."""
|
|
69
|
+
self._module_configs[module_name] = config
|
|
70
|
+
|
|
71
|
+
def get_component(self, name, silent_fail=False):
|
|
72
|
+
"""Get a component, loading it if necessary."""
|
|
73
|
+
with self._lock:
|
|
74
|
+
# Return cached component if available
|
|
75
|
+
if name in self._components:
|
|
76
|
+
return self._components[name]
|
|
77
|
+
|
|
78
|
+
# Skip if previously failed and silent_fail is True
|
|
79
|
+
if silent_fail and name in self._failed_loads:
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
# Check for circular imports
|
|
83
|
+
if name in self._loading_stack:
|
|
84
|
+
error_msg = "Circular import detected: {} -> {}".format(' -> '.join(self._loading_stack), name)
|
|
85
|
+
if silent_fail:
|
|
86
|
+
warnings.warn(error_msg)
|
|
87
|
+
return None
|
|
88
|
+
raise ImportError(error_msg)
|
|
89
|
+
|
|
90
|
+
self._loading_stack.append(name)
|
|
91
|
+
try:
|
|
92
|
+
component = self._load_component(name)
|
|
93
|
+
self._components[name] = component
|
|
94
|
+
return component
|
|
95
|
+
except ImportError as e:
|
|
96
|
+
self._failed_loads.add(name)
|
|
97
|
+
if silent_fail:
|
|
98
|
+
return None
|
|
99
|
+
raise e
|
|
100
|
+
finally:
|
|
101
|
+
if name in self._loading_stack:
|
|
102
|
+
self._loading_stack.remove(name)
|
|
103
|
+
|
|
104
|
+
def _load_component(self, name: str) -> Any:
|
|
105
|
+
"""Load a component dynamically."""
|
|
106
|
+
# Component loading mappings
|
|
107
|
+
component_mappings = {
|
|
108
|
+
# MediCafe core components
|
|
109
|
+
'api_core': 'MediCafe.api_core',
|
|
110
|
+
'api_factory': 'MediCafe.api_factory',
|
|
111
|
+
'api_utils': 'MediCafe.api_utils',
|
|
112
|
+
'core_utils': 'MediCafe.core_utils',
|
|
113
|
+
'graphql_utils': 'MediCafe.graphql_utils',
|
|
114
|
+
'logging_config': 'MediCafe.logging_config',
|
|
115
|
+
'medicafe_config_loader': 'MediCafe.MediLink_ConfigLoader',
|
|
116
|
+
|
|
117
|
+
# MediBot components
|
|
118
|
+
'medibot_main': 'MediBot.MediBot',
|
|
119
|
+
'medibot_preprocessor': 'MediBot.MediBot_Preprocessor',
|
|
120
|
+
'medibot_preprocessor_lib': 'MediBot.MediBot_Preprocessor_lib',
|
|
121
|
+
'medibot_crosswalk_library': 'MediBot.MediBot_Crosswalk_Library',
|
|
122
|
+
'medibot_crosswalk_utils': 'MediBot.MediBot_Crosswalk_Utils',
|
|
123
|
+
'medibot_dataformat_library': 'MediBot.MediBot_dataformat_library',
|
|
124
|
+
'medibot_docx_decoder': 'MediBot.MediBot_docx_decoder',
|
|
125
|
+
'medibot_ui': 'MediBot.MediBot_UI',
|
|
126
|
+
'medibot_charges': 'MediBot.MediBot_Charges',
|
|
127
|
+
'medibot_post': 'MediBot.MediBot_Post',
|
|
128
|
+
'get_medicafe_version': 'MediBot.get_medicafe_version',
|
|
129
|
+
'update_medicafe': 'MediBot.update_medicafe',
|
|
130
|
+
'update_json': 'MediBot.update_json',
|
|
131
|
+
|
|
132
|
+
# MediLink components
|
|
133
|
+
'medilink_main': 'MediLink.MediLink_main',
|
|
134
|
+
'medilink_azure': 'MediLink.MediLink_Azure',
|
|
135
|
+
'medilink_claim_status': 'MediLink.MediLink_ClaimStatus',
|
|
136
|
+
'medilink_datamgmt': 'MediLink.MediLink_DataMgmt',
|
|
137
|
+
'medilink_decoder': 'MediLink.MediLink_Decoder',
|
|
138
|
+
'medilink_deductible': 'MediLink.MediLink_Deductible',
|
|
139
|
+
'medilink_deductible_validator': 'MediLink.MediLink_Deductible_Validator',
|
|
140
|
+
'medilink_display_utils': 'MediLink.MediLink_Display_Utils',
|
|
141
|
+
'medilink_down': 'MediLink.MediLink_Down',
|
|
142
|
+
'medilink_gmail': 'MediLink.MediLink_Gmail',
|
|
143
|
+
'medilink_mailer': 'MediLink.MediLink_Mailer',
|
|
144
|
+
'medilink_parser': 'MediLink.MediLink_Parser',
|
|
145
|
+
'medilink_patient_processor': 'MediLink.MediLink_PatientProcessor',
|
|
146
|
+
'medilink_scan': 'MediLink.MediLink_Scan',
|
|
147
|
+
'medilink_scheduler': 'MediLink.MediLink_Scheduler',
|
|
148
|
+
'medilink_ui': 'MediLink.MediLink_UI',
|
|
149
|
+
'medilink_up': 'MediLink.MediLink_Up',
|
|
150
|
+
'medilink_insurance_utils': 'MediLink.MediLink_insurance_utils',
|
|
151
|
+
'medilink_837p_cob_library': 'MediLink.MediLink_837p_cob_library',
|
|
152
|
+
'medilink_837p_encoder': 'MediLink.MediLink_837p_encoder',
|
|
153
|
+
'medilink_837p_encoder_library': 'MediLink.MediLink_837p_encoder_library',
|
|
154
|
+
'medilink_837p_utilities': 'MediLink.MediLink_837p_utilities',
|
|
155
|
+
'medilink_api_generator': 'MediLink.MediLink_API_Generator',
|
|
156
|
+
'soumit_api': 'MediLink.Soumit_api',
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if name not in component_mappings:
|
|
160
|
+
raise ImportError("Unknown component: {}. Available components: {}".format(name, list(component_mappings.keys())))
|
|
161
|
+
|
|
162
|
+
module_path = component_mappings[name]
|
|
163
|
+
try:
|
|
164
|
+
module = importlib.import_module(module_path)
|
|
165
|
+
return module
|
|
166
|
+
except ImportError as e:
|
|
167
|
+
raise ImportError("Failed to load component '{}' from '{}': {}".format(name, module_path, e))
|
|
168
|
+
|
|
169
|
+
# Global registry instance
|
|
170
|
+
_registry = ComponentRegistry()
|
|
171
|
+
|
|
172
|
+
class ComponentProvider:
|
|
173
|
+
"""Main interface for requesting components."""
|
|
174
|
+
|
|
175
|
+
def __init__(self, registry: ComponentRegistry):
|
|
176
|
+
self.registry = registry
|
|
177
|
+
self._setup_module_configs()
|
|
178
|
+
|
|
179
|
+
def _setup_module_configs(self):
|
|
180
|
+
"""Setup predefined configurations for known module types."""
|
|
181
|
+
configs = {
|
|
182
|
+
# MediBot configurations
|
|
183
|
+
'medibot_preprocessor': {
|
|
184
|
+
'core_dependencies': ['api_core', 'logging_config', 'core_utils'],
|
|
185
|
+
'optional_dependencies': ['api_factory', 'api_utils'],
|
|
186
|
+
'shared_resources': ['medibot_dataformat_library', 'medibot_crosswalk_utils']
|
|
187
|
+
},
|
|
188
|
+
'medibot_ui': {
|
|
189
|
+
'core_dependencies': ['medibot_main', 'logging_config'],
|
|
190
|
+
'optional_dependencies': ['core_utils', 'api_core'],
|
|
191
|
+
'shared_resources': ['medibot_preprocessor', 'medibot_crosswalk_library']
|
|
192
|
+
},
|
|
193
|
+
'medibot_crosswalk': {
|
|
194
|
+
'core_dependencies': ['logging_config', 'core_utils'],
|
|
195
|
+
'optional_dependencies': ['api_core'],
|
|
196
|
+
'shared_resources': ['medibot_crosswalk_library', 'medibot_crosswalk_utils', 'medibot_dataformat_library']
|
|
197
|
+
},
|
|
198
|
+
'medibot_document_processing': {
|
|
199
|
+
'core_dependencies': ['logging_config', 'core_utils'],
|
|
200
|
+
'optional_dependencies': ['api_core'],
|
|
201
|
+
'shared_resources': ['medibot_docx_decoder', 'medibot_preprocessor_lib']
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
# MediLink configurations
|
|
205
|
+
'medilink_main': {
|
|
206
|
+
'core_dependencies': ['api_core', 'logging_config', 'core_utils'],
|
|
207
|
+
'optional_dependencies': ['api_factory', 'graphql_utils'],
|
|
208
|
+
'shared_resources': ['medilink_datamgmt', 'medilink_parser']
|
|
209
|
+
},
|
|
210
|
+
'medilink_claim_processing': {
|
|
211
|
+
'core_dependencies': ['api_core', 'logging_config', 'medilink_datamgmt'],
|
|
212
|
+
'optional_dependencies': ['graphql_utils', 'api_utils'],
|
|
213
|
+
'shared_resources': ['medilink_837p_encoder', 'medilink_837p_utilities', 'medilink_claim_status']
|
|
214
|
+
},
|
|
215
|
+
'medilink_deductible_processing': {
|
|
216
|
+
'core_dependencies': ['api_core', 'logging_config', 'medilink_datamgmt'],
|
|
217
|
+
'optional_dependencies': ['graphql_utils'],
|
|
218
|
+
'shared_resources': ['medilink_deductible', 'medilink_deductible_validator', 'medilink_insurance_utils']
|
|
219
|
+
},
|
|
220
|
+
'medilink_communication': {
|
|
221
|
+
'core_dependencies': ['logging_config', 'core_utils'],
|
|
222
|
+
'optional_dependencies': ['api_core'],
|
|
223
|
+
'shared_resources': ['medilink_gmail', 'medilink_mailer', 'medilink_display_utils']
|
|
224
|
+
},
|
|
225
|
+
'medilink_data_management': {
|
|
226
|
+
'core_dependencies': ['api_core', 'logging_config'],
|
|
227
|
+
'optional_dependencies': ['graphql_utils'],
|
|
228
|
+
'shared_resources': ['medilink_datamgmt', 'medilink_up', 'medilink_down', 'medilink_parser']
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
# General configurations
|
|
232
|
+
'general_api_access': {
|
|
233
|
+
'core_dependencies': ['api_core', 'api_factory'],
|
|
234
|
+
'optional_dependencies': ['api_utils', 'graphql_utils'],
|
|
235
|
+
'shared_resources': ['logging_config', 'core_utils']
|
|
236
|
+
},
|
|
237
|
+
'logging_only': {
|
|
238
|
+
'core_dependencies': ['logging_config'],
|
|
239
|
+
'optional_dependencies': [],
|
|
240
|
+
'shared_resources': []
|
|
241
|
+
},
|
|
242
|
+
'utilities_only': {
|
|
243
|
+
'core_dependencies': ['core_utils'],
|
|
244
|
+
'optional_dependencies': ['api_utils'],
|
|
245
|
+
'shared_resources': ['logging_config']
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
for module_name, config in configs.items():
|
|
250
|
+
self.registry.register_module_config(module_name, config)
|
|
251
|
+
|
|
252
|
+
def __call__(self, *component_names, **kwargs):
|
|
253
|
+
"""Get one or more components by name."""
|
|
254
|
+
silent_fail = kwargs.get('silent_fail', False)
|
|
255
|
+
if len(component_names) == 1:
|
|
256
|
+
return self.registry.get_component(component_names[0], silent_fail=silent_fail)
|
|
257
|
+
|
|
258
|
+
results = []
|
|
259
|
+
for name in component_names:
|
|
260
|
+
component = self.registry.get_component(name, silent_fail=silent_fail)
|
|
261
|
+
results.append(component)
|
|
262
|
+
return tuple(results)
|
|
263
|
+
|
|
264
|
+
def for_module(self, module_type: str, silent_fail: bool = False) -> Dict[str, Any]:
|
|
265
|
+
"""Get all components needed for a specific module type."""
|
|
266
|
+
if module_type not in self.registry._module_configs:
|
|
267
|
+
available_types = list(self.registry._module_configs.keys())
|
|
268
|
+
raise ValueError("Unknown module type: {}. Available types: {}".format(module_type, available_types))
|
|
269
|
+
|
|
270
|
+
config = self.registry._module_configs[module_type]
|
|
271
|
+
components = {}
|
|
272
|
+
|
|
273
|
+
# Load core dependencies (these must succeed unless silent_fail is True)
|
|
274
|
+
for dep in config.get('core_dependencies', []):
|
|
275
|
+
component = self.registry.get_component(dep, silent_fail=silent_fail)
|
|
276
|
+
if component is not None:
|
|
277
|
+
components[dep] = component
|
|
278
|
+
|
|
279
|
+
# Load optional dependencies (always fail silently)
|
|
280
|
+
for dep in config.get('optional_dependencies', []):
|
|
281
|
+
try:
|
|
282
|
+
component = self.registry.get_component(dep, silent_fail=True)
|
|
283
|
+
if component is not None:
|
|
284
|
+
components[dep] = component
|
|
285
|
+
except ImportError:
|
|
286
|
+
pass
|
|
287
|
+
|
|
288
|
+
# Load shared resources (always fail silently)
|
|
289
|
+
for dep in config.get('shared_resources', []):
|
|
290
|
+
try:
|
|
291
|
+
component = self.registry.get_component(dep, silent_fail=True)
|
|
292
|
+
if component is not None:
|
|
293
|
+
components[dep] = component
|
|
294
|
+
except ImportError:
|
|
295
|
+
pass
|
|
296
|
+
|
|
297
|
+
return components
|
|
298
|
+
|
|
299
|
+
def get_api_suite(self) -> Dict[str, Any]:
|
|
300
|
+
"""Get the complete API access suite."""
|
|
301
|
+
return self.for_module('general_api_access')
|
|
302
|
+
|
|
303
|
+
def get_medibot_suite(self, module_type: str = 'medibot_preprocessor') -> Dict[str, Any]:
|
|
304
|
+
"""Get components specifically for MediBot operations."""
|
|
305
|
+
return self.for_module(module_type)
|
|
306
|
+
|
|
307
|
+
def get_medilink_suite(self, module_type: str = 'medilink_main') -> Dict[str, Any]:
|
|
308
|
+
"""Get components specifically for MediLink operations."""
|
|
309
|
+
return self.for_module(module_type)
|
|
310
|
+
|
|
311
|
+
def list_available_components(self) -> List[str]:
|
|
312
|
+
"""List all available component names."""
|
|
313
|
+
# Get component mappings from registry's _load_component method
|
|
314
|
+
component_mappings = {
|
|
315
|
+
'api_core', 'api_factory', 'api_utils', 'core_utils', 'graphql_utils', 'logging_config',
|
|
316
|
+
'medicafe_config_loader', 'medibot_main', 'medibot_preprocessor', 'medibot_preprocessor_lib',
|
|
317
|
+
'medibot_crosswalk_library', 'medibot_crosswalk_utils', 'medibot_dataformat_library',
|
|
318
|
+
'medibot_docx_decoder', 'medibot_ui', 'medibot_charges', 'medibot_post',
|
|
319
|
+
'get_medicafe_version', 'update_medicafe', 'update_json', 'medilink_main',
|
|
320
|
+
'medilink_azure', 'medilink_claim_status', 'medilink_datamgmt', 'medilink_decoder',
|
|
321
|
+
'medilink_deductible', 'medilink_deductible_validator', 'medilink_display_utils',
|
|
322
|
+
'medilink_down', 'medilink_gmail', 'medilink_mailer', 'medilink_parser',
|
|
323
|
+
'medilink_patient_processor', 'medilink_scan', 'medilink_scheduler', 'medilink_ui',
|
|
324
|
+
'medilink_up', 'medilink_insurance_utils', 'medilink_837p_cob_library',
|
|
325
|
+
'medilink_837p_encoder', 'medilink_837p_encoder_library', 'medilink_837p_utilities',
|
|
326
|
+
'medilink_api_generator', 'soumit_api'
|
|
327
|
+
}
|
|
328
|
+
return sorted(list(component_mappings))
|
|
329
|
+
|
|
330
|
+
def list_available_module_types(self) -> List[str]:
|
|
331
|
+
"""List all available module type configurations."""
|
|
332
|
+
return sorted(list(self.registry._module_configs.keys()))
|
|
333
|
+
|
|
334
|
+
# Global component provider
|
|
335
|
+
get_components = ComponentProvider(_registry)
|
|
336
|
+
|
|
337
|
+
# Convenience functions for common use cases
|
|
338
|
+
def get_api_access():
|
|
339
|
+
"""Get standard API access components."""
|
|
340
|
+
return get_components.get_api_suite()
|
|
341
|
+
|
|
342
|
+
def get_logging():
|
|
343
|
+
"""Get logging configuration."""
|
|
344
|
+
return get_components('logging_config')
|
|
345
|
+
|
|
346
|
+
def get_core_utils():
|
|
347
|
+
"""Get core utilities."""
|
|
348
|
+
return get_components('core_utils')
|
|
349
|
+
|
|
350
|
+
def setup_for_medibot(module_type: str = 'medibot_preprocessor'):
|
|
351
|
+
"""Setup everything needed for MediBot operations."""
|
|
352
|
+
return get_components.get_medibot_suite(module_type)
|
|
353
|
+
|
|
354
|
+
def setup_for_medilink(module_type: str = 'medilink_main'):
|
|
355
|
+
"""Setup everything needed for MediLink operations."""
|
|
356
|
+
return get_components.get_medilink_suite(module_type)
|
|
357
|
+
|
|
358
|
+
# Helper functions for discovery
|
|
359
|
+
def list_components():
|
|
360
|
+
"""List all available component names."""
|
|
361
|
+
return get_components.list_available_components()
|
|
362
|
+
|
|
363
|
+
def list_module_types():
|
|
364
|
+
"""List all available module type configurations."""
|
|
365
|
+
return get_components.list_available_module_types()
|
|
366
|
+
|
|
367
|
+
def describe_module_type(module_type: str):
|
|
368
|
+
"""Describe what components a module type provides."""
|
|
369
|
+
if module_type in _registry._module_configs:
|
|
370
|
+
config = _registry._module_configs[module_type]
|
|
371
|
+
print("Module Type: {}".format(module_type))
|
|
372
|
+
print("Core Dependencies: {}".format(config.get('core_dependencies', [])))
|
|
373
|
+
print("Optional Dependencies: {}".format(config.get('optional_dependencies', [])))
|
|
374
|
+
print("Shared Resources: {}".format(config.get('shared_resources', [])))
|
|
375
|
+
else:
|
|
376
|
+
print("Unknown module type: {}".format(module_type))
|
|
377
|
+
print("Available types: {}".format(list_module_types()))
|
|
378
|
+
|
|
379
|
+
# Module initialization and validation
|
|
380
|
+
def validate_setup():
|
|
381
|
+
"""Validate that the import system is working correctly."""
|
|
382
|
+
try:
|
|
383
|
+
# Test core components
|
|
384
|
+
logging_config = get_components('logging_config')
|
|
385
|
+
core_utils = get_components('core_utils')
|
|
386
|
+
|
|
387
|
+
print("[+] MediCafe Smart Import System initialized successfully")
|
|
388
|
+
print("[+] Available components: {}".format(len(list_components())))
|
|
389
|
+
print("[+] Available module types: {}".format(len(list_module_types())))
|
|
390
|
+
return True
|
|
391
|
+
except Exception as e:
|
|
392
|
+
print("[-] MediCafe Smart Import System validation failed: {}".format(e))
|
|
393
|
+
return False
|
|
394
|
+
|
|
395
|
+
# Advanced usage examples and documentation
|
|
396
|
+
def show_usage_examples():
|
|
397
|
+
"""Show usage examples for the smart import system."""
|
|
398
|
+
examples = """
|
|
399
|
+
MediCafe Smart Import System - Usage Examples
|
|
400
|
+
|
|
401
|
+
1. Basic component import:
|
|
402
|
+
from MediCafe.smart_import import get_components
|
|
403
|
+
api_core, logging_config = get_components('api_core', 'logging_config')
|
|
404
|
+
|
|
405
|
+
2. Setup for MediBot:
|
|
406
|
+
from MediCafe.smart_import import setup_for_medibot
|
|
407
|
+
components = setup_for_medibot('medibot_preprocessor')
|
|
408
|
+
api_core = components['api_core']
|
|
409
|
+
|
|
410
|
+
3. Setup for MediLink:
|
|
411
|
+
from MediCafe.smart_import import setup_for_medilink
|
|
412
|
+
components = setup_for_medilink('medilink_claim_processing')
|
|
413
|
+
datamgmt = components['medilink_datamgmt']
|
|
414
|
+
|
|
415
|
+
4. Get API access suite:
|
|
416
|
+
from MediCafe.smart_import import get_api_access
|
|
417
|
+
api_suite = get_api_access()
|
|
418
|
+
api_core = api_suite['api_core']
|
|
419
|
+
api_factory = api_suite['api_factory']
|
|
420
|
+
|
|
421
|
+
5. Discovery functions:
|
|
422
|
+
from MediCafe.smart_import import list_components, list_module_types
|
|
423
|
+
print("Available components:", list_components())
|
|
424
|
+
print("Available module types:", list_module_types())
|
|
425
|
+
"""
|
|
426
|
+
print(examples)
|
|
427
|
+
|
|
428
|
+
# Auto-validation on import (silent)
|
|
429
|
+
if __name__ != '__main__':
|
|
430
|
+
try:
|
|
431
|
+
# Silent validation - don't print success messages on import
|
|
432
|
+
logging_config = get_components('logging_config', silent_fail=True)
|
|
433
|
+
if logging_config:
|
|
434
|
+
pass # Successfully validated
|
|
435
|
+
except:
|
|
436
|
+
pass # Silent fail on import
|
|
@@ -32,8 +32,8 @@ Key Implementation Notes:
|
|
|
32
32
|
SEGMENT ORDER CONSTRAINTS:
|
|
33
33
|
- 1000A: Submitter
|
|
34
34
|
- 1000B: Receiver
|
|
35
|
-
- 2000A
|
|
36
|
-
- 2000B
|
|
35
|
+
- 2000A?2010AA: Billing provider
|
|
36
|
+
- 2000B?2010BA/BB: Subscriber and payer
|
|
37
37
|
- 2300: Claim
|
|
38
38
|
- 2320: Other subscriber info (COB)
|
|
39
39
|
- 2330B: Prior payer
|
|
@@ -50,32 +50,32 @@ VALIDATION REQUIREMENTS:
|
|
|
50
50
|
|
|
51
51
|
from datetime import datetime
|
|
52
52
|
import sys, os
|
|
53
|
-
|
|
53
|
+
|
|
54
|
+
# Use core utilities for standardized imports
|
|
55
|
+
from MediCafe.core_utils import get_shared_config_loader
|
|
56
|
+
MediLink_ConfigLoader = get_shared_config_loader()
|
|
54
57
|
|
|
55
58
|
project_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
56
59
|
if project_dir not in sys.path:
|
|
57
60
|
sys.path.append(project_dir)
|
|
58
61
|
|
|
59
|
-
#
|
|
62
|
+
# Import utility functions - absolute imports only
|
|
60
63
|
try:
|
|
61
|
-
from
|
|
62
|
-
except
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
""
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
except (ValueError, TypeError):
|
|
77
|
-
# Return original string if conversion fails
|
|
78
|
-
return date_str
|
|
64
|
+
from MediLink_837p_utilities import convert_date_format
|
|
65
|
+
except ImportError as e:
|
|
66
|
+
# Fallback implementation for convert_date_format if utilities module is not available
|
|
67
|
+
MediLink_ConfigLoader.log("Warning: Could not import utilities functions: {}".format(e), level="WARNING")
|
|
68
|
+
def convert_date_format(date_str):
|
|
69
|
+
"""Fallback date format conversion function"""
|
|
70
|
+
try:
|
|
71
|
+
# Parse the input date string into a datetime object
|
|
72
|
+
input_format = "%m-%d-%Y" if len(date_str) == 10 else "%m-%d-%y"
|
|
73
|
+
date_obj = datetime.strptime(date_str, input_format)
|
|
74
|
+
# Format the datetime object into the desired output format
|
|
75
|
+
return date_obj.strftime("%Y%m%d")
|
|
76
|
+
except (ValueError, TypeError):
|
|
77
|
+
# Return original string if conversion fails
|
|
78
|
+
return date_str
|
|
79
79
|
|
|
80
80
|
def create_2320_other_subscriber_segments(patient_data, config, crosswalk):
|
|
81
81
|
"""
|
|
@@ -83,7 +83,7 @@ def create_2320_other_subscriber_segments(patient_data, config, crosswalk):
|
|
|
83
83
|
|
|
84
84
|
Required segments:
|
|
85
85
|
- SBR: Secondary payer relationship and responsibility
|
|
86
|
-
- AMT: AMT*D
|
|
86
|
+
- AMT: AMT*D ? Total amount paid by Medicare or other primary
|
|
87
87
|
- CAS: Patient liability (CO/PR adjustments)
|
|
88
88
|
- OI: Other insurance coverage indicator
|
|
89
89
|
|
|
@@ -190,7 +190,7 @@ def create_2430_service_line_cob_segments(patient_data, config, crosswalk):
|
|
|
190
190
|
Required segments (when service-level adjudication exists):
|
|
191
191
|
- SVD: Paid amount per service line (from 835 SVC03)
|
|
192
192
|
- CAS: Line-level adjustments (from 835 CAS segments)
|
|
193
|
-
- DTP: DTP*573
|
|
193
|
+
- DTP: DTP*573 ? Adjudication date per service
|
|
194
194
|
|
|
195
195
|
Parameters:
|
|
196
196
|
- patient_data: Dictionary containing service line and adjudication data
|
|
@@ -365,10 +365,10 @@ def extract_835_adjudication_data(patient_data, config):
|
|
|
365
365
|
Extracts and validates 835-derived adjudication data for COB embedding.
|
|
366
366
|
|
|
367
367
|
Extracts:
|
|
368
|
-
- CLP02
|
|
369
|
-
- CAS segments
|
|
370
|
-
- SVC03
|
|
371
|
-
- DTP segments
|
|
368
|
+
- CLP02 ? AMT*D (2320)
|
|
369
|
+
- CAS segments ? CAS (2320 and/or 2430)
|
|
370
|
+
- SVC03 ? SVD02 (2430)
|
|
371
|
+
- DTP segments ? DTP*573 (2430)
|
|
372
372
|
|
|
373
373
|
Parameters:
|
|
374
374
|
- patient_data: Dictionary containing 835 data
|
|
@@ -1,42 +1,36 @@
|
|
|
1
1
|
# MediLink_837p_encoder.py
|
|
2
|
-
import re, argparse, os
|
|
2
|
+
import re, argparse, os, sys
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
# Add workspace directory to Python path for MediCafe imports
|
|
6
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
7
|
+
workspace_dir = os.path.dirname(current_dir)
|
|
8
|
+
if workspace_dir not in sys.path:
|
|
9
|
+
sys.path.insert(0, workspace_dir)
|
|
10
|
+
|
|
11
|
+
# Use core utilities for standardized imports and path setup
|
|
12
|
+
from MediCafe.core_utils import get_shared_config_loader, get_api_client, setup_module_paths
|
|
13
|
+
setup_module_paths(__file__)
|
|
14
|
+
|
|
15
|
+
MediLink_ConfigLoader = get_shared_config_loader()
|
|
13
16
|
|
|
14
|
-
#
|
|
17
|
+
# Import api_core for API client fallback
|
|
15
18
|
try:
|
|
16
|
-
from
|
|
17
|
-
except
|
|
18
|
-
|
|
19
|
-
from MediLink_DataMgmt import parse_fixed_width_data, read_fixed_width_data
|
|
20
|
-
except ImportError:
|
|
21
|
-
from MediLink.MediLink_DataMgmt import parse_fixed_width_data, read_fixed_width_data
|
|
19
|
+
from MediCafe import api_core
|
|
20
|
+
except ImportError:
|
|
21
|
+
api_core = None
|
|
22
22
|
|
|
23
|
-
#
|
|
23
|
+
# Import DataMgmt functions - absolute imports only
|
|
24
24
|
try:
|
|
25
|
-
from
|
|
26
|
-
except
|
|
27
|
-
|
|
28
|
-
import MediLink_837p_encoder_library
|
|
29
|
-
except ImportError:
|
|
30
|
-
from MediLink import MediLink_837p_encoder_library
|
|
25
|
+
from MediLink_DataMgmt import parse_fixed_width_data, read_fixed_width_data
|
|
26
|
+
except ImportError:
|
|
27
|
+
from MediLink.MediLink_DataMgmt import parse_fixed_width_data, read_fixed_width_data
|
|
31
28
|
|
|
32
|
-
#
|
|
29
|
+
# Import encoder library - absolute imports only
|
|
33
30
|
try:
|
|
34
|
-
|
|
35
|
-
except
|
|
36
|
-
|
|
37
|
-
import MediLink_API_v3
|
|
38
|
-
except ImportError:
|
|
39
|
-
from MediLink import MediLink_API_v3
|
|
31
|
+
import MediLink_837p_encoder_library
|
|
32
|
+
except ImportError:
|
|
33
|
+
from MediLink import MediLink_837p_encoder_library
|
|
40
34
|
|
|
41
35
|
# TODO (COB ENHANCEMENT): Import COB library when implementing Medicare and secondary claim support
|
|
42
36
|
# import MediLink_837p_cob_library
|
|
@@ -246,7 +240,7 @@ def read_and_validate_claims(file_path, config):
|
|
|
246
240
|
|
|
247
241
|
# Iterate over data in the file
|
|
248
242
|
for personal_info, insurance_info, service_info, service_info_2, service_info_3 in read_fixed_width_data(file_path):
|
|
249
|
-
#
|
|
243
|
+
# Process reserved 5-line Medisoft record (currently using 3 lines, 2 reserved)
|
|
250
244
|
parsed_data = parse_fixed_width_data(personal_info, insurance_info, service_info, service_info_2, service_info_3, config.get('MediLink_Config', config))
|
|
251
245
|
# Validate the parsed data
|
|
252
246
|
is_valid, errors = validate_claim_data(parsed_data, config)
|
|
@@ -304,10 +298,10 @@ def validate_claim_data(parsed_data, config, required_fields=[]):
|
|
|
304
298
|
if required_fields is None:
|
|
305
299
|
required_fields = [
|
|
306
300
|
('CHART', None),
|
|
307
|
-
('billing_provider_npi', r'
|
|
301
|
+
('billing_provider_npi', r'^\\d{10}$'),
|
|
308
302
|
('IPOLICY', None),
|
|
309
303
|
('CODEA', None),
|
|
310
|
-
('DATE', r'
|
|
304
|
+
('DATE', r'^\\d{8}$'),
|
|
311
305
|
('AMOUNT', None),
|
|
312
306
|
('TOS', None),
|
|
313
307
|
('DIAG', None)
|
|
@@ -434,7 +428,12 @@ def main():
|
|
|
434
428
|
config = config.get('MediLink_Config', config)
|
|
435
429
|
|
|
436
430
|
# Create API client for payer name resolution
|
|
437
|
-
|
|
431
|
+
from MediCafe.core_utils import get_api_client
|
|
432
|
+
client = get_api_client()
|
|
433
|
+
if client is None:
|
|
434
|
+
print("Warning: API client not available via factory")
|
|
435
|
+
# Fallback to direct instantiation
|
|
436
|
+
client = api_core.APIClient()
|
|
438
437
|
|
|
439
438
|
process_dat_files(args.path, config, args.endpoint, args.is_directory, crosswalk, client)
|
|
440
439
|
print("Conversion complete.")
|