123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- #!/usr/bin/env python
- """
- (c) 2019 EDI Parser Toolkit,
- Health Information Privacy Lab, Vanderbilt University Medical Center
- Steve L. Nyemba <steve.l.nyemba@vanderbilt.edu>
- Khanhly Nguyen <khanhly.t.nguyen@gmail.com>
- This code is intended to process and parse healthcare x12 837 (claims) and x12 835 (remittances) into human readable JSON format.
- The claims/outpout can be forwarded to a NoSQL Data store like couchdb and mongodb
- Usage :
- Commandline :
- # parse {x12}
- healthcare-io parse <x12_folder>
- # export {x12}
- healthcare-io export
- -
- Embedded :
- """
- # import healthcareio
- import typer
- from typing import Optional
- from typing_extensions import Annotated
- import uuid
- import os
- import meta
- import json
- import time
- from healthcareio import x12
- from healthcareio.x12.parser import X12Parser
- import requests
- import pandas as pd
- import numpy as np
- # import healthcareio
- # import healthcareio.x12.util
- # from healthcareio.x12.parser import X12Parser
- app = typer.Typer()
- CONFIG_FOLDER = os.sep.join([os.environ['HOME'],'.healthcareio'])
- HOST = "https://healthcareio.the-phi.com" if 'PARSER_HOST_URL' not in os.environ else os.environ['PARSER_HOST_URL']
- @app.command(name='init')
- def config(email:str,provider:str='sqlite',auth_file:str=None) :
- """\b
- Generate configuration file needed with default data store. For supported data-store providers visit https://hiplab.mc.vanderbilt.edu/git/hiplab/data-transport.git
-
- :email your email
-
- :provider data store provider (visit https://hiplab.mc.vanderbilt.edu/git/hiplab/data-transport.git)
- """
- _db = "healthcareio"
- global CONFIG_FOLDER
- # _PATH = os.sep.join([os.environ['HOME'],'.healthcareio'])
-
- if not os.path.exists(CONFIG_FOLDER) :
- os.mkdir(CONFIG_FOLDER)
-
- #
- # NOTE:
- # if a provider is setup as an environment variable, we override the parameter
- # This is designed for developement and containers
- #
- if 'X12_DATABASE' in os.environ :
- provider = os.environ['X12_DATABASE']
- if provider in ['sqlite','sqlite3'] :
- _db = os.sep.join([CONFIG_FOLDER,_db+'.db3'])
- _config = {
- "store":{
- "provider":provider,"database":_db,"context":"write"
- },
- "plugins":None,
- "system":{
- "uid":str(uuid.uuid4()),
- "email":email,
- "version":meta.__version__,
- "copyright":meta.__author__
- }
- }
- if auth_file and os.path.exists(auth_file) and provider not in ['sqlite','sqlite3'] :
- f = open(auth_file)
- _auth = json.loads(f.read())
- f.close()
- _config['store'] = dict(_config['store'],**_auth)
- #
- # Let create or retrieve a user's key/token to make sure he/she has access to features they need
- # This would also allow us to allow the users to be informed of new versions
- #
- try:
- global HOST
- # HOST = "https://healthcareio.the-phi.com" if 'PARSER_HOST_URL' not in os.environ else os.environ['PARSER_HOST']
- url = f"{HOST}/api/users/signup"
- _body = {"email":email,"version":meta.__version__}
- _headers = {"content-type":"application/json"}
- resp = requests.post(url,headers=_headers,data=json.dumps(_body))
- if resp.ok :
- _config['system'] = dict(_config['system'],**resp.json())
- except Exception as e:
- print (e)
- pass
- # store this on disk
- f = open(os.sep.join([CONFIG_FOLDER,'config.json']),'w')
- f.write(json.dumps(_config))
- f.close()
- _msg = f"""
- Thank you for considering using our {{x12}} parser verion {meta.__version__}
- The generatted configuration file found at {CONFIG_FOLDER}
- The database provider is {provider}
- visit {HOST} to learn more about the features,
-
- """
- print (_msg)
- @app.command(name='about')
- def copyright():
- f"""
- This function will return information about the {meta.__name__}
- """
- for note in [meta.__name__,meta.__author__,meta.__license__]:
- print (note)
- pass
- @app.command()
- def parse (claim_folder:str,plugin_folder:str = None,config_path:str = None):
- """
- This function will parse 837 and or 835 claims given a location of parsing given claim folder and/or plugin folder.
-
- plugin_folder folder containing user defined plugins (default are loaded)
-
- config_path default configuration path
- """
-
- _plugins,_parents = x12.plugins.instance(path=plugin_folder)
- _files = x12.util.file.Location.get(path=claim_folder,chunks=10)
- _path = config_path if config_path else os.sep.join([CONFIG_FOLDER,'config.json'])
-
- if os.path.exists(_path) :
- f = open(_path)
- _config = json.loads(f.read())
- f.close()
- _store = _config['store']
- # # print (len(_files))
- jobs = []
- for _chunks in _files:
- pthread = X12Parser(plugins=_plugins,parents=_parents,files=_chunks, store=_store)
- pthread.start()
- jobs.append(pthread)
- while jobs :
- jobs = [pthread for pthread in jobs if pthread.is_alive()]
- time.sleep(1)
- # pass
- # else:
- # pass
- print ()
- print (" PARSED ")
- print ("...................... FINISHED .........................")
- #
- #
- @app.command()
- def check():
- """
- This function checks for the version running against the current version
- """
- _info = [meta.__version__,None]
- url = f'{HOST}/api/store/version'
- try:
- resp= requests.post(url)
- _info[1] = resp.text if resp.status_code == 200 else "NA"
- except Exception as e:
- _info[1] = "NA"
- pass
- if _info[1] == "NA" :
- _msg = "Unavailable server (unreachable)"
- else:
- _msg = ""
- print ()
- _info =pd.DataFrame(_info,columns=["versions"],index=["Yours","Current"])
- print (_info)
- print (_msg)
- @app.command(name="export-schema")
- def export_schema (file_type:str):
- """
- This function will display the schema in JSON format of a given file/type
- """
- _plugins,_parents = x12.plugins.instance()
- if file_type not in ['835','837'] and file_type in ['claims','remits']:
- file_type = '835' if file_type == 'remits' else '837'
- _template = x12.publish.build(x12=file_type,plugins=_plugins)
- print ( json.dumps(_template))
- @app.command(name="export")
- def publish (file_type:str,path:str):
- """
- This function will export to a different database
- file_type values are either claims or remits
-
- path path to export configuration (data transport file)
- file_type claims or remits (835 or 837)
- """
- _type = None
- if file_type.strip() in ['837','claims'] :
- _type = 'claims'
- _x12 = '837'
- elif file_type.strip() in ['835','remits']:
- _type = 'remits'
- _x12 = '835'
- if _type :
- _store = {'source':os.sep.join([CONFIG_FOLDER,'config.json']),'target':path}
- for _key in _store :
- f = open(_store[_key])
- _store[_key] = json.loads(f.read())
- f.close()
- _store['source'] = _store['source']['store']
-
- _plugins,_parents = x12.plugins.instance()
- x12.publish.init(plugins=_plugins,x12=_x12,store=_store)
- else:
- print ("Can not determine type, (837 or 835)")
- print ()
- print (" EXPORT ")
- print ("...................... FINISHED .........................")
-
-
- if __name__ == '__main__' :
-
- app()
|