medicafe 0.250813.2__py3-none-any.whl → 0.250814.3__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.bat +1 -1
- MediBot/MediBot.py +1 -1
- MediBot/MediBot_Preprocessor_lib.py +21 -5
- MediBot/MediBot_UI.py +13 -1
- MediBot/__init__.py +1 -1
- MediBot/update_medicafe.py +69 -7
- MediCafe/__init__.py +1 -1
- MediLink/__init__.py +1 -1
- {medicafe-0.250813.2.dist-info → medicafe-0.250814.3.dist-info}/METADATA +1 -1
- {medicafe-0.250813.2.dist-info → medicafe-0.250814.3.dist-info}/RECORD +14 -27
- MediBot/MediPost.py +0 -5
- MediBot/PDF_to_CSV_Cleaner.py +0 -211
- MediLink/MediLink.py +0 -623
- MediLink/MediLink_277_decoder.py +0 -92
- MediLink/MediLink_API_v2.py +0 -176
- MediLink/MediLink_API_v3.py +0 -910
- MediLink/MediLink_APIs.py +0 -138
- MediLink/MediLink_ConfigLoader.py +0 -87
- MediLink/MediLink_ERA_decoder.py +0 -192
- MediLink/MediLink_GraphQL.py +0 -445
- MediLink/MediLink_StatusCheck.py +0 -0
- MediLink/MediLink_api_utils.py +0 -305
- MediLink/MediLink_batch.bat +0 -7
- {medicafe-0.250813.2.dist-info → medicafe-0.250814.3.dist-info}/LICENSE +0 -0
- {medicafe-0.250813.2.dist-info → medicafe-0.250814.3.dist-info}/WHEEL +0 -0
- {medicafe-0.250813.2.dist-info → medicafe-0.250814.3.dist-info}/entry_points.txt +0 -0
- {medicafe-0.250813.2.dist-info → medicafe-0.250814.3.dist-info}/top_level.txt +0 -0
MediLink/MediLink_277_decoder.py
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
import csv
|
2
|
-
import os
|
3
|
-
import sys
|
4
|
-
|
5
|
-
"""
|
6
|
-
This script processes a 277 healthcare claim status response file, extracting and structuring key information
|
7
|
-
about each claim into a CSV format. The goal is to interpret acknowledgment returns and provide a readable receipt
|
8
|
-
of claim statuses for further analysis or record-keeping.
|
9
|
-
|
10
|
-
Extracted fields and their sources from the 277 transaction set include:
|
11
|
-
- Clearing House: Extracted from 'NM1' segment where entity identifier code is '41' (payer) as the clearinghouse or payer name.
|
12
|
-
- Received Date: Extracted from the 'DTP' segment with qualifier '050' indicating the date claim information was received.
|
13
|
-
- Claim Status Tracking #: Extracted from the 'TRN' segment, representing a unique identifier used to track the claim.
|
14
|
-
- Billed Amount: Extracted from the 'AMT' segment with qualifier 'YU' representing the total billed amount.
|
15
|
-
- Date of Service: Extracted from the 'DTP' segment with qualifier '472', indicating the date services were rendered.
|
16
|
-
- Last and First Name: Extracted from 'NM1' segment where entity identifier is 'QC' (patient) to obtain patient's last and first names.
|
17
|
-
- Acknowledged Amount: Extracted from the 'STC' segment, specifically the monetary amount acknowledged.
|
18
|
-
- Status: Extracted from the 'STC' segment, indicating the processing status of the claim.
|
19
|
-
|
20
|
-
Each record corresponds to a single claim, and the script consolidates these records from the raw 277 file into a structured CSV file.
|
21
|
-
The CSV output contains headers corresponding to the above fields for ease of review and use in subsequent processes.
|
22
|
-
|
23
|
-
Prerequisites:
|
24
|
-
- Python 3.x
|
25
|
-
- Access to a filesystem for reading input files and writing output CSV files.
|
26
|
-
|
27
|
-
Usage:
|
28
|
-
The script requires the path to the 277 file as input and specifies an output directory for the CSV files.
|
29
|
-
Example command-line usage:
|
30
|
-
python3 MediLink_277_decoder.py input_file.txt output_directory
|
31
|
-
"""
|
32
|
-
|
33
|
-
def parse_277_content(content):
|
34
|
-
segments = content.split('~')
|
35
|
-
records = []
|
36
|
-
current_record = {}
|
37
|
-
for segment in segments:
|
38
|
-
parts = segment.split('*')
|
39
|
-
if parts[0] == 'HL':
|
40
|
-
if current_record:
|
41
|
-
records.append(current_record)
|
42
|
-
current_record = {}
|
43
|
-
elif parts[0] == 'NM1':
|
44
|
-
if parts[1] == 'QC': # Patient information
|
45
|
-
current_record['Last'] = parts[3]
|
46
|
-
current_record['First'] = parts[4]
|
47
|
-
elif parts[1] == '41': # Payer information
|
48
|
-
current_record['Clearing House'] = parts[3]
|
49
|
-
elif parts[0] == 'TRN':
|
50
|
-
current_record['Claim Status Tracking #'] = parts[2]
|
51
|
-
elif parts[0] == 'STC':
|
52
|
-
current_record['Status'] = parts[1]
|
53
|
-
current_record['Acknowledged Amt'] = parts[4]
|
54
|
-
elif parts[0] == 'DTP':
|
55
|
-
if parts[1] == '472': # Service date
|
56
|
-
current_record['Date of Service'] = parts[3]
|
57
|
-
elif parts[1] == '050': # Received date
|
58
|
-
current_record['Received Date'] = parts[3]
|
59
|
-
elif parts[0] == 'AMT':
|
60
|
-
if parts[1] == 'YU':
|
61
|
-
current_record['Billed Amt'] = parts[2]
|
62
|
-
|
63
|
-
if current_record:
|
64
|
-
records.append(current_record)
|
65
|
-
|
66
|
-
return records
|
67
|
-
|
68
|
-
def write_records_to_csv(records, output_file_path):
|
69
|
-
with open(output_file_path, 'w', newline='') as csvfile:
|
70
|
-
fieldnames = ['Clearing House', 'Received Date', 'Claim Status Tracking #', 'Billed Amt', 'Date of Service', 'Last', 'First', 'Acknowledged Amt', 'Status']
|
71
|
-
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
72
|
-
writer.writeheader()
|
73
|
-
for record in records:
|
74
|
-
writer.writerow(record)
|
75
|
-
|
76
|
-
def main(file_path, output_directory):
|
77
|
-
if not os.path.exists(output_directory):
|
78
|
-
os.makedirs(output_directory)
|
79
|
-
|
80
|
-
output_file_path = os.path.join(output_directory, os.path.basename(file_path) + '_decoded.csv')
|
81
|
-
|
82
|
-
with open(file_path, 'r') as file:
|
83
|
-
content = file.read().replace('\n', '')
|
84
|
-
|
85
|
-
records = parse_277_content(content)
|
86
|
-
write_records_to_csv(records, output_file_path)
|
87
|
-
print("Decoded data written to {}".format(output_file_path))
|
88
|
-
|
89
|
-
if __name__ == "__main__":
|
90
|
-
file_path = sys.argv[1]
|
91
|
-
output_directory = 'output'
|
92
|
-
main(file_path, output_directory)
|
MediLink/MediLink_API_v2.py
DELETED
@@ -1,176 +0,0 @@
|
|
1
|
-
# Unused archive backup. This has been superceded by API_v3
|
2
|
-
|
3
|
-
import time
|
4
|
-
import requests
|
5
|
-
|
6
|
-
# Importing configuration loader
|
7
|
-
try:
|
8
|
-
from MediLink import MediLink_ConfigLoader
|
9
|
-
except ImportError:
|
10
|
-
import MediLink_ConfigLoader
|
11
|
-
|
12
|
-
# Class for handling API calls
|
13
|
-
class APIClient:
|
14
|
-
def __init__(self):
|
15
|
-
# Load configuration
|
16
|
-
self.config, _ = MediLink_ConfigLoader.load_configuration()
|
17
|
-
# Initialize token cache
|
18
|
-
self.token_cache = {}
|
19
|
-
|
20
|
-
# Method to get access token
|
21
|
-
def get_access_token(self, endpoint_name):
|
22
|
-
# Retrieve endpoint configuration
|
23
|
-
endpoint_config = self.config['MediLink_Config']['endpoints'][endpoint_name]
|
24
|
-
current_time = time.time()
|
25
|
-
|
26
|
-
# Check if token is cached and still valid
|
27
|
-
if endpoint_name in self.token_cache:
|
28
|
-
cached_token = self.token_cache[endpoint_name]
|
29
|
-
if cached_token['expires_at'] > current_time:
|
30
|
-
return cached_token['access_token']
|
31
|
-
|
32
|
-
# Prepare data for token request
|
33
|
-
data = {
|
34
|
-
'grant_type': 'client_credentials',
|
35
|
-
'client_id': endpoint_config['client_id'],
|
36
|
-
'client_secret': endpoint_config['client_secret'],
|
37
|
-
'scope': 'hipaa'
|
38
|
-
}
|
39
|
-
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
|
40
|
-
|
41
|
-
# Request token
|
42
|
-
response = requests.post(endpoint_config['token_url'], headers=headers, data=data)
|
43
|
-
response.raise_for_status()
|
44
|
-
token_data = response.json()
|
45
|
-
access_token = token_data['access_token']
|
46
|
-
expires_in = token_data.get('expires_in', 3600)
|
47
|
-
|
48
|
-
# Cache token with expiration time adjusted
|
49
|
-
self.token_cache[endpoint_name] = {
|
50
|
-
'access_token': access_token,
|
51
|
-
'expires_at': current_time + expires_in - 120
|
52
|
-
}
|
53
|
-
return access_token
|
54
|
-
|
55
|
-
# Method for making API calls
|
56
|
-
def make_api_call(self, endpoint_name, call_type, url_extension="", params=None, data=None):
|
57
|
-
# Retrieve endpoint configuration
|
58
|
-
endpoint_config = self.config['MediLink_Config']['endpoints'][endpoint_name]
|
59
|
-
# Get access token
|
60
|
-
token = self.get_access_token(endpoint_name)
|
61
|
-
headers = {'Authorization': 'Bearer {}'.format(token), 'Accept': 'application/json'}
|
62
|
-
|
63
|
-
# Construct full URL
|
64
|
-
url = endpoint_config['api_url'] + url_extension
|
65
|
-
|
66
|
-
# Make appropriate type of call
|
67
|
-
if call_type == 'GET':
|
68
|
-
response = requests.get(url, headers=headers, params=params)
|
69
|
-
elif call_type == 'POST':
|
70
|
-
headers['Content-Type'] = 'application/json'
|
71
|
-
response = requests.post(url, headers=headers, json=data)
|
72
|
-
elif call_type == 'DELETE':
|
73
|
-
response = requests.delete(url, headers=headers)
|
74
|
-
else:
|
75
|
-
raise ValueError("Unsupported call type")
|
76
|
-
|
77
|
-
if response.status_code >= 400:
|
78
|
-
print("Error {}: {}".format(response.status_code, response.text))
|
79
|
-
response.raise_for_status()
|
80
|
-
|
81
|
-
return response.json()
|
82
|
-
|
83
|
-
# Method for creating coverage
|
84
|
-
def create_coverage(self, endpoint_name, patient_info):
|
85
|
-
return self.make_api_call(endpoint_name, 'POST', url_extension="/coverages", data=patient_info)
|
86
|
-
|
87
|
-
# Method for getting all coverages
|
88
|
-
def get_coverages(self, endpoint_name, params=None):
|
89
|
-
return self.make_api_call(endpoint_name, 'GET', url_extension="/coverages", params=params)
|
90
|
-
|
91
|
-
# Method for getting coverage by ID
|
92
|
-
def get_coverage_by_id(self, endpoint_name, coverage_id):
|
93
|
-
return self.make_api_call(endpoint_name, 'GET', url_extension="/coverages/{}".format(coverage_id))
|
94
|
-
|
95
|
-
# Method for deleting coverage by ID
|
96
|
-
def delete_coverage_by_id(self, endpoint_name, coverage_id):
|
97
|
-
return self.make_api_call(endpoint_name, 'DELETE', url_extension="/coverages/{}".format(coverage_id))
|
98
|
-
|
99
|
-
# Method for getting payer list
|
100
|
-
def get_payer_list(self, endpoint_name, params=None):
|
101
|
-
return self.make_api_call(endpoint_name, 'GET', url_extension="/availity-payer-list", params=params)
|
102
|
-
|
103
|
-
# Function to fetch payer name from API
|
104
|
-
def fetch_payer_name_from_api(payer_id, config, primary_endpoint='AVAILITY'):
|
105
|
-
client = APIClient()
|
106
|
-
|
107
|
-
# Step 1: Reload configuration for safety (This should be able to be replaced by APIClient())
|
108
|
-
config, _ = MediLink_ConfigLoader.load_configuration()
|
109
|
-
|
110
|
-
# Step 2: Check if the primary endpoint is specified and is valid
|
111
|
-
# (these validity checks will need to be incorporated into the main functionality)
|
112
|
-
endpoints = config['MediLink_Config']['endpoints']
|
113
|
-
if primary_endpoint and primary_endpoint in endpoints:
|
114
|
-
endpoint_order = [primary_endpoint] + [endpoint for endpoint in endpoints if endpoint != primary_endpoint]
|
115
|
-
else:
|
116
|
-
endpoint_order = list(endpoints.keys())
|
117
|
-
|
118
|
-
# Step 3: Iterate through available endpoints in specified order
|
119
|
-
for endpoint_name in endpoint_order:
|
120
|
-
endpoint_config = endpoints[endpoint_name]
|
121
|
-
if not all(key in endpoint_config for key in ['token_url', 'client_id', 'client_secret']):
|
122
|
-
MediLink_ConfigLoader.log("Skipping {} due to missing API keys.".format(endpoint_name), config, level="WARNING")
|
123
|
-
continue
|
124
|
-
|
125
|
-
try:
|
126
|
-
response = client.get_payer_list(endpoint_name, params={'payerId': payer_id})
|
127
|
-
if 'payers' in response and response['payers']:
|
128
|
-
payer = response['payers'][0]
|
129
|
-
payer_name = payer.get('displayName') or payer.get('name')
|
130
|
-
|
131
|
-
MediLink_ConfigLoader.log("Successfully found payer at {} for ID {}: {}".format(endpoint_name, payer_id, payer_name), config, level="INFO")
|
132
|
-
return payer_name
|
133
|
-
else:
|
134
|
-
MediLink_ConfigLoader.log("No payer found at {} for ID: {}. Trying next available endpoint.".format(endpoint_name, payer_id), config, level="INFO")
|
135
|
-
except requests.RequestException as e:
|
136
|
-
MediLink_ConfigLoader.log("API call failed at {} for Payer ID '{}': {}".format(endpoint_name, payer_id, str(e)), config, level="ERROR")
|
137
|
-
|
138
|
-
error_message = "All endpoints exhausted for Payer ID {}.".format(payer_id)
|
139
|
-
MediLink_ConfigLoader.log(error_message, config, level="CRITICAL")
|
140
|
-
raise ValueError(error_message)
|
141
|
-
|
142
|
-
# Example usage
|
143
|
-
if __name__ == "__main__":
|
144
|
-
client = APIClient()
|
145
|
-
try:
|
146
|
-
# Fetch and print payer name
|
147
|
-
payer_name = fetch_payer_name_from_api("11347", 'config.yaml')
|
148
|
-
print("Payer Name: {}".format(payer_name))
|
149
|
-
|
150
|
-
# Example patient info
|
151
|
-
patient_info = {
|
152
|
-
"policyNumber": "12345",
|
153
|
-
"name": "John Doe",
|
154
|
-
"dob": "1980-01-01"
|
155
|
-
}
|
156
|
-
# Create coverage and print response
|
157
|
-
response = client.create_coverage('AVAILITY', patient_info)
|
158
|
-
print("Create Coverage Response: {}".format(response))
|
159
|
-
|
160
|
-
# Get all coverages and print response
|
161
|
-
response = client.get_coverages('AVAILITY')
|
162
|
-
print("All Coverages: {}".format(response))
|
163
|
-
|
164
|
-
# Example coverage ID
|
165
|
-
coverage_id = "some-coverage-id"
|
166
|
-
# Get coverage by ID and print response
|
167
|
-
response = client.get_coverage_by_id('AVAILITY', coverage_id)
|
168
|
-
print("Coverage by ID: {}".format(response))
|
169
|
-
|
170
|
-
# Delete coverage by ID and print response
|
171
|
-
response = client.delete_coverage_by_id('AVAILITY', coverage_id)
|
172
|
-
print("Delete Coverage Response: {}".format(response))
|
173
|
-
|
174
|
-
except Exception as e:
|
175
|
-
# Print error if any
|
176
|
-
print("Error: {}".format(e))
|