medicafe 0.240613.0__py3-none-any.whl → 0.240716.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.

@@ -0,0 +1,325 @@
1
+ import time
2
+ import requests
3
+ import yaml
4
+ import json
5
+ import os
6
+
7
+ try:
8
+ from MediLink import MediLink_ConfigLoader
9
+ except ImportError:
10
+ import MediLink_ConfigLoader
11
+
12
+ class ConfigLoader:
13
+ @staticmethod
14
+ def load_configuration(config_path=os.path.join(os.path.dirname(__file__), '..', 'json', 'config.json'),
15
+ crosswalk_path=os.path.join(os.path.dirname(__file__), '..', 'json', 'crosswalk.json')):
16
+ return MediLink_ConfigLoader.load_configuration(config_path, crosswalk_path)
17
+
18
+ @staticmethod
19
+ def load_swagger_file(swagger_path):
20
+ try:
21
+ print("Attempting to load Swagger file: {}".format(swagger_path))
22
+ with open(swagger_path, 'r') as swagger_file:
23
+ if swagger_path.endswith('.yaml') or swagger_path.endswith('.yml'):
24
+ print("Parsing YAML file: {}".format(swagger_path))
25
+ swagger_data = yaml.safe_load(swagger_file)
26
+ elif swagger_path.endswith('.json'):
27
+ print("Parsing JSON file: {}".format(swagger_path))
28
+ swagger_data = json.load(swagger_file)
29
+ else:
30
+ raise ValueError("Unsupported Swagger file format.")
31
+ print("Successfully loaded Swagger file: {}".format(swagger_path))
32
+ return swagger_data
33
+ except ValueError as e:
34
+ print("Error parsing Swagger file {}: {}".format(swagger_path, e))
35
+ MediLink_ConfigLoader.log("Error parsing Swagger file {}: {}".format(swagger_path, e), level="ERROR")
36
+ except FileNotFoundError:
37
+ print("Swagger file not found: {}".format(swagger_path))
38
+ MediLink_ConfigLoader.log("Swagger file not found: {}".format(swagger_path), level="ERROR")
39
+ except Exception as e:
40
+ print("Unexpected error loading Swagger file {}: {}".format(swagger_path, e))
41
+ MediLink_ConfigLoader.log("Unexpected error loading Swagger file {}: {}".format(swagger_path, e), level="ERROR")
42
+ return None
43
+
44
+ # Function to ensure numeric type
45
+ def ensure_numeric(value):
46
+ if isinstance(value, str):
47
+ try:
48
+ value = float(value)
49
+ except ValueError:
50
+ raise ValueError("Cannot convert {} to a numeric type".format(value))
51
+ return value
52
+
53
+ class TokenCache:
54
+ def __init__(self):
55
+ self.tokens = {}
56
+
57
+ def get(self, endpoint_name, current_time):
58
+ token_info = self.tokens.get(endpoint_name, {})
59
+ if token_info and token_info['expires_at'] > current_time:
60
+ return token_info['access_token']
61
+ return None
62
+
63
+ def set(self, endpoint_name, access_token, expires_in, current_time):
64
+ # Ensure types are correct
65
+ current_time = ensure_numeric(current_time)
66
+ expires_in = ensure_numeric(expires_in)
67
+
68
+ self.tokens[endpoint_name] = {
69
+ 'access_token': access_token,
70
+ 'expires_at': current_time + expires_in - 120
71
+ }
72
+
73
+ class BaseAPIClient:
74
+ def __init__(self, config):
75
+ self.config = config
76
+ self.token_cache = TokenCache()
77
+
78
+ def get_access_token(self, endpoint_name):
79
+ raise NotImplementedError("Subclasses should implement this!")
80
+
81
+ def make_api_call(self, endpoint_name, call_type, url_extension="", params=None, data=None, headers=None):
82
+ raise NotImplementedError("Subclasses should implement this!")
83
+
84
+ class APIClient(BaseAPIClient):
85
+ def __init__(self):
86
+ config, _ = MediLink_ConfigLoader.load_configuration()
87
+ super().__init__(config)
88
+
89
+ def get_access_token(self, endpoint_name):
90
+ current_time = time.time()
91
+ cached_token = self.token_cache.get(endpoint_name, current_time)
92
+ if cached_token:
93
+ MediLink_ConfigLoader.log("Using cached token for endpoint: {}".format(endpoint_name), level="INFO")
94
+ return cached_token
95
+
96
+ endpoint_config = self.config['MediLink_Config']['endpoints'][endpoint_name]
97
+ token_url = endpoint_config['token_url']
98
+ data = {
99
+ 'grant_type': 'client_credentials',
100
+ 'client_id': endpoint_config['client_id'],
101
+ 'client_secret': endpoint_config['client_secret']
102
+ }
103
+
104
+ # Add scope if specified in the configuration
105
+ if 'scope' in endpoint_config:
106
+ data['scope'] = endpoint_config['scope']
107
+
108
+ headers = {'Content-Type': 'application/x-www-form-urlencoded'}
109
+
110
+ response = requests.post(token_url, headers=headers, data=data)
111
+ response.raise_for_status()
112
+ token_data = response.json()
113
+ access_token = token_data['access_token']
114
+ expires_in = token_data.get('expires_in', 3600)
115
+
116
+ self.token_cache.set(endpoint_name, access_token, expires_in, current_time)
117
+ MediLink_ConfigLoader.log("Obtained new token for endpoint: {}".format(endpoint_name), level="INFO")
118
+ return access_token
119
+
120
+ def make_api_call(self, endpoint_name, call_type, url_extension="", params=None, data=None, headers=None):
121
+ token = self.get_access_token(endpoint_name)
122
+ if headers is None:
123
+ headers = {}
124
+ headers.update({'Authorization': 'Bearer {}'.format(token), 'Accept': 'application/json'})
125
+ url = self.config['MediLink_Config']['endpoints'][endpoint_name]['api_url'] + url_extension
126
+
127
+ # Debug: Print request details
128
+ # print("Request URL: {}".format(url))
129
+ # print("Request Headers: {}".format(headers))
130
+ # print("Request Params: {}".format(params))
131
+ # print("Request Data: {}".format(data))
132
+
133
+ if call_type == 'GET':
134
+ response = requests.get(url, headers=headers, params=params)
135
+ elif call_type == 'POST':
136
+ headers['Content-Type'] = 'application/json'
137
+ response = requests.post(url, headers=headers, json=data)
138
+ elif call_type == 'DELETE':
139
+ response = requests.delete(url, headers=headers)
140
+ else:
141
+ raise ValueError("Unsupported call type")
142
+
143
+ if response.status_code >= 400:
144
+ error_message = "Error {}: {}".format(response.status_code, response.text)
145
+ MediLink_ConfigLoader.log(error_message, level="ERROR")
146
+ response.raise_for_status()
147
+
148
+ return response.json()
149
+
150
+ def fetch_payer_name_from_api(payer_id, config, primary_endpoint='AVAILITY'):
151
+ client = APIClient()
152
+ config, _ = MediLink_ConfigLoader.load_configuration()
153
+ endpoints = config['MediLink_Config']['endpoints']
154
+
155
+ if primary_endpoint and primary_endpoint in endpoints:
156
+ endpoint_order = [primary_endpoint] + [endpoint for endpoint in endpoints if endpoint != primary_endpoint]
157
+ else:
158
+ endpoint_order = list(endpoints.keys())
159
+
160
+ for endpoint_name in endpoint_order:
161
+ try:
162
+ response = client.make_api_call(endpoint_name, 'GET', config['MediLink_Config']['endpoints'][endpoint_name].get('payer_list_endpoint', '/availity-payer-list'), {'payerId': payer_id})
163
+ payers = response.get('payers', [])
164
+ if payers:
165
+ payer_name = payers[0].get('displayName', payers[0].get('name'))
166
+ MediLink_ConfigLoader.log("Successfully found payer at {} for ID {}: {}".format(endpoint_name, payer_id, payer_name), level="INFO")
167
+ return payer_name
168
+ else:
169
+ MediLink_ConfigLoader.log("No payer found at {} for ID: {}. Trying next available endpoint.".format(endpoint_name, payer_id), level="INFO")
170
+ except Exception as e:
171
+ MediLink_ConfigLoader.log("API call to {} failed: {}".format(endpoint_name, e), level="ERROR")
172
+
173
+ error_message = "All endpoints exhausted for Payer ID {}.".format(payer_id)
174
+ MediLink_ConfigLoader.log(error_message, level="CRITICAL")
175
+ raise ValueError(error_message)
176
+
177
+ def get_claim_summary_by_provider(client, tin, first_service_date, last_service_date, payer_id, get_standard_error='false'):
178
+ endpoint_name = 'UHCApi'
179
+ url_extension = client.config['MediLink_Config']['endpoints'][endpoint_name]['additional_endpoints']['claim_summary_by_provider']
180
+ headers = {
181
+ 'tin': tin,
182
+ 'firstServiceDt': first_service_date,
183
+ 'lastServiceDt': last_service_date,
184
+ 'payerId': payer_id,
185
+ 'getStandardError': get_standard_error,
186
+ 'Accept': 'application/json'
187
+ }
188
+ return client.make_api_call(endpoint_name, 'GET', url_extension, params=None, data=None, headers=headers)
189
+
190
+ def get_eligibility(client, payer_id, provider_last_name, search_option, date_of_birth, member_id, npi):
191
+ endpoint_name = 'UHCApi'
192
+ url_extension = client.config['MediLink_Config']['endpoints'][endpoint_name]['additional_endpoints']['eligibility']
193
+ url_extension = url_extension + '?payerID={}&providerLastName={}&searchOption={}&dateOfBirth={}&memberId={}&npi={}'.format(
194
+ payer_id, provider_last_name, search_option, date_of_birth, member_id, npi)
195
+ return client.make_api_call(endpoint_name, 'GET', url_extension)
196
+
197
+ def get_eligibility_v3(client, payer_id, provider_last_name, search_option, date_of_birth, member_id, npi,
198
+ first_name=None, last_name=None, payer_label=None, payer_name=None, service_start=None, service_end=None,
199
+ middle_name=None, gender=None, ssn=None, city=None, state=None, zip=None, group_number=None,
200
+ service_type_code=None, provider_first_name=None, tax_id_number=None, provider_name_id=None,
201
+ corporate_tax_owner_id=None, corporate_tax_owner_name=None, organization_name=None,
202
+ organization_id=None, identify_service_level_deductible=True):
203
+
204
+ # Ensure all required parameters have values
205
+ if not all([client, payer_id, provider_last_name, search_option, date_of_birth, member_id, npi]):
206
+ raise ValueError("All required parameters must have values: client, payer_id, provider_last_name, search_option, date_of_birth, member_id, npi")
207
+
208
+ # Validate payer_id
209
+ valid_payer_ids = ["87726", "06111", "25463", "37602", "39026", "74227", "65088", "81400", "03432", "86050", "86047", "95378", "95467"]
210
+ if payer_id not in valid_payer_ids:
211
+ raise ValueError("Invalid payer_id: {}. Must be one of: {}".format(payer_id, ", ".join(valid_payer_ids)))
212
+
213
+ endpoint_name = 'UHCApi'
214
+ url_extension = client.config['MediLink_Config']['endpoints'][endpoint_name]['additional_endpoints']['eligibility_v3']
215
+
216
+ # Construct request body
217
+ body = {
218
+ "memberId": member_id,
219
+ "lastName": last_name,
220
+ "firstName": first_name,
221
+ "dateOfBirth": date_of_birth,
222
+ "payerID": payer_id,
223
+ "payerLabel": payer_label,
224
+ "payerName": payer_name,
225
+ "serviceStart": service_start,
226
+ "serviceEnd": service_end,
227
+ "middleName": middle_name,
228
+ "gender": gender,
229
+ "ssn": ssn,
230
+ "city": city,
231
+ "state": state,
232
+ "zip": zip,
233
+ "groupNumber": group_number,
234
+ "serviceTypeCode": service_type_code,
235
+ "providerLastName": provider_last_name,
236
+ "providerFirstName": provider_first_name,
237
+ "taxIdNumber": tax_id_number,
238
+ "providerNameID": provider_name_id,
239
+ "npi": npi,
240
+ "corporateTaxOwnerID": corporate_tax_owner_id,
241
+ "corporateTaxOwnerName": corporate_tax_owner_name,
242
+ "organizationName": organization_name,
243
+ "organizationID": organization_id,
244
+ "searchOption": search_option,
245
+ "identifyServiceLevelDeductible": identify_service_level_deductible
246
+ }
247
+
248
+ # Remove None values from the body
249
+ body = {k: v for k, v in body.items() if v is not None}
250
+
251
+ # Log the request body
252
+ MediLink_ConfigLoader.log("Request body: {}".format(json.dumps(body, indent=4)), level="DEBUG")
253
+
254
+ return client.make_api_call(endpoint_name, 'POST', url_extension, params=None, data=body)
255
+
256
+ if __name__ == "__main__":
257
+ client = APIClient()
258
+
259
+ # Define a configuration to enable or disable tests
260
+ test_config = {
261
+ 'test_fetch_payer_name': False,
262
+ 'test_claim_summary': False,
263
+ 'test_eligibility': False,
264
+ 'test_eligibility_v3': True,
265
+ }
266
+
267
+ try:
268
+ api_test_cases = client.config['MediLink_Config']['API Test Case']
269
+
270
+ # Test 1: Fetch Payer Name
271
+ if test_config.get('test_fetch_payer_name', False):
272
+ try:
273
+ for case in api_test_cases:
274
+ payer_name = fetch_payer_name_from_api(case['payer_id'], client.config)
275
+ print("TEST API: Payer Name: {}".format(payer_name))
276
+ except Exception as e:
277
+ print("TEST API: Error in Fetch Payer Name Test: {}".format(e))
278
+
279
+ # Test 2: Get Claim Summary
280
+ if test_config.get('test_claim_summary', False):
281
+ try:
282
+ for case in api_test_cases:
283
+ claim_summary = get_claim_summary_by_provider(client, case['provider_tin'], '05/01/2024', '06/23/2024', case['payer_id'])
284
+ print("TEST API: Claim Summary: {}".format(claim_summary))
285
+ except Exception as e:
286
+ print("TEST API: Error in Claim Summary Test: {}".format(e))
287
+
288
+ # Test 3: Get Eligibility
289
+ if test_config.get('test_eligibility', False):
290
+ try:
291
+ for case in api_test_cases:
292
+ eligibility = get_eligibility(client, case['payer_id'], case['provider_last_name'], case['search_option'],
293
+ case['date_of_birth'], case['member_id'], case['npi'])
294
+ print("TEST API: Eligibility: {}".format(eligibility))
295
+ except Exception as e:
296
+ print("TEST API: Error in Eligibility Test: {}".format(e))
297
+
298
+ # Test 4: Get Eligibility v3
299
+ if test_config.get('test_eligibility_v3', False):
300
+ try:
301
+ for case in api_test_cases:
302
+ eligibility_v3 = get_eligibility_v3(client, payer_id=case['payer_id'], provider_last_name=case['provider_last_name'],
303
+ search_option=case['search_option'], date_of_birth=case['date_of_birth'],
304
+ member_id=case['member_id'], npi=case['npi'])
305
+ print("TEST API: Eligibility v3: {}".format(eligibility_v3))
306
+ except Exception as e:
307
+ print("TEST API: Error in Eligibility v3 Test: {}".format(e))
308
+
309
+ """
310
+ # Example of iterating over multiple patients (if needed)
311
+ patients = [
312
+ {'payer_id': '87726', 'provider_last_name': 'VIDA', 'search_option': 'MemberIDDateOfBirth', 'date_of_birth': '1980-01-01', 'member_id': '123456789', 'npi': '9876543210'},
313
+ {'payer_id': '87726', 'provider_last_name': 'SMITH', 'search_option': 'MemberIDDateOfBirth', 'date_of_birth': '1970-02-02', 'member_id': '987654321', 'npi': '1234567890'},
314
+ # Add more patients as needed
315
+ ]
316
+
317
+ for patient in patients:
318
+ try:
319
+ eligibility = get_eligibility(client, patient['payer_id'], patient['provider_last_name'], patient['search_option'], patient['date_of_birth'], patient['member_id'], patient['npi'])
320
+ print("Eligibility for {}: {}".format(patient['provider_last_name'], eligibility))
321
+ except Exception as e:
322
+ print("Error in getting eligibility for {}: {}".format(patient['provider_last_name'], e))
323
+ """
324
+ except Exception as e:
325
+ print("TEST API: Unexpected Error: {}".format(e))
@@ -0,0 +1,144 @@
1
+ from datetime import datetime, timedelta
2
+ import MediLink_API_v3
3
+
4
+ try:
5
+ from MediLink import MediLink_ConfigLoader
6
+ except ImportError:
7
+ import MediLink_ConfigLoader
8
+
9
+ # Load configuration
10
+ config, _ = MediLink_ConfigLoader.load_configuration()
11
+
12
+ # Calculate start_date as 60 days before today's date and end_date as today's date
13
+ end_date = datetime.today()
14
+ start_date = end_date - timedelta(days=60)
15
+ end_date_str = end_date.strftime('%m/%d/%Y')
16
+ start_date_str = start_date.strftime('%m/%d/%Y')
17
+
18
+ # Get billing provider TIN from configuration
19
+ billing_provider_tin = config['MediLink_Config'].get('billing_provider_tin')
20
+
21
+ # Define the list of payer_id's to iterate over
22
+ payer_ids = ['87726'] # Default value
23
+ # Allowed payer id's for UHC
24
+ # payer_ids = ['87726', '03432', '96385', '95467', '86050', '86047', '95378', '06111', '37602']
25
+
26
+ # Initialize the API client
27
+ client = MediLink_API_v3.APIClient()
28
+
29
+ # Function to process and display the data in a compact, tabular format
30
+ def display_claim_summary(claim_summary, payer_id):
31
+ claims = claim_summary.get('claims', [])
32
+
33
+ # Display header
34
+ header = "Payer ID: {} | Start Date: {} | End Date: {}".format(payer_id, start_date_str, end_date_str)
35
+ print(header)
36
+ print("=" * len(header))
37
+
38
+ # Table header
39
+ table_header = "{:<10} | {:<10} | {:<20} | {:<6} | {:<6} | {:<7} | {:<7} | {:<7} | {:<7}".format(
40
+ "Claim #", "Status", "Patient", "Proc.", "Serv.", "Allowed", "Paid", "Pt Resp", "Charged")
41
+ print(table_header)
42
+ print("-" * len(table_header))
43
+
44
+ # Process each claim and display it in a compact format
45
+ claims_dict = {}
46
+ for claim in claims:
47
+ claim_number = claim['claimNumber'] # String: e.g., "29285698"
48
+ claim_status = claim['claimStatus'] # String: e.g., "Finalized"
49
+ patient_first_name = claim['memberInfo']['ptntFn'] # String: e.g., "FRANK"
50
+ patient_last_name = claim['memberInfo']['ptntLn'] # String: e.g., "LOHR"
51
+ processed_date = claim['claimSummary']['processedDt'] # String (Date in "MM/DD/YYYY" format): e.g., "06/10/2024"
52
+ first_service_date = claim['claimSummary']['firstSrvcDt'] # String (Date in "MM/DD/YYYY" format): e.g., "05/13/2024"
53
+ total_charged_amount = claim['claimSummary']['totalChargedAmt'] # String (Decimal as String): e.g., "450.00"
54
+ total_allowed_amount = claim['claimSummary']['totalAllowdAmt'] # String (Decimal as String): e.g., "108.95"
55
+ total_paid_amount = claim['claimSummary']['totalPaidAmt'] # String (Decimal as String): e.g., "106.78"
56
+ total_patient_responsibility_amount = claim['claimSummary']['totalPtntRespAmt'] # String (Decimal as String): e.g., "0.00"
57
+
58
+ patient_name = "{} {}".format(patient_first_name, patient_last_name)
59
+
60
+ # Store claims in a dictionary to handle duplicate claim numbers
61
+ if claim_number not in claims_dict:
62
+ claims_dict[claim_number] = []
63
+ claims_dict[claim_number].append({
64
+ 'claim_status': claim_status,
65
+ 'patient_name': patient_name,
66
+ 'processed_date': processed_date,
67
+ 'first_service_date': first_service_date,
68
+ 'total_charged_amount': total_charged_amount,
69
+ 'total_allowed_amount': total_allowed_amount,
70
+ 'total_paid_amount': total_paid_amount,
71
+ 'total_patient_responsibility_amount': total_patient_responsibility_amount,
72
+ 'claim_xwalk_data': claim['claimSummary']['clmXWalkData']
73
+ })
74
+
75
+ # Sort claims by first_service_date
76
+ sorted_claims = sorted(claims_dict.items(), key=lambda x: x[1][0]['first_service_date'])
77
+
78
+ for claim_number, claim_data_list in sorted_claims:
79
+ # Check for repeated claim numbers and validate data
80
+ if len(claim_data_list) > 1:
81
+ # Validate data
82
+ unique_claims = {tuple(claim_data.items()) for claim_data in claim_data_list}
83
+ if len(unique_claims) == 1:
84
+ # Data is the same, only print once
85
+ claim_data = claim_data_list[0]
86
+ table_row = "{:<10} | {:<10} | {:<20} | {:<6} | {:<6} | {:<7} | {:<7} | {:<7} | {:<7}".format(
87
+ claim_number, claim_data['claim_status'], claim_data['patient_name'][:20],
88
+ claim_data['processed_date'][:5], claim_data['first_service_date'][:5],
89
+ claim_data['total_allowed_amount'], claim_data['total_paid_amount'],
90
+ claim_data['total_patient_responsibility_amount'], claim_data['total_charged_amount']
91
+ )
92
+ print(table_row)
93
+
94
+ if claim_data['total_paid_amount'] == '0.00':
95
+ for xwalk in claim_data['claim_xwalk_data']:
96
+ clm507Cd = xwalk['clm507Cd'] # String: e.g., "F1"
97
+ clm507CdDesc = xwalk['clm507CdDesc'] # String: e.g., "Finalized/Payment-The claim/line has been paid."
98
+ clm508Cd = xwalk['clm508Cd'] # String: e.g., "104"
99
+ clm508CdDesc = xwalk['clm508CdDesc'] # String: e.g., "Processed according to plan provisions..."
100
+ clmIcnSufxCd = xwalk['clmIcnSufxCd'] # String: e.g., "01"
101
+ print(" 507: {} ({}) | 508: {} ({}) | ICN Suffix: {}".format(clm507Cd, clm507CdDesc, clm508Cd, clm508CdDesc, clmIcnSufxCd))
102
+ else:
103
+ # Data is different, print all
104
+ for claim_data in claim_data_list:
105
+ table_row = "{:<10} | {:<10} | {:<20} | {:<6} | {:<6} | {:<7} | {:<7} | {:<7} | {:<7}".format(
106
+ claim_number, claim_data['claim_status'], claim_data['patient_name'][:20],
107
+ claim_data['processed_date'][:5], claim_data['first_service_date'][:5],
108
+ claim_data['total_allowed_amount'], claim_data['total_paid_amount'],
109
+ claim_data['total_patient_responsibility_amount'], claim_data['total_charged_amount']
110
+ )
111
+ print(table_row + " (Duplicate with different data)")
112
+
113
+ if claim_data['total_paid_amount'] == '0.00':
114
+ for xwalk in claim_data['claim_xwalk_data']:
115
+ clm507Cd = xwalk['clm507Cd'] # String: e.g., "F1"
116
+ clm507CdDesc = xwalk['clm507CdDesc'] # String: e.g., "Finalized/Payment-The claim/line has been paid."
117
+ clm508Cd = xwalk['clm508Cd'] # String: e.g., "104"
118
+ clm508CdDesc = xwalk['clm508CdDesc'] # String: e.g., "Processed according to plan provisions..."
119
+ clmIcnSufxCd = xwalk['clmIcnSufxCd'] # String: e.g., "01"
120
+ print(" 507: {} ({}) | 508: {} ({}) | ICN Suffix: {}".format(clm507Cd, clm507CdDesc, clm508Cd, clm508CdDesc, clmIcnSufxCd))
121
+ else:
122
+ # Only one claim, print normally
123
+ claim_data = claim_data_list[0]
124
+ table_row = "{:<10} | {:<10} | {:<20} | {:<6} | {:<6} | {:<7} | {:<7} | {:<7} | {:<7}".format(
125
+ claim_number, claim_data['claim_status'], claim_data['patient_name'][:20],
126
+ claim_data['processed_date'][:5], claim_data['first_service_date'][:5],
127
+ claim_data['total_allowed_amount'], claim_data['total_paid_amount'],
128
+ claim_data['total_patient_responsibility_amount'], claim_data['total_charged_amount']
129
+ )
130
+ print(table_row)
131
+
132
+ if claim_data['total_paid_amount'] == '0.00':
133
+ for xwalk in claim_data['claim_xwalk_data']:
134
+ clm507Cd = xwalk['clm507Cd'] # String: e.g., "F1"
135
+ clm507CdDesc = xwalk['clm507CdDesc'] # String: e.g., "Finalized/Payment-The claim/line has been paid."
136
+ clm508Cd = xwalk['clm508Cd'] # String: e.g., "104"
137
+ clm508CdDesc = xwalk['clm508CdDesc'] # String: e.g., "Processed according to plan provisions..."
138
+ clmIcnSufxCd = xwalk['clmIcnSufxCd'] # String: e.g., "01"
139
+ print(" 507: {} ({}) | 508: {} ({}) | ICN Suffix: {}".format(clm507Cd, clm507CdDesc, clm508Cd, clm508CdDesc, clmIcnSufxCd))
140
+
141
+ # Loop through each payer_id and call the API, then display the claim summary
142
+ for payer_id in payer_ids:
143
+ claim_summary = MediLink_API_v3.get_claim_summary_by_provider(client, billing_provider_tin, start_date_str, end_date_str, payer_id=payer_id)
144
+ display_claim_summary(claim_summary, payer_id)
@@ -5,18 +5,19 @@ from datetime import datetime
5
5
  from collections import OrderedDict
6
6
  import sys
7
7
  import platform
8
+ import yaml
8
9
 
9
10
  """
10
11
  This function should be generalizable to have a initialization script over all the Medi* functions
11
12
  """
12
13
  def load_configuration(config_path=os.path.join(os.path.dirname(__file__), '..', 'json', 'config.json'), crosswalk_path=os.path.join(os.path.dirname(__file__), '..', 'json', 'crosswalk.json')):
13
14
  """
14
- Loads endpoint configuration, credentials, and other settings from JSON files.
15
+ Loads endpoint configuration, credentials, and other settings from JSON or YAML files.
15
16
 
16
17
  Returns: A tuple containing dictionaries with configuration settings for the main config and crosswalk.
17
18
  """
18
19
  # TODO (Low Config Upgrade) The Medicare / Private differentiator flag probably needs to be pulled or passed to this.
19
- # BUG (HARDCODE) FOR NOW:
20
+ # BUG Hardcode sucks.
20
21
  # Detect the operating system
21
22
  if platform.system() == 'Windows' and platform.release() == 'XP':
22
23
  # Use F: paths for Windows XP
@@ -29,10 +30,15 @@ def load_configuration(config_path=os.path.join(os.path.dirname(__file__), '..',
29
30
 
30
31
  try:
31
32
  with open(config_path, 'r') as config_file:
32
- config = json.load(config_file, object_pairs_hook=OrderedDict)
33
+ if config_path.endswith('.yaml') or config_path.endswith('.yml'):
34
+ config = yaml.safe_load(config_file)
35
+ elif config_path.endswith('.json'):
36
+ config = json.load(config_file, object_pairs_hook=OrderedDict)
37
+ else:
38
+ raise ValueError("Unsupported configuration format.")
39
+
33
40
  if 'MediLink_Config' not in config:
34
41
  raise KeyError("MediLink_Config key is missing from the loaded configuration.")
35
- # MediLink_config = config['MediLink_Config']
36
42
 
37
43
  with open(crosswalk_path, 'r') as crosswalk_file:
38
44
  crosswalk = json.load(crosswalk_file)
@@ -40,12 +46,12 @@ def load_configuration(config_path=os.path.join(os.path.dirname(__file__), '..',
40
46
  return config, crosswalk
41
47
  except ValueError as e:
42
48
  if isinstance(e, UnicodeDecodeError):
43
- print("Error decoding JSON file: {}".format(e))
49
+ print("Error decoding file: {}".format(e))
44
50
  else:
45
- print("Error parsing JSON file: {}".format(e))
51
+ print("Error parsing file: {}".format(e))
46
52
  sys.exit(1) # Exit the script due to a critical error in configuration loading
47
53
  except FileNotFoundError:
48
- print("One or both JSON files not found. Config: {}, Crosswalk: {}".format(config_path, crosswalk_path))
54
+ print("One or both configuration files not found. Config: {}, Crosswalk: {}".format(config_path, crosswalk_path))
49
55
  sys.exit(1) # Exit the script due to a critical error in configuration loading
50
56
  except KeyError as e:
51
57
  print("Critical configuration is missing: {}".format(e))