Merge remote-tracking branch 'origin/dev'

master
Steve L. Nyemba 4 years ago
commit f25a5831c0

@ -22,16 +22,26 @@ We wrote this frame to be used in both command line or as a library within in yo
pip install --upgrade git+https://hiplab.mc.vanderbilt.edu/git/lab/parse-edi.git pip install --upgrade git+https://hiplab.mc.vanderbilt.edu/git/lab/parse-edi.git
## Usage ## Usage
**cli :** **cli :**
1. signup to get parsing configuration 1. signup to get parsing configuration
The parser is driven by a configuration file that specifies fields to parse and how to parse them. You need by signing up, to get a copy of the configuration file.
healthcare-io.py --signup <email> [--store <mongo|sqlite>] healthcare-io.py --signup <email> [--store <mongo|sqlite>]
2. parsing claims in a folder
healthcare-io.py --parse <claims|remits> --folder <path> [--batch <n>] [--resume] 2. check version
Occasionally the attributes in the configuration file may change, This function will determine if there is a new version available.
healthcare-io.py --check-update
3. parsing data in a folder
The parser will recursively traverse a directory with claims and or remittances
healthcare-io.py --parse --folder <path> [--batch <n>] [--resume]
with : with :
--parse tells the engine what to parse claims or remits --parse tells the engine what to parse claims or remits
@ -39,12 +49,42 @@ We wrote this frame to be used in both command line or as a library within in yo
--batch number of processes to spawn to parse the files --batch number of processes to spawn to parse the files
--resume tells the parser to resume parsing --resume tells the parser to resume parsing
if all files weren't processed or new files were added into the folder if all files weren't processed or new files were added into the folder
3. dashboard
4. export data to a relational data-store
There is a built-in dashboard that has displays descriptive analytics in a web browser
The parser will export data into other data-stores as a relational tables allowing users to construct views to support a variety of studies.
healthcare-io.py --server <port> [--context <name>]
healthcare-io.py --export <835|837> --config <path-export.json>
with:
--config configuration to support data-store
The configuration file needed to implement export is modelled after the following template:
{
"provider":"<postgresql|redshift|mysql|mariadb>",
"db":"mydatabase",
[
"host":"server-name","port":5432,
"user":"me","password":"!@#z4qm",
"schema":"target-schema"
]
}
**parameters:**
provider postgresql,redshift,mysql or mariadb (supported providers)
db name of the database
**optional:**
schema name of the target schema. If not provided we will assume the default
host host of the database. If not provided assuming localhost
port port value of the database if not provided the default will be used
user database user name. If not provided we assume security settings to trust
password password of database user. If not set we assume security settings to trust
**Embedded in Code :** **Embedded in Code :**
The Healthcare/IO **parser** can be used within your code base as a library and handle storing data in a data store of choice The Healthcare/IO **parser** can be used within your code base as a library and handle storing data in a data store of choice

@ -1,4 +1,8 @@
FROM ubuntu:bionic-20200403 #
# Let us create an image for healthcareio
# The image will contain the {X12} Parser and the
# FROM ubuntu:bionic-20200403
FROM ubuntu:focal
RUN ["apt","update","--fix-missing"] RUN ["apt","update","--fix-missing"]
RUN ["apt-get","upgrade","-y"] RUN ["apt-get","upgrade","-y"]
@ -6,9 +10,22 @@ RUN ["apt-get","-y","install","apt-utils"]
RUN ["apt","update","--fix-missing"] RUN ["apt","update","--fix-missing"]
RUN ["apt-get","upgrade","-y"] RUN ["apt-get","upgrade","-y"]
RUN ["apt-get","install","-y","sqlite3","sqlite3-pcre","libsqlite3-dev","python3-dev","python3","python3-pip","git","python3-virtualenv"] RUN ["apt-get","install","-y","mongo","sqlite3","sqlite3-pcre","libsqlite3-dev","python3-dev","python3","python3-pip","git","python3-virtualenv","wget"]
# #
# #
RUN ["pip3","install","--upgrade","pip"]
# RUN ["pip3","install","git+https://healthcare.the-phi.com/git/code/parser.git","botocore"]
USER health-user USER health-user
#
# This volume is where the data will be loaded from (otherwise it is assumed the user will have it in the container somehow)
#
VOLUME ["/data"]
#
# This is the port from which some degree of monitoring can/will happen
EXPOSE 80
# wget https://healthcareio.the-phi.com/git/code/parser.git/bootup.sh
COPY bootup.sh bootup.sh
ENTRYPOINT ["bash","-C"]
CMD ["bootup.sh"]
# VOLUME ["/home/health-user/healthcare-io/","/home-healthuser/.healthcareio"] # VOLUME ["/home/health-user/healthcare-io/","/home-healthuser/.healthcareio"]
# RUN ["pip3","install","git+https://healthcareio.the-phi.com/git"] # RUN ["pip3","install","git+https://healthcareio.the-phi.com/git"]

@ -16,5 +16,9 @@ Usage :
""" """
from healthcareio import analytics from healthcareio import analytics
from healthcareio import server
from healthcareio import export
import healthcareio.x12 as x12 import healthcareio.x12 as x12
import healthcareio.params as params
# from healthcareio import server # from healthcareio import server

@ -11,7 +11,7 @@ import transport
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import re, base64 import re, base64
# from weasyprint import HTML, CSS # from weasyprint import HTML, CSS
COLORS = ["#f79256","#7dcfb6","#fbd1a2","#00b2ca","#1d4e89","#4682B4","#c5c3c6","#4c5c68","#1985a1","#f72585","#7209b7","#3a0ca3","#4361ee","#4cc9f0","#ff595e","#ffca3a","#8ac926","#1982c4","#6a4c93"] COLORS = ["#fbd1a2","#00b2ca","#1d4e89","#4682B4","#c5c3c6","#4c5c68","#1985a1","#f72585","#7209b7","#3a0ca3","#4361ee","#4cc9f0","#ff595e","#ffca3a","#8ac926","#1982c4","#6a4c93"]
class stdev : class stdev :
def __init__(self) : def __init__(self) :
self.values = [] self.values = []
@ -149,11 +149,16 @@ class Apex :
This class will format a data-frame to work with Apex charting engine This class will format a data-frame to work with Apex charting engine
""" """
@staticmethod @staticmethod
def apply(item): def apply(item,theme={'mode':'light','palette':'palette6'}):
pointer = item['chart']['type'] pointer = item['chart']['type']
if hasattr(Apex,pointer) : if hasattr(Apex,pointer) :
pointer = getattr(Apex,pointer) pointer = getattr(Apex,pointer)
options = pointer(item) options = pointer(item)
if 'apex' in options and 'colors' in options['apex'] :
del options['apex']['colors']
if 'apex' in options :
options['apex']['theme'] = theme
options['responsive']= [ options['responsive']= [
{ {
'breakpoint': 1, 'breakpoint': 1,
@ -168,6 +173,18 @@ class Apex :
print ("Oops") print ("Oops")
pass pass
@staticmethod @staticmethod
def radial(item):
df = item['data']
x = item['chart']['axis']['x']
y = item['chart']['axis']['y']
labels = df[y].tolist()
values = [float(np.round(value,2)) for value in df[x].tolist()]
chart = {"type":"radialBar","height":200}
option = {"chart":chart,"series":values,"labels":labels,"plotOptions":{"radialBar":{"hollow":{"size":"70%"}}}}
return {'apex':option}
@staticmethod
def scatter(item): def scatter(item):
options = Apex.spline(item) options = Apex.spline(item)
options['apex']['chart']['type'] = 'scatter' options['apex']['chart']['type'] = 'scatter'
@ -175,7 +192,7 @@ class Apex :
@staticmethod @staticmethod
def scalar(item): def scalar(item):
_df = item['data'] _df = item['data']
print (_df)
name = _df.columns.tolist()[0] name = _df.columns.tolist()[0]
value = _df[name].values.round(2)[0] value = _df[name].values.round(2)[0]
html = '<div class="scalar"><div class="value">:value</div><div class="label">:label</div></div>' html = '<div class="scalar"><div class="value">:value</div><div class="label">:label</div></div>'
@ -235,16 +252,17 @@ class Apex :
@TODO: alias this with bar (!= column) @TODO: alias this with bar (!= column)
""" """
df = item['data'] df = item['data']
N = df.shape[0] if df.shape[0] < 10 else 10 N = df.shape[0] if df.shape[0] < 10 else 10
axis = item['chart']['axis'] axis = item['chart']['axis']
y = axis['y'] y = axis['y']
if type(y) == list : if type(y) == list :
y = y[0] y = y[0]
axis['x'] = [axis['x']] if type(axis['x']) != list else axis['x'] axis['x'] = [axis['x']] if type(axis['x']) != list else axis['x']
if not set(axis['x']) & set(df.columns.tolist()) : # if not set(axis['x']) & set(df.columns.tolist()) :
print (set(axis['x']) & set(df.columns.tolist())) # print (set(axis['x']) & set(df.columns.tolist()))
print (axis['x']) # print (axis['x'])
print (df.columns) # print (df.columns)
# df.columns = axis['x'] # df.columns = axis['x']
series = [] series = []
_min=_max = 0 _min=_max = 0
@ -294,7 +312,6 @@ class Apex :
values are x-axis values are x-axis
""" """
df = item['data'] df = item['data']
if df.shape [0]> 1 : if df.shape [0]> 1 :
y_cols,x_cols = item['chart']['axis']['y'],item['chart']['axis']['x'] y_cols,x_cols = item['chart']['axis']['y'],item['chart']['axis']['x']
labels = df[y_cols].values.tolist() labels = df[y_cols].values.tolist()
@ -302,10 +319,11 @@ class Apex :
values = df[x_cols].values.round(2).tolist() values = df[x_cols].values.round(2).tolist()
else: else:
labels = [name.upper().replace('_',' ') for name in df.columns.tolist()] labels = [name.upper().replace('_',' ') for name in df.columns.tolist()]
df = df.astype(float)
values = df.values.round(2).tolist()[0] if df.shape[1] > 1 else df.values.round(2).tolist() values = df.values.round(2).tolist()[0] if df.shape[1] > 1 else df.values.round(2).tolist()
colors = COLORS[:len(values)] colors = COLORS[:len(values)]
options = {"series":values,"colors":colors,"labels":labels,"chart":{"type":"donut"},"plotOptions":{"pie":{"customScale":.8}},"legend":{"position":"right"}} options = {"series":values,"colors":colors,"labels":labels,"dataLabels":{"enabled":True,"style":{"colors":["#000000"]},"dropShadow":{"enabled":False}},"chart":{"type":"donut","width":200},"plotOptions":{"pie":{"customScale":.9}},"legend":{"position":"right"}}
return {"apex":options} return {"apex":options}
pass pass
@ -329,43 +347,117 @@ class engine :
_args['type'] = 'mongo.MongoReader' _args['type'] = 'mongo.MongoReader'
else: else:
_args['type'] = 'disk.SQLiteReader' _args['type'] = 'disk.SQLiteReader'
self.reader = transport.factory.instance(**_args) self.store_config = _args ;
def filter (self,**args):
"""
type: claims or remits
filter optional identifier claims, procedures, taxonomy, ...
"""
_m = {'claim':'837','claims':'837','remits':'835','remit':'835'}
table = _m[ args['type']]
_analytics = self.info[table]
if 'index' in args :
index = int(args['index'])
_analytics = [_analytics[index]]
_info = list(_analytics) #if 'filter' not in args else [item for item in analytics if args['filter'] == item['id']]
# conn = lite.connect(self.store_config['args']['path'],isolation_level=None)
# conn.create_aggregate("stdev",1,stdev)
DB_TYPE = 'mongo' if (type(self.reader) == transport.mongo.MongoReader) else 'sql'
if DB_TYPE == 'mongo' :
self.store_config['args']['doc'] = args['type']
self.reader = transport.factory.instance(**self.store_config)
r = []
for row in _info :
pipeline = row['pipeline']
index = 0
for item in pipeline:
if not item[DB_TYPE] :
continue
query = {DB_TYPE:item[DB_TYPE]}
df = pd.DataFrame(self.reader.read(**query)) #item)
df = df.fillna('N/A')
# item['data'] = df
chart = item['chart']
pipe = {"data":df,"chart":chart}
for key in list(item.keys()) :
if key not in ["chart","data","mongo","sql","couch"] :
pipe[key] = item[key]
r.append(pipe)
self.reader.close()
return {"id":_info[0]['id'],'pipeline':r}
def apply (self,**args) : def apply (self,**args) :
""" """
type: claims or remits type: claims or remits
filter optional identifier claims, procedures, taxonomy, ... filter optional identifier claims, procedures, taxonomy, ...
""" """
_m = {'claim':'837','claims':'837','remits':'835','remit':'835'} _m = {'claim':'837','claims':'837','remits':'835','remit':'835'}
# key = '837' if args['type'] == 'claims' else '835' # key = '837' if args['type'] == 'claims' else '835'
table = _m[ args['type']] table = _m[ args['type']]
analytics = self.info[table]
_analytics = self.info[table]
if 'index' in args : if 'index' in args :
index = int(args['index']) index = int(args['index'])
analytics = [analytics[index]] _analytics = [_analytics[index]]
_info = list(analytics) if 'filter' not in args else [item for item in analytics if args['filter'] == item['id']] _info = list(_analytics) if 'filter' not in args else [item for item in analytics if args['filter'] == item['id']]
# conn = lite.connect(self.store_config['args']['path'],isolation_level=None) # conn = lite.connect(self.store_config['args']['path'],isolation_level=None)
# conn.create_aggregate("stdev",1,stdev) # conn.create_aggregate("stdev",1,stdev)
DB_TYPE = 'mongo' if (type(self.reader) == transport.mongo.MongoReader) else 'sql' #
# @TODO: Find a better way to handle database variance
#
# DB_TYPE = 'mongo' if (type(self.reader) == transport.mongo.MongoReader) else 'sql'
if 'mongo' in self.store_config['type'] :
DB_TYPE='mongo'
else:
DB_TYPE='sql'
self.store_config['args']['table'] = args['type']
self.reader = transport.factory.instance(**self.store_config)
r = [] r = []
for row in _info : for row in _info :
pipeline = row['pipeline']
for item in row['pipeline'] : index = 0
for item in pipeline:
# item['data'] = pd.read_sql(item['sql'],conn) # item['data'] = pd.read_sql(item['sql'],conn)
query = {DB_TYPE:item[DB_TYPE]} # query = {DB_TYPE:item[DB_TYPE]}
item['data'] = self.reader.read(**item) query = item[DB_TYPE]
if not query :
continue
if DB_TYPE == 'sql' :
query = {"sql":query}
item['data'] = self.reader.read(**query) #item)
if 'serialize' in args : if 'serialize' in args :
item['data'] = json.dumps(item['data'].to_dict(orient='record')) if type(item['data']) == pd.DataFrame else item['data'] # item['data'] = json.dumps(item['data'].to_dict(orient='record')) if type(item['data']) == pd.DataFrame else item['data']
item['data'] = json.dumps(item['data'].to_dict('record')) if type(item['data']) == pd.DataFrame else item['data']
else: else:
item['data'] = (pd.DataFrame(item['data'])) item['data'] = (pd.DataFrame(item['data']))
pipeline[index] = item
index += 1
#
#
row['pipeline']= pipeline
# if 'info' in item: # if 'info' in item:
# item['info'] = item['info'].replace(":rows",str(item["data"].shape[0])) # item['info'] = item['info'].replace(":rows",str(item["data"].shape[0]))
# conn.close() # conn.close()
self.reader.close()
return _info return _info
def _html(self,item) : def _html(self,item) :

@ -0,0 +1,37 @@
#
# Let us create an image for healthcareio
# The image will contain the {X12} Parser and the
# FROM ubuntu:bionic-20200403
FROM ubuntu:focal
RUN ["apt-get","update","--fix-missing"]
RUN ["apt-get","upgrade","-y"]
RUN ["apt-get","-y","install","apt-utils"]
RUN ["apt-get","update","--fix-missing"]
RUN ["apt-get","upgrade","-y"]
RUN ["apt-get","install","-y","mongodb","sqlite3","sqlite3-pcre","libsqlite3-dev","python3-dev","python3","python3-pip","git","python3-virtualenv","wget"]
#
#
RUN ["pip3","install","--upgrade","pip"]
RUN ["pip3","install","numpy","pandas","git+https://dev.the-phi.com/git/steve/data-transport","botocore","matplotlib"]
# RUN ["pip3","install","git+https://healthcare.the-phi.com/git/code/parser.git","botocore"]
# RUN ["useradd", "-ms", "/bin/bash", "health-user"]
# USER health-user
#
# This volume is where the data will be loaded from (otherwise it is assumed the user will have it in the container somehow)
#
VOLUME ["/data","/app/healthcareio"]
WORKDIR /app
ENV PYTHONPATH="/app"
#
# This is the port from which some degree of monitoring can/will happen
EXPOSE 80
EXPOSE 27017
# wget https://healthcareio.the-phi.com/git/code/parser.git/bootup.sh
COPY bootup.sh bootup.sh
ENTRYPOINT ["bash","-C"]
CMD ["bootup.sh"]
# VOLUME ["/home/health-user/healthcare-io/","/home-healthuser/.healthcareio"]
# RUN ["pip3","install","git+https://healthcareio.the-phi.com/git"]

@ -0,0 +1,10 @@
set -e
/etc/init.d/mongodb start
cd /app
export
export PYTHONPATH=$PWD
ls
# python3 healthcareio/healthcare-io.py --signup $EMAIL --store mongo
# python3 healthcareio/healthcare-io.py --analytics --port 80 --debug
bash

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

@ -0,0 +1,314 @@
<?xml version="1.0" encoding="UTF-8"?>
<XMI xmi.version="1.2" timestamp="2021-01-11T11:53:03" xmlns:UML="http://schema.omg.org/spec/UML/1.4" verified="false">
<XMI.header>
<XMI.documentation>
<XMI.exporter>umbrello uml modeller http://umbrello.kde.org</XMI.exporter>
<XMI.exporterVersion>1.6.17</XMI.exporterVersion>
<XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>
</XMI.documentation>
<XMI.metamodel xmi.version="1.4" xmi.name="UML" href="UML.xml"/>
</XMI.header>
<XMI.content>
<UML:Model isAbstract="false" isRoot="false" name="UML Model" isLeaf="false" isSpecification="false" xmi.id="m1">
<UML:Namespace.ownedElement>
<UML:Stereotype isAbstract="false" isRoot="false" name="folder" isLeaf="false" visibility="public" isSpecification="false" xmi.id="folder" namespace="m1"/>
<UML:Model isAbstract="false" isRoot="false" name="Logical View" isLeaf="false" visibility="public" isSpecification="false" xmi.id="Logical_View" namespace="m1">
<UML:Namespace.ownedElement>
<UML:Package isAbstract="false" isRoot="false" name="Datatypes" isLeaf="false" visibility="public" stereotype="folder" isSpecification="false" xmi.id="Datatypes" namespace="Logical_View">
<UML:Namespace.ownedElement>
<UML:DataType isAbstract="false" isRoot="false" name="char" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uabvhj07enGME" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="int" isLeaf="false" visibility="public" isSpecification="false" xmi.id="u4OxDbpjlH3pe" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="float" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uDJRPxwaZX3V7" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="double" isLeaf="false" visibility="public" isSpecification="false" xmi.id="usBQivEzmQ1BW" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="bool" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uwRCbX5F7jgLF" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="string" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uzDhYR9iUxXR6" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="unsigned char" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uFh4LzRYE3f5n" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="signed char" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uWGlDG1tsuigz" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="unsigned int" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uCRFY3OMvmsTh" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="signed int" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uzkXa9SjrJK3C" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="short int" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uHr88gSJngOwQ" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="unsigned short int" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uMFI3J7IsMqdx" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="signed short int" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uHnTLssRNvwe9" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="long int" isLeaf="false" visibility="public" isSpecification="false" xmi.id="udr0tadLTTAWz" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="signed long int" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uGiRQT4nooVd3" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="unsigned long int" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uXN2ZkDRs26FV" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="long double" isLeaf="false" visibility="public" isSpecification="false" xmi.id="ueN3MSvcxioDm" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="wchar_t" isLeaf="false" visibility="public" isSpecification="false" xmi.id="u3oTW1v02tom1" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="bigint" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uhsHrB8csHO10" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="bigserial" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uivybGgIE3bD0" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="bit" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uWWi8ci3eh65i" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="bit varying" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uqpjG9tkWEa7X" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="boolean" isLeaf="false" visibility="public" isSpecification="false" xmi.id="u5TSvGJ0WXtUp" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="box" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uGDbLeVMULJkk" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="bytea" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uLGmbFVmIZR5K" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="character varying" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uSnvPt02S7tvb" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="character" isLeaf="false" visibility="public" isSpecification="false" xmi.id="ukmjXUC40LtU7" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="cidr" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uz3Al8mzoS0I3" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="circle" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uyHfbIHPXILpB" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="date" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uL5DOPBGjUyyC" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="decimal" isLeaf="false" visibility="public" isSpecification="false" xmi.id="u6MI7pVV7hXsf" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="double precision" isLeaf="false" visibility="public" isSpecification="false" xmi.id="ujgGh0hthNOjx" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="inet" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uKX78NObRE1fe" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="integer" isLeaf="false" visibility="public" isSpecification="false" xmi.id="ulzNk0Rb91myv" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="interval" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uI220TA6Z0j6n" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="line" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uDrG5vcusdKBM" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="lseg" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uCgYfO6iac2jN" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="macaddr" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uxSn0sOl0rdv1" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="money" isLeaf="false" visibility="public" isSpecification="false" xmi.id="unOpNjlDqyBUV" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="numeric" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uOGQO1PzHG9jT" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="path" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uIYX1EziKvxte" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="point" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uB5Z9Av67TQfu" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="polygon" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uclB4l6uHrYXp" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="real" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uvDJ2b98uJr2k" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="serial" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uoRs9Jh7Jejo2" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="smallint" isLeaf="false" visibility="public" isSpecification="false" xmi.id="u0Uu6RLk1nAgq" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="time without time zone" isLeaf="false" visibility="public" isSpecification="false" xmi.id="u85nOph4JKwlg" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="time with time zone" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uL9aNTx5gdrZz" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="timestamp without time zone" isLeaf="false" visibility="public" isSpecification="false" xmi.id="u4qKd0QA9rWNf" namespace="Datatypes"/>
<UML:DataType isAbstract="false" isRoot="false" name="timestamp with time zone" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uOTQbnbs1N3TF" namespace="Datatypes"/>
</UML:Namespace.ownedElement>
</UML:Package>
</UML:Namespace.ownedElement>
<XMI.extension xmi.extender="umbrello">
<diagrams resolution="96">
<diagram xmi.id="u8KOkLitCdEg4" showattsig="1" localid="-1" snapcsgrid="0" documentation="" name="class diagram" snapgrid="0" showattribassocs="1" isopen="1" linecolor="#ff0000" linewidth="0" showopsig="1" snapy="25" usefillcolor="1" type="1" canvasheight="0" showatts="1" griddotcolor="#d3d3d3" snapx="25" zoom="100" fillcolor="#ffff00" showstereotype="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" textcolor="#000000" showops="1" showpubliconly="0" showscope="1" canvaswidth="0" backgroundcolor="#ffffff" showpackage="1" showgrid="0">
<widgets/>
<messages/>
<associations/>
</diagram>
</diagrams>
</XMI.extension>
</UML:Model>
<UML:Model isAbstract="false" isRoot="false" name="Use Case View" isLeaf="false" visibility="public" isSpecification="false" xmi.id="Use_Case_View" namespace="m1">
<UML:Namespace.ownedElement/>
</UML:Model>
<UML:Model isAbstract="false" isRoot="false" name="Component View" isLeaf="false" visibility="public" isSpecification="false" xmi.id="Component_View" namespace="m1">
<UML:Namespace.ownedElement/>
</UML:Model>
<UML:Model isAbstract="false" isRoot="false" name="Deployment View" isLeaf="false" visibility="public" isSpecification="false" xmi.id="Deployment_View" namespace="m1">
<UML:Namespace.ownedElement/>
</UML:Model>
<UML:Model isAbstract="false" isRoot="false" name="Entity Relationship Model" isLeaf="false" visibility="public" isSpecification="false" xmi.id="Entity_Relationship_Model" namespace="m1">
<UML:Namespace.ownedElement>
<UML:Entity isAbstract="false" isRoot="false" name="adjustments" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uIt8r5rl1o40g" namespace="Entity_Relationship_Model">
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="claim_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uSYVzSUI013SA" namespace="uIt8r5rl1o40g" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="amount" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uTpfrtFZpRhat" namespace="uIt8r5rl1o40g" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="reason" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="ukqfwxa6LykJ0" namespace="uIt8r5rl1o40g" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="quantity" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="u588PxOwyWVln" namespace="uIt8r5rl1o40g" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="_index" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uFD7jRw8vwz8o" namespace="uIt8r5rl1o40g" type="uSnvPt02S7tvb"/>
</UML:Entity>
<UML:Entity isAbstract="false" isRoot="false" name="claims" isLeaf="false" visibility="public" isSpecification="false" xmi.id="u0o6nLeO0fEm7" namespace="Entity_Relationship_Model">
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="claim_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uYDfK8VkY0Uex" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="claim_amount" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="un3xoNxajJ2xm" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="place_of_service" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uwUPYbIyt5p6d" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="is_delayed" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="u74xYiT4G5wyL" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="patient_dob" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="ulgSeuvbWb2IS" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="patient_gender" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="ue7HQl68mupvi" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="provider_code" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="u7ACwVQiy9E9Z" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="provider_ref_id_code" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uiZCcx2if32Rz" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="provider_ref_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="u6YddgnfmpAlc" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="receiver_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uogvUuoceENSP" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="claim_type" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="udh4izR25tLXk" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="submitted_date" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uNawwAMUkVRCI" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="submitted_time" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uRjR66XIKc4Cj" namespace="u0o6nLeO0fEm7" type="uSnvPt02S7tvb"/>
</UML:Entity>
<UML:Entity isAbstract="false" isRoot="false" name="dates" isLeaf="false" visibility="public" isSpecification="false" xmi.id="u9jx6NrYMk8ba" namespace="Entity_Relationship_Model">
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="claim_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uOFiCH5hs2CqD" namespace="u9jx6NrYMk8ba" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="date_value" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uWlHRTJczp2hP" namespace="u9jx6NrYMk8ba" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="date_type" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uJ3UETdwbO2Ig" namespace="u9jx6NrYMk8ba" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="_index" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uDgHTOeq61MN6" namespace="u9jx6NrYMk8ba" type="uSnvPt02S7tvb"/>
</UML:Entity>
<UML:Entity isAbstract="false" isRoot="false" name="diagnosis" isLeaf="false" visibility="public" isSpecification="false" xmi.id="u8PmJ0kOURyJH" namespace="Entity_Relationship_Model">
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="claim_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uO3lWqTMmrG6a" namespace="u8PmJ0kOURyJH" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="code" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uFe9gE8wNmF3K" namespace="u8PmJ0kOURyJH" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="type" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uyHg48x5zNXfx" namespace="u8PmJ0kOURyJH" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="_index" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uxk7Kdk2zHUiA" namespace="u8PmJ0kOURyJH" type="uSnvPt02S7tvb"/>
</UML:Entity>
<UML:Entity isAbstract="false" isRoot="false" name="insurance" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uryWFOwX9Hwnx" namespace="Entity_Relationship_Model">
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="claim_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uRBVaj3Qzg9x6" namespace="uryWFOwX9Hwnx" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="vendor" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="ud6f1Wq2fcILc" namespace="uryWFOwX9Hwnx" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="type" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uoMTq1S9lomkk" namespace="uryWFOwX9Hwnx" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="_index" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uhptNu9fqya8L" namespace="uryWFOwX9Hwnx" type="uSnvPt02S7tvb"/>
</UML:Entity>
<UML:Entity isAbstract="false" isRoot="false" name="payer_payment" isLeaf="false" visibility="public" isSpecification="false" xmi.id="urfdKBRGTHsvD" namespace="Entity_Relationship_Model">
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="claim_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uQoUZNnAPQtkc" namespace="urfdKBRGTHsvD" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="payer_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uDCgrCiBo3ofU" namespace="urfdKBRGTHsvD" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="amount_paid" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uqE70vCYpR39d" namespace="urfdKBRGTHsvD" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="type" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="utcVCqg6Ujm0K" namespace="urfdKBRGTHsvD" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="code" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uchV31XAlL5zV" namespace="urfdKBRGTHsvD" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="_index" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="u9JcqdgWdfAr7" namespace="urfdKBRGTHsvD" type="uSnvPt02S7tvb"/>
</UML:Entity>
<UML:Entity isAbstract="false" isRoot="false" name="payments" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uqcoZhRnX5ofD" namespace="Entity_Relationship_Model">
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="claim_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="umeVf4SSnodg6" namespace="uqcoZhRnX5ofD" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="amount" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="u7QSbdxKaVCfZ" namespace="uqcoZhRnX5ofD" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="qualifier" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="ubC1rdi8Tsfqz" namespace="uqcoZhRnX5ofD" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="_index" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uC6IVjw3XYT2f" namespace="uqcoZhRnX5ofD" type="uSnvPt02S7tvb"/>
</UML:Entity>
<UML:Entity isAbstract="false" isRoot="false" name="procedures" isLeaf="false" visibility="public" isSpecification="false" xmi.id="uzBUSd4zzXvR9" namespace="Entity_Relationship_Model">
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="claim_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="um1KvytxUVkEL" namespace="uzBUSd4zzXvR9" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="code" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uqr4qRy9YDMZv" namespace="uzBUSd4zzXvR9" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="service_id" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uCkrP7xWJJ8UD" namespace="uzBUSd4zzXvR9" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="quantity" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uPcRikSKl2zqO" namespace="uzBUSd4zzXvR9" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="unit" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="u0hNz09sDwFYQ" namespace="uzBUSd4zzXvR9" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="amount" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="ux0JFk7sWlVm4" namespace="uzBUSd4zzXvR9" type="uSnvPt02S7tvb"/>
<UML:EntityAttribute isAbstract="false" dbindex_type="1100" isRoot="false" auto_increment="0" name="_index" isLeaf="false" values="125" attributes="" visibility="public" initialValue="" isSpecification="false" allow_null="1" xmi.id="uRoHyMxDDc7FO" namespace="uzBUSd4zzXvR9" type="uSnvPt02S7tvb"/>
</UML:Entity>
</UML:Namespace.ownedElement>
<XMI.extension xmi.extender="umbrello">
<diagrams resolution="96">
<diagram xmi.id="u1KHlJny82WhH" showattsig="1" localid="-1" snapcsgrid="0" documentation="" name="claims-sql" snapgrid="1" showattribassocs="1" isopen="1" linecolor="#000000" linewidth="0" showopsig="1" snapy="25" usefillcolor="0" type="9" canvasheight="427" showatts="1" griddotcolor="#d3d3d3" snapx="25" zoom="100" fillcolor="#ffff00" showstereotype="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" textcolor="#000000" showops="1" showpubliconly="0" showscope="1" canvaswidth="1126" backgroundcolor="#ffffff" showpackage="1" showgrid="0">
<widgets>
<entitywidget xmi.id="u9jx6NrYMk8ba" localid="uQmpvyqvHokUk" height="75" usesdiagramusefillcolor="0" linecolor="#000000" linewidth="0" y="-575" usefillcolor="0" isinstance="0" x="-2250" showattsigs="1" fillcolor="#ffff00" showstereotype="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" textcolor="#000000" autoresize="1" usesdiagramfillcolor="0" width="236"/>
<entitywidget xmi.id="u0o6nLeO0fEm7" localid="uRYkAokLx9ZQj" height="201" usesdiagramusefillcolor="0" linecolor="#000000" linewidth="0" y="-575" usefillcolor="0" isinstance="0" x="-1975" showattsigs="1" fillcolor="#ffff00" showstereotype="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" textcolor="#000000" autoresize="0" usesdiagramfillcolor="0" width="302"/>
<floatingtext xmi.id="uDemX08IckkEy" role="700" localid="uNo8r8g2BuJ3G" posttext="" height="35" usesdiagramusefillcolor="0" linecolor="#000000" linewidth="0" text="837 CLAIMS" y="-650" usefillcolor="0" isinstance="0" x="-2500" fillcolor="#ffff00" showstereotype="1" font="Sans Serif,20,-1,5,50,0,0,0,0,0" textcolor="#000000" autoresize="1" usesdiagramfillcolor="0" pretext="" width="169"/>
<entitywidget xmi.id="uryWFOwX9Hwnx" localid="umAk5ifZJ1kRl" height="75" usesdiagramusefillcolor="0" linecolor="#000000" linewidth="0" y="-375" usefillcolor="0" isinstance="0" x="-2250" showattsigs="1" fillcolor="#ffff00" showstereotype="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" textcolor="#000000" autoresize="0" usesdiagramfillcolor="0" width="238"/>
<entitywidget xmi.id="u8PmJ0kOURyJH" localid="ueg6EQdGyk81X" height="79" usesdiagramusefillcolor="0" linecolor="#000000" linewidth="0" y="-475" usefillcolor="0" isinstance="0" x="-2250" showattsigs="1" fillcolor="#ffff00" showstereotype="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" textcolor="#000000" autoresize="0" usesdiagramfillcolor="0" width="238"/>
<entitywidget xmi.id="uqcoZhRnX5ofD" localid="uGrVEdAPjRMja" height="100" usesdiagramusefillcolor="0" linecolor="#000000" linewidth="0" y="-325" usefillcolor="0" isinstance="0" x="-1625" showattsigs="0" fillcolor="#ffff00" showstereotype="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" textcolor="#000000" autoresize="0" usesdiagramfillcolor="0" width="251"/>
<entitywidget xmi.id="urfdKBRGTHsvD" localid="usicGhIAq9f7L" height="103" usesdiagramusefillcolor="0" linecolor="#000000" linewidth="0" y="-450" usefillcolor="0" isinstance="0" x="-1625" showattsigs="1" fillcolor="#ffff00" showstereotype="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" textcolor="#000000" autoresize="1" usesdiagramfillcolor="0" width="250"/>
<entitywidget xmi.id="uIt8r5rl1o40g" localid="ud80YBCGjoc8n" height="96" usesdiagramusefillcolor="0" linecolor="#000000" linewidth="0" y="-575" usefillcolor="0" isinstance="0" x="-1625" showattsigs="1" fillcolor="#ffff00" showstereotype="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" textcolor="#000000" autoresize="0" usesdiagramfillcolor="0" width="251"/>
<entitywidget xmi.id="uzBUSd4zzXvR9" localid="u7tNjpPKWJoGd" height="127" usesdiagramusefillcolor="0" linecolor="#000000" linewidth="0" y="-350" usefillcolor="0" isinstance="0" x="-1975" showattsigs="0" fillcolor="#ffff00" showstereotype="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" textcolor="#000000" autoresize="0" usesdiagramfillcolor="0" width="302"/>
</widgets>
<messages/>
<associations/>
</diagram>
</diagrams>
</XMI.extension>
</UML:Model>
</UML:Namespace.ownedElement>
</UML:Model>
</XMI.content>
<XMI.extensions xmi.extender="umbrello">
<docsettings documentation="" viewid="u1KHlJny82WhH" uniqueid="uinb8VTgboe7o"/>
<listview>
<listitem id="Views" open="1" type="800">
<listitem id="Component_View" open="1" type="821"/>
<listitem id="Deployment_View" open="1" type="827"/>
<listitem id="Entity_Relationship_Model" open="1" type="836">
<listitem id="uIt8r5rl1o40g" open="0" type="832">
<listitem id="uFD7jRw8vwz8o" open="0" type="833"/>
<listitem id="uTpfrtFZpRhat" open="0" type="833"/>
<listitem id="uSYVzSUI013SA" open="0" type="833"/>
<listitem id="u588PxOwyWVln" open="0" type="833"/>
<listitem id="ukqfwxa6LykJ0" open="0" type="833"/>
</listitem>
<listitem id="u0o6nLeO0fEm7" open="0" type="832">
<listitem id="un3xoNxajJ2xm" open="0" type="833"/>
<listitem id="uYDfK8VkY0Uex" open="0" type="833"/>
<listitem id="udh4izR25tLXk" open="0" type="833"/>
<listitem id="u74xYiT4G5wyL" open="0" type="833"/>
<listitem id="ulgSeuvbWb2IS" open="0" type="833"/>
<listitem id="ue7HQl68mupvi" open="0" type="833"/>
<listitem id="uwUPYbIyt5p6d" open="0" type="833"/>
<listitem id="u7ACwVQiy9E9Z" open="0" type="833"/>
<listitem id="u6YddgnfmpAlc" open="0" type="833"/>
<listitem id="uiZCcx2if32Rz" open="0" type="833"/>
<listitem id="uogvUuoceENSP" open="0" type="833"/>
<listitem id="uNawwAMUkVRCI" open="0" type="833"/>
<listitem id="uRjR66XIKc4Cj" open="0" type="833"/>
</listitem>
<listitem id="u1KHlJny82WhH" open="0" label="claims-sql" type="834"/>
<listitem id="u9jx6NrYMk8ba" open="0" type="832">
<listitem id="uDgHTOeq61MN6" open="0" type="833"/>
<listitem id="uOFiCH5hs2CqD" open="0" type="833"/>
<listitem id="uJ3UETdwbO2Ig" open="0" type="833"/>
<listitem id="uWlHRTJczp2hP" open="0" type="833"/>
</listitem>
<listitem id="u8PmJ0kOURyJH" open="0" type="832">
<listitem id="uxk7Kdk2zHUiA" open="0" type="833"/>
<listitem id="uO3lWqTMmrG6a" open="0" type="833"/>
<listitem id="uFe9gE8wNmF3K" open="0" type="833"/>
<listitem id="uyHg48x5zNXfx" open="0" type="833"/>
</listitem>
<listitem id="uryWFOwX9Hwnx" open="0" type="832">
<listitem id="uhptNu9fqya8L" open="0" type="833"/>
<listitem id="uRBVaj3Qzg9x6" open="0" type="833"/>
<listitem id="uoMTq1S9lomkk" open="0" type="833"/>
<listitem id="ud6f1Wq2fcILc" open="0" type="833"/>
</listitem>
<listitem id="urfdKBRGTHsvD" open="0" type="832">
<listitem id="u9JcqdgWdfAr7" open="0" type="833"/>
<listitem id="uqE70vCYpR39d" open="0" type="833"/>
<listitem id="uQoUZNnAPQtkc" open="0" type="833"/>
<listitem id="uchV31XAlL5zV" open="0" type="833"/>
<listitem id="uDCgrCiBo3ofU" open="0" type="833"/>
<listitem id="utcVCqg6Ujm0K" open="0" type="833"/>
</listitem>
<listitem id="uqcoZhRnX5ofD" open="0" type="832">
<listitem id="uC6IVjw3XYT2f" open="0" type="833"/>
<listitem id="u7QSbdxKaVCfZ" open="0" type="833"/>
<listitem id="umeVf4SSnodg6" open="0" type="833"/>
<listitem id="ubC1rdi8Tsfqz" open="0" type="833"/>
</listitem>
<listitem id="uzBUSd4zzXvR9" open="0" type="832">
<listitem id="uRoHyMxDDc7FO" open="0" type="833"/>
<listitem id="ux0JFk7sWlVm4" open="0" type="833"/>
<listitem id="um1KvytxUVkEL" open="0" type="833"/>
<listitem id="uqr4qRy9YDMZv" open="0" type="833"/>
<listitem id="uPcRikSKl2zqO" open="0" type="833"/>
<listitem id="uCkrP7xWJJ8UD" open="0" type="833"/>
<listitem id="u0hNz09sDwFYQ" open="0" type="833"/>
</listitem>
</listitem>
<listitem id="Logical_View" open="1" type="801">
<listitem id="u8KOkLitCdEg4" open="0" label="class diagram" type="807"/>
<listitem id="Datatypes" open="0" type="830">
<listitem id="uhsHrB8csHO10" open="1" type="829"/>
<listitem id="uivybGgIE3bD0" open="1" type="829"/>
<listitem id="uWWi8ci3eh65i" open="1" type="829"/>
<listitem id="uqpjG9tkWEa7X" open="1" type="829"/>
<listitem id="uwRCbX5F7jgLF" open="0" type="829"/>
<listitem id="u5TSvGJ0WXtUp" open="1" type="829"/>
<listitem id="uGDbLeVMULJkk" open="1" type="829"/>
<listitem id="uLGmbFVmIZR5K" open="1" type="829"/>
<listitem id="uabvhj07enGME" open="0" type="829"/>
<listitem id="ukmjXUC40LtU7" open="1" type="829"/>
<listitem id="uSnvPt02S7tvb" open="1" type="829"/>
<listitem id="uz3Al8mzoS0I3" open="1" type="829"/>
<listitem id="uyHfbIHPXILpB" open="1" type="829"/>
<listitem id="uL5DOPBGjUyyC" open="1" type="829"/>
<listitem id="u6MI7pVV7hXsf" open="1" type="829"/>
<listitem id="usBQivEzmQ1BW" open="0" type="829"/>
<listitem id="ujgGh0hthNOjx" open="1" type="829"/>
<listitem id="uDJRPxwaZX3V7" open="0" type="829"/>
<listitem id="uKX78NObRE1fe" open="1" type="829"/>
<listitem id="u4OxDbpjlH3pe" open="0" type="829"/>
<listitem id="ulzNk0Rb91myv" open="1" type="829"/>
<listitem id="uI220TA6Z0j6n" open="1" type="829"/>
<listitem id="uDrG5vcusdKBM" open="1" type="829"/>
<listitem id="ueN3MSvcxioDm" open="0" type="829"/>
<listitem id="udr0tadLTTAWz" open="0" type="829"/>
<listitem id="uCgYfO6iac2jN" open="1" type="829"/>
<listitem id="uxSn0sOl0rdv1" open="1" type="829"/>
<listitem id="unOpNjlDqyBUV" open="1" type="829"/>
<listitem id="uOGQO1PzHG9jT" open="1" type="829"/>
<listitem id="uIYX1EziKvxte" open="1" type="829"/>
<listitem id="uB5Z9Av67TQfu" open="1" type="829"/>
<listitem id="uclB4l6uHrYXp" open="1" type="829"/>
<listitem id="uvDJ2b98uJr2k" open="1" type="829"/>
<listitem id="uoRs9Jh7Jejo2" open="1" type="829"/>
<listitem id="uHr88gSJngOwQ" open="0" type="829"/>
<listitem id="uWGlDG1tsuigz" open="0" type="829"/>
<listitem id="uzkXa9SjrJK3C" open="0" type="829"/>
<listitem id="uGiRQT4nooVd3" open="0" type="829"/>
<listitem id="uHnTLssRNvwe9" open="0" type="829"/>
<listitem id="u0Uu6RLk1nAgq" open="1" type="829"/>
<listitem id="uzDhYR9iUxXR6" open="0" type="829"/>
<listitem id="uL9aNTx5gdrZz" open="1" type="829"/>
<listitem id="u85nOph4JKwlg" open="1" type="829"/>
<listitem id="uOTQbnbs1N3TF" open="1" type="829"/>
<listitem id="u4qKd0QA9rWNf" open="1" type="829"/>
<listitem id="uFh4LzRYE3f5n" open="0" type="829"/>
<listitem id="uCRFY3OMvmsTh" open="0" type="829"/>
<listitem id="uXN2ZkDRs26FV" open="0" type="829"/>
<listitem id="uMFI3J7IsMqdx" open="0" type="829"/>
<listitem id="u3oTW1v02tom1" open="0" type="829"/>
</listitem>
</listitem>
<listitem id="Use_Case_View" open="1" type="802"/>
</listitem>
</listview>
<codegeneration>
<codegenerator language="PostgreSQL"/>
</codegeneration>
</XMI.extensions>
</XMI>

@ -0,0 +1,331 @@
<?xml version="1.0" encoding="UTF-8"?>
<XMI verified="false" timestamp="2021-01-11T15:50:46" xmlns:UML="http://schema.omg.org/spec/UML/1.4" xmi.version="1.2">
<XMI.header>
<XMI.documentation>
<XMI.exporter>umbrello uml modeller http://umbrello.kde.org</XMI.exporter>
<XMI.exporterVersion>1.6.17</XMI.exporterVersion>
<XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>
</XMI.documentation>
<XMI.metamodel xmi.name="UML" xmi.version="1.4" href="UML.xml"/>
</XMI.header>
<XMI.content>
<UML:Model xmi.id="m1" isLeaf="false" isAbstract="false" name="UML Model" isSpecification="false" isRoot="false">
<UML:Namespace.ownedElement>
<UML:Stereotype xmi.id="folder" isLeaf="false" isAbstract="false" visibility="public" name="folder" isSpecification="false" namespace="m1" isRoot="false"/>
<UML:Model xmi.id="Logical_View" isLeaf="false" isAbstract="false" visibility="public" name="Logical View" isSpecification="false" namespace="m1" isRoot="false">
<UML:Namespace.ownedElement>
<UML:Package xmi.id="Datatypes" stereotype="folder" isLeaf="false" isAbstract="false" visibility="public" name="Datatypes" isSpecification="false" namespace="Logical_View" isRoot="false">
<UML:Namespace.ownedElement>
<UML:DataType xmi.id="u4xIFQFMKzJrw" isLeaf="false" isAbstract="false" visibility="public" name="char" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uUrqcj6xGhwaC" isLeaf="false" isAbstract="false" visibility="public" name="int" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="u2CL1gZXtSnOS" isLeaf="false" isAbstract="false" visibility="public" name="float" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="u2wysBNkFNdqp" isLeaf="false" isAbstract="false" visibility="public" name="double" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="usYHH6veFLtOr" isLeaf="false" isAbstract="false" visibility="public" name="bool" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uN90WSzxg70L5" isLeaf="false" isAbstract="false" visibility="public" name="string" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uks0OAl3npzAp" isLeaf="false" isAbstract="false" visibility="public" name="unsigned char" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="unwvIxd81D8F6" isLeaf="false" isAbstract="false" visibility="public" name="signed char" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uegsqNCOwThlg" isLeaf="false" isAbstract="false" visibility="public" name="unsigned int" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="u8U3EclXHUBqf" isLeaf="false" isAbstract="false" visibility="public" name="signed int" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uHcFFwtOW2QoG" isLeaf="false" isAbstract="false" visibility="public" name="short int" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="u3gksr7QwMjSv" isLeaf="false" isAbstract="false" visibility="public" name="unsigned short int" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uc2wrhdQQFdKR" isLeaf="false" isAbstract="false" visibility="public" name="signed short int" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uO1NrEETU4UC8" isLeaf="false" isAbstract="false" visibility="public" name="long int" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="umes0MFf2bAXI" isLeaf="false" isAbstract="false" visibility="public" name="signed long int" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uIzLslKdzkNSu" isLeaf="false" isAbstract="false" visibility="public" name="unsigned long int" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uuismMojqbmsx" isLeaf="false" isAbstract="false" visibility="public" name="long double" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uaxm6xi0OF7H9" isLeaf="false" isAbstract="false" visibility="public" name="wchar_t" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uKoxqBVMuFAFv" isLeaf="false" isAbstract="false" visibility="public" name="blob" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="udJEUGSmFsMc7" isLeaf="false" isAbstract="false" visibility="public" name="bigint" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="u0C5GYVgNAN71" isLeaf="false" isAbstract="false" visibility="public" name="date" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="u9FKE3RWhiqcG" isLeaf="false" isAbstract="false" visibility="public" name="datetime" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uhDxBNpwOBqQw" isLeaf="false" isAbstract="false" visibility="public" name="decimal" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uHqbfHWPho1Ur" isLeaf="false" isAbstract="false" visibility="public" name="enum" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uya6iY5Q7DGeZ" isLeaf="false" isAbstract="false" visibility="public" name="longblob" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uaeIOuN6e4FU1" isLeaf="false" isAbstract="false" visibility="public" name="longtext" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="u8zuwCW44JB95" isLeaf="false" isAbstract="false" visibility="public" name="mediumblob" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uGdQJaRR6gTOr" isLeaf="false" isAbstract="false" visibility="public" name="mediumint" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uYevwcNN1qRSX" isLeaf="false" isAbstract="false" visibility="public" name="mediumtext" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uApLJztW3N1vU" isLeaf="false" isAbstract="false" visibility="public" name="set" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uCMJShOyEcx65" isLeaf="false" isAbstract="false" visibility="public" name="smallint" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uMXT4n4yeeGxP" isLeaf="false" isAbstract="false" visibility="public" name="text" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uZPyITrjct7nt" isLeaf="false" isAbstract="false" visibility="public" name="time" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uJlnCmWCjiZyb" isLeaf="false" isAbstract="false" visibility="public" name="timestamp" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uJ6eIdSRnQ1mC" isLeaf="false" isAbstract="false" visibility="public" name="tinyblob" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uFa0n9CbZAGQz" isLeaf="false" isAbstract="false" visibility="public" name="tinyint" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uUmpoisGYNixK" isLeaf="false" isAbstract="false" visibility="public" name="tinytext" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uCYvllFCLICqv" isLeaf="false" isAbstract="false" visibility="public" name="varchar" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uJPiqYCPjwNHv" isLeaf="false" isAbstract="false" visibility="public" name="year" isSpecification="false" namespace="Datatypes" isRoot="false"/>
<UML:DataType xmi.id="uy27kWMqeaG0m" isLeaf="false" isAbstract="false" visibility="public" name="character varying" isSpecification="false" namespace="Datatypes" isRoot="false"/>
</UML:Namespace.ownedElement>
</UML:Package>
</UML:Namespace.ownedElement>
<XMI.extension xmi.extender="umbrello">
<diagrams resolution="96">
<diagram documentation="" showstereotype="1" textcolor="#000000" showattribassocs="1" name="class diagram" snapy="25" zoom="100" showops="1" showopsig="1" fillcolor="#ffff00" showpackage="1" canvaswidth="0" isopen="1" backgroundcolor="#ffffff" showpubliconly="0" snapgrid="0" snapx="25" xmi.id="ucgtgQRSMYlOp" showatts="1" type="1" griddotcolor="#d3d3d3" showattsig="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" showgrid="0" showscope="1" linecolor="#ff0000" snapcsgrid="0" linewidth="0" usefillcolor="1" localid="-1" canvasheight="0">
<widgets/>
<messages/>
<associations/>
</diagram>
</diagrams>
</XMI.extension>
</UML:Model>
<UML:Model xmi.id="Use_Case_View" isLeaf="false" isAbstract="false" visibility="public" name="Use Case View" isSpecification="false" namespace="m1" isRoot="false">
<UML:Namespace.ownedElement/>
</UML:Model>
<UML:Model xmi.id="Component_View" isLeaf="false" isAbstract="false" visibility="public" name="Component View" isSpecification="false" namespace="m1" isRoot="false">
<UML:Namespace.ownedElement/>
</UML:Model>
<UML:Model xmi.id="Deployment_View" isLeaf="false" isAbstract="false" visibility="public" name="Deployment View" isSpecification="false" namespace="m1" isRoot="false">
<UML:Namespace.ownedElement/>
</UML:Model>
<UML:Model xmi.id="Entity_Relationship_Model" isLeaf="false" isAbstract="false" visibility="public" name="Entity Relationship Model" isSpecification="false" namespace="m1" isRoot="false">
<UML:Namespace.ownedElement>
<UML:Entity xmi.id="unciQy8XxFf2T" isLeaf="false" isAbstract="false" visibility="public" name="adjudicated" isSpecification="false" namespace="Entity_Relationship_Model" isRoot="false">
<UML:EntityAttribute xmi.id="uMy5ahFmN0KRD" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="claim_id" isSpecification="false" namespace="unciQy8XxFf2T" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="ubJdB6RGlsKyI" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="adjudicated_procedure_cd" isSpecification="false" namespace="unciQy8XxFf2T" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uW0mYtdR4tpSX" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="adjudicated_procedure_cd_qual" isSpecification="false" namespace="unciQy8XxFf2T" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="ujq5GJmFPNCgS" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="adjudicated_proc_modifier_1" isSpecification="false" namespace="unciQy8XxFf2T" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uXwwLwuES808h" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="adjudicated_proc_modifier_2" isSpecification="false" namespace="unciQy8XxFf2T" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uvpv92xuc6vb5" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="adjudicated_proc_modifier_3" isSpecification="false" namespace="unciQy8XxFf2T" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="ugpN8ZjPYZz0b" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="adjudicated_proc_modifier_4" isSpecification="false" namespace="unciQy8XxFf2T" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="u0cbN6lqPZFq5" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="_index" isSpecification="false" namespace="unciQy8XxFf2T" values="125" isRoot="false"/>
</UML:Entity>
<UML:Entity xmi.id="u7JoY1YgBbZBw" isLeaf="false" isAbstract="false" visibility="public" name="adjustments" isSpecification="false" namespace="Entity_Relationship_Model" isRoot="false">
<UML:EntityAttribute xmi.id="uJWMJDJW7OPHZ" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="claim_id" isSpecification="false" namespace="u7JoY1YgBbZBw" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="ut2LR9qmsrOKs" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="amount" isSpecification="false" namespace="u7JoY1YgBbZBw" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uPRzkRJCCJabo" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="reason" isSpecification="false" namespace="u7JoY1YgBbZBw" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uCGGZqIN2sQH3" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="quantity" isSpecification="false" namespace="u7JoY1YgBbZBw" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="utB3YD4uBHDFe" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="group_code" isSpecification="false" namespace="u7JoY1YgBbZBw" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uJB8h1NGbex2g" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="reason_code" isSpecification="false" namespace="u7JoY1YgBbZBw" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uSWWvOUaew5HP" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="adustment_amount" isSpecification="false" namespace="u7JoY1YgBbZBw" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uF4C162xw4VxT" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="adjustment_quantity" isSpecification="false" namespace="u7JoY1YgBbZBw" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uized1QFwg0ct" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="_index" isSpecification="false" namespace="u7JoY1YgBbZBw" values="125" isRoot="false"/>
</UML:Entity>
<UML:Entity xmi.id="uYFy5I3jZovwB" isLeaf="false" isAbstract="false" visibility="public" name="dates" isSpecification="false" namespace="Entity_Relationship_Model" isRoot="false">
<UML:EntityAttribute xmi.id="u19O44eIBLpSx" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="claim_id" isSpecification="false" namespace="uYFy5I3jZovwB" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="u24TxypfX1ehF" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="type" isSpecification="false" namespace="uYFy5I3jZovwB" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="u1rGJT5BzOnTc" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="date" isSpecification="false" namespace="uYFy5I3jZovwB" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uh1XMXOFqqkLH" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="claim_received_by_payer_date" isSpecification="false" namespace="uYFy5I3jZovwB" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="udhZrX8aJ7mx2" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="_index" isSpecification="false" namespace="uYFy5I3jZovwB" values="125" isRoot="false"/>
</UML:Entity>
<UML:Entity xmi.id="uQLb3AjtJtg1u" isLeaf="false" isAbstract="false" visibility="public" name="procedures" isSpecification="false" namespace="Entity_Relationship_Model" isRoot="false">
<UML:EntityAttribute xmi.id="uAjDOjucMMjVA" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="claim_id" isSpecification="false" namespace="uQLb3AjtJtg1u" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uvwYZ2ZXVtktZ" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="code" isSpecification="false" namespace="uQLb3AjtJtg1u" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uK1hOh0gYH7UR" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="amount" isSpecification="false" namespace="uQLb3AjtJtg1u" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uzXoWRaQEBR4N" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="line_charge_amount" isSpecification="false" namespace="uQLb3AjtJtg1u" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uTu2N31LFQjZs" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="submitted_units_of_service" isSpecification="false" namespace="uQLb3AjtJtg1u" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uX3uZJhBt3XbF" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="revenue_code" isSpecification="false" namespace="uQLb3AjtJtg1u" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="u1iY5DjVfwxct" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="paid_units_of_service" isSpecification="false" namespace="uQLb3AjtJtg1u" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="udHyId5EQgnxd" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="line_paid_amount" isSpecification="false" namespace="uQLb3AjtJtg1u" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="ucBf8PfYusdLF" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="_index" isSpecification="false" namespace="uQLb3AjtJtg1u" values="125" isRoot="false"/>
</UML:Entity>
<UML:Entity xmi.id="uxCXzVM24yYaX" isLeaf="false" isAbstract="false" visibility="public" name="provider" isSpecification="false" namespace="Entity_Relationship_Model" isRoot="false">
<UML:EntityAttribute xmi.id="ucbfGJzClrgx7" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="claim_id" isSpecification="false" namespace="uxCXzVM24yYaX" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="ui5GIXpde552t" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="provider_id" isSpecification="false" namespace="uxCXzVM24yYaX" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uqpcLcCfQxPc1" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="adjustment_fiscal_year" isSpecification="false" namespace="uxCXzVM24yYaX" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="u8EKwCD4KJD35" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="adjustment_amount" isSpecification="false" namespace="uxCXzVM24yYaX" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="ugSzBbS45Appb" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="_index" isSpecification="false" namespace="uxCXzVM24yYaX" values="125" isRoot="false"/>
</UML:Entity>
<UML:Entity xmi.id="uFhe3BvJ5GFMv" isLeaf="false" isAbstract="false" visibility="public" name="remits" isSpecification="false" namespace="Entity_Relationship_Model" isRoot="false">
<UML:EntityAttribute xmi.id="uaPrhdtHj174f" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="claim_id" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="umBq8tNVoHLwQ" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="charge_amount" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="u2TjnY4FpRX7E" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="payment_amount" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uO0RFshYIUxyV" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="patient_amount" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="u26a7mGlibP31" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="patient_status" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uqT7KYiudzE2a" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="status" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="utDLqzoqgcm98" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="total_paid_amt" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="u4760sev0qJdC" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="total_claim_charge_amount" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uYOWi0TRwwQ9C" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="patient_responsibility_amount" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uTmKxBb1U6HHd" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="drug_code" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="u8b87l43udLdm" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="type_of_bill" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="ussv42OpwEC3o" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="claim_control_number" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uutC8Ww5MIEDw" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="type_of_coverage" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uVwZLtkVRxhLS" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="place_of_service" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uMxluIdcl530X" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="claim_status" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="u35C8cp4M74EZ" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="transaction_type" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uGKSxco6bkhJK" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="transaction_amount" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uFR0HPZWCHTOd" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="transaction_method" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uRKSgcFBa5IZo" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="date_paid" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uTI9AfIOT6Vgi" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="billing_pr_adr_line_1" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uh7Mo4vNDxjEP" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="billing_pr_adr_line_2" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uIOoyY9AcSXqj" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="billing_pr_adr_zip" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uM8YUylmQOOZz" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="billing_pr_adr_state" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="ueFTa93wS5vpr" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="billing_pr_adr_city" isSpecification="false" namespace="uFhe3BvJ5GFMv" values="125" isRoot="false"/>
</UML:Entity>
<UML:Entity xmi.id="uDyfldNoIv0VN" isLeaf="false" isAbstract="false" visibility="public" name="submitted_procedures" isSpecification="false" namespace="Entity_Relationship_Model" isRoot="false">
<UML:EntityAttribute xmi.id="uHlzHdGAzTLje" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="claim_id" isSpecification="false" namespace="uDyfldNoIv0VN" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uTdAUNse734xO" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="submitted_procedure_cd" isSpecification="false" namespace="uDyfldNoIv0VN" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="usy1XBeLxeUGA" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="submitted_procedure_cd_qual" isSpecification="false" namespace="uDyfldNoIv0VN" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uXzmRTjxt5urK" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="submitted_proc_modifier_1" isSpecification="false" namespace="uDyfldNoIv0VN" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uZaNNwlpF8G8D" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="submitted_proc_modifier_2" isSpecification="false" namespace="uDyfldNoIv0VN" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uTVrpMWQGZv9k" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="submitted_proc_modifier_3" isSpecification="false" namespace="uDyfldNoIv0VN" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uDVH1N8QTr4Hh" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="submitted_proc_modifier_4" isSpecification="false" namespace="uDyfldNoIv0VN" values="125" isRoot="false"/>
<UML:EntityAttribute xmi.id="uiSnbXbl5xZgj" allow_null="1" dbindex_type="1100" isLeaf="false" isAbstract="false" visibility="public" initialValue="" attributes="" type="uy27kWMqeaG0m" auto_increment="0" name="_index" isSpecification="false" namespace="uDyfldNoIv0VN" values="125" isRoot="false"/>
</UML:Entity>
</UML:Namespace.ownedElement>
<XMI.extension xmi.extender="umbrello">
<diagrams resolution="96">
<diagram documentation="" showstereotype="1" textcolor="#000000" showattribassocs="1" name="remits" snapy="25" zoom="100" showops="1" showopsig="1" fillcolor="#ffff00" showpackage="1" canvaswidth="1599" isopen="1" backgroundcolor="#ffffff" showpubliconly="0" snapgrid="1" snapx="25" xmi.id="uKioLvROZP9sj" showatts="1" type="9" griddotcolor="#d3d3d3" showattsig="1" font="Sans Serif,9,-1,5,50,0,0,0,0,0" showgrid="0" showscope="1" linecolor="#000000" snapcsgrid="0" linewidth="0" usefillcolor="0" localid="-1" canvasheight="556">
<widgets>
<entitywidget width="374" showstereotype="1" textcolor="#000000" showattsigs="1" autoresize="1" usesdiagramusefillcolor="0" height="131" fillcolor="#ffff00" x="-400" xmi.id="unciQy8XxFf2T" isinstance="0" y="-325" font="Sans Serif,9,-1,5,50,0,0,0,0,0" usesdiagramfillcolor="0" linecolor="#000000" linewidth="0" localid="u9BawkrPSkiAR" usefillcolor="0"/>
<entitywidget width="373" showstereotype="1" textcolor="#000000" showattsigs="1" autoresize="0" usesdiagramusefillcolor="0" height="145" fillcolor="#ffff00" x="-400" xmi.id="u7JoY1YgBbZBw" isinstance="0" y="-150" font="Sans Serif,9,-1,5,50,0,0,0,0,0" usesdiagramfillcolor="0" linecolor="#000000" linewidth="0" localid="u4iVjIspsosQL" usefillcolor="0"/>
<entitywidget width="374" showstereotype="1" textcolor="#000000" showattsigs="1" autoresize="0" usesdiagramusefillcolor="0" height="90" fillcolor="#ffff00" x="-400" xmi.id="uYFy5I3jZovwB" isinstance="0" y="25" font="Sans Serif,9,-1,5,50,0,0,0,0,0" usesdiagramfillcolor="0" linecolor="#000000" linewidth="0" localid="u2C9V7ZineWlR" usefillcolor="0"/>
<entitywidget width="362" showstereotype="1" textcolor="#000000" showattsigs="1" autoresize="0" usesdiagramusefillcolor="0" height="147" fillcolor="#ffff00" x="-1250" xmi.id="uQLb3AjtJtg1u" isinstance="0" y="-325" font="Sans Serif,9,-1,5,50,0,0,0,0,0" usesdiagramfillcolor="0" linecolor="#000000" linewidth="0" localid="urgFkiZg2gtuo" usefillcolor="0"/>
<entitywidget width="364" showstereotype="1" textcolor="#000000" showattsigs="0" autoresize="0" usesdiagramusefillcolor="0" height="124" fillcolor="#ffff00" x="-1250" xmi.id="uxCXzVM24yYaX" isinstance="0" y="-150" font="Sans Serif,9,-1,5,50,0,0,0,0,0" usesdiagramfillcolor="0" linecolor="#000000" linewidth="0" localid="uCObA80MWNOaQ" usefillcolor="0"/>
<entitywidget width="373" showstereotype="1" textcolor="#000000" showattsigs="1" autoresize="0" usesdiagramusefillcolor="0" height="452" fillcolor="#ffff00" x="-825" xmi.id="uFhe3BvJ5GFMv" isinstance="0" y="-325" font="Sans Serif,9,-1,5,50,0,0,0,0,0" usesdiagramfillcolor="0" linecolor="#000000" linewidth="0" localid="ujz1Vg5ZL42FJ" usefillcolor="0"/>
<entitywidget width="362" showstereotype="1" textcolor="#000000" showattsigs="0" autoresize="0" usesdiagramusefillcolor="0" height="131" fillcolor="#ffff00" x="-1250" xmi.id="uDyfldNoIv0VN" isinstance="0" y="0" font="Sans Serif,9,-1,5,50,0,0,0,0,0" usesdiagramfillcolor="0" linecolor="#000000" linewidth="0" localid="umfGrEfhw5trO" usefillcolor="0"/>
<floatingtext width="257" showstereotype="1" textcolor="#000000" pretext="" autoresize="1" usesdiagramusefillcolor="0" height="35" fillcolor="#ffff00" x="-1625" xmi.id="uojLF0iPnR6e2" isinstance="0" y="-425" text="835 REMITTANCES" font="Sans Serif,20,-1,5,50,0,0,0,0,0" usesdiagramfillcolor="0" linecolor="#000000" role="700" linewidth="0" localid="uSSnE3AdKsGoB" usefillcolor="0" posttext=""/>
</widgets>
<messages/>
<associations/>
</diagram>
</diagrams>
</XMI.extension>
</UML:Model>
</UML:Namespace.ownedElement>
</UML:Model>
</XMI.content>
<XMI.extensions xmi.extender="umbrello">
<docsettings viewid="uKioLvROZP9sj" documentation="" uniqueid="ueCKqCZwQu4Lk"/>
<listview>
<listitem type="800" id="Views" open="1">
<listitem type="821" id="Component_View" open="1"/>
<listitem type="827" id="Deployment_View" open="1"/>
<listitem type="836" id="Entity_Relationship_Model" open="1">
<listitem type="832" id="unciQy8XxFf2T" open="0">
<listitem type="833" id="u0cbN6lqPZFq5" open="0"/>
<listitem type="833" id="ujq5GJmFPNCgS" open="0"/>
<listitem type="833" id="uXwwLwuES808h" open="0"/>
<listitem type="833" id="uvpv92xuc6vb5" open="0"/>
<listitem type="833" id="ugpN8ZjPYZz0b" open="0"/>
<listitem type="833" id="ubJdB6RGlsKyI" open="0"/>
<listitem type="833" id="uW0mYtdR4tpSX" open="0"/>
<listitem type="833" id="uMy5ahFmN0KRD" open="0"/>
</listitem>
<listitem type="832" id="u7JoY1YgBbZBw" open="0">
<listitem type="833" id="uized1QFwg0ct" open="0"/>
<listitem type="833" id="uF4C162xw4VxT" open="0"/>
<listitem type="833" id="uSWWvOUaew5HP" open="0"/>
<listitem type="833" id="ut2LR9qmsrOKs" open="0"/>
<listitem type="833" id="uJWMJDJW7OPHZ" open="0"/>
<listitem type="833" id="utB3YD4uBHDFe" open="0"/>
<listitem type="833" id="uCGGZqIN2sQH3" open="0"/>
<listitem type="833" id="uPRzkRJCCJabo" open="0"/>
<listitem type="833" id="uJB8h1NGbex2g" open="0"/>
</listitem>
<listitem type="832" id="uYFy5I3jZovwB" open="0">
<listitem type="833" id="udhZrX8aJ7mx2" open="0"/>
<listitem type="833" id="u19O44eIBLpSx" open="0"/>
<listitem type="833" id="uh1XMXOFqqkLH" open="0"/>
<listitem type="833" id="u1rGJT5BzOnTc" open="0"/>
<listitem type="833" id="u24TxypfX1ehF" open="0"/>
</listitem>
<listitem type="832" id="uQLb3AjtJtg1u" open="0">
<listitem type="833" id="ucBf8PfYusdLF" open="0"/>
<listitem type="833" id="uK1hOh0gYH7UR" open="0"/>
<listitem type="833" id="uAjDOjucMMjVA" open="0"/>
<listitem type="833" id="uvwYZ2ZXVtktZ" open="0"/>
<listitem type="833" id="uzXoWRaQEBR4N" open="0"/>
<listitem type="833" id="udHyId5EQgnxd" open="0"/>
<listitem type="833" id="u1iY5DjVfwxct" open="0"/>
<listitem type="833" id="uX3uZJhBt3XbF" open="0"/>
<listitem type="833" id="uTu2N31LFQjZs" open="0"/>
</listitem>
<listitem type="832" id="uxCXzVM24yYaX" open="0">
<listitem type="833" id="ugSzBbS45Appb" open="0"/>
<listitem type="833" id="u8EKwCD4KJD35" open="0"/>
<listitem type="833" id="uqpcLcCfQxPc1" open="0"/>
<listitem type="833" id="ucbfGJzClrgx7" open="0"/>
<listitem type="833" id="ui5GIXpde552t" open="0"/>
</listitem>
<listitem type="832" id="uFhe3BvJ5GFMv" open="0">
<listitem type="833" id="ueFTa93wS5vpr" open="0"/>
<listitem type="833" id="uTI9AfIOT6Vgi" open="0"/>
<listitem type="833" id="uh7Mo4vNDxjEP" open="0"/>
<listitem type="833" id="uM8YUylmQOOZz" open="0"/>
<listitem type="833" id="uIOoyY9AcSXqj" open="0"/>
<listitem type="833" id="umBq8tNVoHLwQ" open="0"/>
<listitem type="833" id="ussv42OpwEC3o" open="0"/>
<listitem type="833" id="uaPrhdtHj174f" open="0"/>
<listitem type="833" id="uMxluIdcl530X" open="0"/>
<listitem type="833" id="uRKSgcFBa5IZo" open="0"/>
<listitem type="833" id="uTmKxBb1U6HHd" open="0"/>
<listitem type="833" id="uO0RFshYIUxyV" open="0"/>
<listitem type="833" id="uYOWi0TRwwQ9C" open="0"/>
<listitem type="833" id="u26a7mGlibP31" open="0"/>
<listitem type="833" id="u2TjnY4FpRX7E" open="0"/>
<listitem type="833" id="uVwZLtkVRxhLS" open="0"/>
<listitem type="833" id="uqT7KYiudzE2a" open="0"/>
<listitem type="833" id="u4760sev0qJdC" open="0"/>
<listitem type="833" id="utDLqzoqgcm98" open="0"/>
<listitem type="833" id="uGKSxco6bkhJK" open="0"/>
<listitem type="833" id="uFR0HPZWCHTOd" open="0"/>
<listitem type="833" id="u35C8cp4M74EZ" open="0"/>
<listitem type="833" id="u8b87l43udLdm" open="0"/>
<listitem type="833" id="uutC8Ww5MIEDw" open="0"/>
</listitem>
<listitem label="remits" type="834" id="uKioLvROZP9sj" open="0"/>
<listitem type="832" id="uDyfldNoIv0VN" open="0">
<listitem type="833" id="uiSnbXbl5xZgj" open="0"/>
<listitem type="833" id="uHlzHdGAzTLje" open="0"/>
<listitem type="833" id="uXzmRTjxt5urK" open="0"/>
<listitem type="833" id="uZaNNwlpF8G8D" open="0"/>
<listitem type="833" id="uTVrpMWQGZv9k" open="0"/>
<listitem type="833" id="uDVH1N8QTr4Hh" open="0"/>
<listitem type="833" id="uTdAUNse734xO" open="0"/>
<listitem type="833" id="usy1XBeLxeUGA" open="0"/>
</listitem>
</listitem>
<listitem type="801" id="Logical_View" open="1">
<listitem label="class diagram" type="807" id="ucgtgQRSMYlOp" open="0"/>
<listitem type="830" id="Datatypes" open="0">
<listitem type="829" id="udJEUGSmFsMc7" open="1"/>
<listitem type="829" id="uKoxqBVMuFAFv" open="1"/>
<listitem type="829" id="usYHH6veFLtOr" open="0"/>
<listitem type="829" id="u4xIFQFMKzJrw" open="0"/>
<listitem type="829" id="uy27kWMqeaG0m" open="0"/>
<listitem type="829" id="u0C5GYVgNAN71" open="1"/>
<listitem type="829" id="u9FKE3RWhiqcG" open="1"/>
<listitem type="829" id="uhDxBNpwOBqQw" open="1"/>
<listitem type="829" id="u2wysBNkFNdqp" open="0"/>
<listitem type="829" id="uHqbfHWPho1Ur" open="1"/>
<listitem type="829" id="u2CL1gZXtSnOS" open="0"/>
<listitem type="829" id="uUrqcj6xGhwaC" open="0"/>
<listitem type="829" id="uuismMojqbmsx" open="0"/>
<listitem type="829" id="uO1NrEETU4UC8" open="0"/>
<listitem type="829" id="uya6iY5Q7DGeZ" open="1"/>
<listitem type="829" id="uaeIOuN6e4FU1" open="1"/>
<listitem type="829" id="u8zuwCW44JB95" open="1"/>
<listitem type="829" id="uGdQJaRR6gTOr" open="1"/>
<listitem type="829" id="uYevwcNN1qRSX" open="1"/>
<listitem type="829" id="uApLJztW3N1vU" open="1"/>
<listitem type="829" id="uHcFFwtOW2QoG" open="0"/>
<listitem type="829" id="unwvIxd81D8F6" open="0"/>
<listitem type="829" id="u8U3EclXHUBqf" open="0"/>
<listitem type="829" id="umes0MFf2bAXI" open="0"/>
<listitem type="829" id="uc2wrhdQQFdKR" open="0"/>
<listitem type="829" id="uCMJShOyEcx65" open="1"/>
<listitem type="829" id="uN90WSzxg70L5" open="0"/>
<listitem type="829" id="uMXT4n4yeeGxP" open="1"/>
<listitem type="829" id="uZPyITrjct7nt" open="1"/>
<listitem type="829" id="uJlnCmWCjiZyb" open="1"/>
<listitem type="829" id="uJ6eIdSRnQ1mC" open="1"/>
<listitem type="829" id="uFa0n9CbZAGQz" open="1"/>
<listitem type="829" id="uUmpoisGYNixK" open="1"/>
<listitem type="829" id="uks0OAl3npzAp" open="0"/>
<listitem type="829" id="uegsqNCOwThlg" open="0"/>
<listitem type="829" id="uIzLslKdzkNSu" open="0"/>
<listitem type="829" id="u3gksr7QwMjSv" open="0"/>
<listitem type="829" id="uCYvllFCLICqv" open="1"/>
<listitem type="829" id="uaxm6xi0OF7H9" open="0"/>
<listitem type="829" id="uJPiqYCPjwNHv" open="1"/>
</listitem>
</listitem>
<listitem type="802" id="Use_Case_View" open="1"/>
</listitem>
</listview>
<codegeneration>
<codegenerator language="SQL"/>
</codegeneration>
</XMI.extensions>
</XMI>

@ -32,9 +32,10 @@ Usage :
from healthcareio.params import SYS_ARGS from healthcareio.params import SYS_ARGS
from transport import factory from transport import factory
import requests import requests
from healthcareio import analytics from healthcareio import analytics
from healthcareio import server from healthcareio import server
from healthcareio.parser import get_content from healthcareio.parser import get_content
import os import os
import json import json
@ -43,6 +44,10 @@ import numpy as np
from multiprocessing import Process from multiprocessing import Process
import time import time
from healthcareio import x12 from healthcareio import x12
from healthcareio.export import export
import smart
from healthcareio.server import proxy
import pandas as pd
PATH = os.sep.join([os.environ['HOME'],'.healthcareio']) PATH = os.sep.join([os.environ['HOME'],'.healthcareio'])
OUTPUT_FOLDER = os.sep.join([os.environ['HOME'],'healthcare-io']) OUTPUT_FOLDER = os.sep.join([os.environ['HOME'],'healthcare-io'])
@ -53,10 +58,28 @@ if not os.path.exists(PATH) :
import platform import platform
import sqlite3 as lite import sqlite3 as lite
# PATH = os.sep.join([os.environ['HOME'],'.edi-parser']) # PATH = os.sep.join([os.environ['HOME'],'.edi-parser'])
def register (**args) : HELP_MESSAGE = """
cli:
healthcare-io.py --<[signup|init]> <email> --store <sqlite|mongo> [--batch <value>]
healthcare-io.py --parse --folder <path> [--batch <value>] [--resume]
healthcare-io.py --check-update
healthcare-io.py --export <835|837> --config <config-path>
action :
--signup|init signup user and get configuration file
--parse starts parsing
--check checks for updates
--export export data of a 835 or 837 into another database
parameters :
--<[signup|init]> signup or get a configuration file from a parsing server
--folder location of the files (the program will recursively traverse it)
--store data store mongo or sqlite or mongodb
--resume will attempt to resume if there was an interruption
"""
def signup (**args) :
""" """
:email user's email address :email user's email address
:url url of the provider to register :url url of the provider to signup
""" """
email = args['email'] email = args['email']
@ -121,77 +144,77 @@ def init():
# #
# Global variables that load the configuration files # Global variables that load the configuration files
def parse(**args): # def parse(**args):
""" # """
This function will parse the content of a claim or remittance (x12 format) give the following parameters # This function will parse the content of a claim or remittance (x12 format) give the following parameters
:filename absolute path of the file to be parsed # :filename absolute path of the file to be parsed
:type claims|remits in x12 format # :type claims|remits in x12 format
""" # """
global INFO # global INFO
if not INFO : # if not INFO :
INFO = init() # INFO = init()
if args['type'] == 'claims' : # if args['type'] == 'claims' :
CONFIG = INFO['parser']['837'] # CONFIG = INFO['parser']['837']
elif args['type'] == 'remits' : # elif args['type'] == 'remits' :
CONFIG = INFO['parser']['835'] # CONFIG = INFO['parser']['835']
else: # else:
CONFIG = None # CONFIG = None
if CONFIG : # if CONFIG :
# CONFIG = CONFIG[-1] if 'version' not in args and (args['version'] < len(CONFIG)) else CONFIG[0] # # CONFIG = CONFIG[-1] if 'version' not in args and (args['version'] < len(CONFIG)) else CONFIG[0]
CONFIG = CONFIG[int(args['version'])-1] if 'version' in SYS_ARGS and int(SYS_ARGS['version']) < len(CONFIG) else CONFIG[-1] # CONFIG = CONFIG[int(args['version'])-1] if 'version' in SYS_ARGS and int(SYS_ARGS['version']) < len(CONFIG) else CONFIG[-1]
SECTION = CONFIG['SECTION'] # SECTION = CONFIG['SECTION']
os.environ['HEALTHCAREIO_SALT'] = INFO['owner'] # os.environ['HEALTHCAREIO_SALT'] = INFO['owner']
return get_content(args['filename'],CONFIG,SECTION) # return get_content(args['filename'],CONFIG,SECTION)
def resume (files,id,config): # def resume (files,id,config):
_args = config['store'].copy() # _args = config['store'].copy()
if 'mongo' in config['store']['type'] : # if 'mongo' in config['store']['type'] :
_args['type'] = 'mongo.MongoReader' # _args['type'] = 'mongo.MongoReader'
reader = factory.instance(**_args) # reader = factory.instance(**_args)
_files = [] # _files = []
if 'resume' in config['analytics'] : # if 'resume' in config['analytics'] :
_args = config['analytics']['resume'][id] # _args = config['analytics']['resume'][id]
_files = reader.read(**_args) # _files = reader.read(**_args)
_files = [item['name'] for item in _files if item['name'] != None] # _files = [item['name'] for item in _files if item['name'] != None]
return list(set(files) - set(_files)) # return list(set(files) - set(_files))
return files # return files
pass # pass
def apply(files,store_info,logger_info=None): # def apply(files,store_info,logger_info=None):
""" # """
:files list of files to be processed in this given thread/process # :files list of files to be processed in this given thread/process
:store_info information about data-store, for now disk isn't thread safe # :store_info information about data-store, for now disk isn't thread safe
:logger_info information about where to store the logs # :logger_info information about where to store the logs
""" # """
if not logger_info : # if not logger_info :
logger = factory.instance(type='disk.DiskWriter',args={'path':os.sep.join([info['out-folder'],SYS_ARGS['parse']+'.log'])}) # logger = factory.instance(type='disk.DiskWriter',args={'path':os.sep.join([info['out-folder'],SYS_ARGS['parse']+'.log'])})
else: # else:
logger = factory.instance(**logger_info) # logger = factory.instance(**logger_info)
writer = factory.instance(**store_info) # writer = factory.instance(**store_info)
for filename in files : # for filename in files :
if filename.strip() == '': # if filename.strip() == '':
continue # continue
# content,logs = get_content(filename,CONFIG,CONFIG['SECTION']) # # content,logs = get_content(filename,CONFIG,CONFIG['SECTION'])
# # #
try: # try:
content,logs = parse(filename = filename,type=SYS_ARGS['parse']) # content,logs = parse(filename = filename,type=SYS_ARGS['parse'])
if content : # if content :
writer.write(content) # writer.write(content)
if logs : # if logs :
[logger.write(dict(_row,**{"parse":SYS_ARGS['parse']})) for _row in logs] # [logger.write(dict(_row,**{"parse":SYS_ARGS['parse']})) for _row in logs]
else: # else:
logger.write({"parse":SYS_ARGS['parse'],"name":filename,"completed":True,"rows":len(content)}) # logger.write({"parse":SYS_ARGS['parse'],"name":filename,"completed":True,"rows":len(content)})
except Exception as e: # except Exception as e:
logger.write({"parse":SYS_ARGS['parse'],"filename":filename,"completed":False,"rows":-1,"msg":e.args[0]}) # logger.write({"parse":SYS_ARGS['parse'],"filename":filename,"completed":False,"rows":-1,"msg":e.args[0]})
# print ([filename,len(content)]) # # print ([filename,len(content)])
# # #
# @TODO: forward this data to the writer and log engine # # @TODO: forward this data to the writer and log engine
# #
def upgrade(**args): def upgrade(**args):
""" """
@ -200,13 +223,28 @@ def upgrade(**args):
""" """
url = args['url'] if 'url' in args else URL+"/upgrade" url = args['url'] if 'url' in args else URL+"/upgrade"
headers = {"key":args['key'],"email":args["email"],"url":url} headers = {"key":args['key'],"email":args["email"],"url":url}
def check(**_args):
"""
This function will check if there is an update available (versions are in the configuration file)
:param url
"""
url = _args['url'][:-1] if _args['url'].endswith('/') else _args['url']
url = url + "/version"
if 'version' not in _args :
version = {"_id":"version","current":0.0}
else:
version = _args['version']
http = requests.session()
r = http.get(url)
return r.json()
if __name__ == '__main__' : if __name__ == '__main__' :
info = init() info = init()
if 'out-folder' in SYS_ARGS : if 'out-folder' in SYS_ARGS :
OUTPUT_FOLDER = SYS_ARGS['out-folder'] OUTPUT_FOLDER = SYS_ARGS['out-folder']
SYS_ARGS['url'] = SYS_ARGS['url'] if 'url' in SYS_ARGS else URL
if set(list(SYS_ARGS.keys())) & set(['signup','init']): if set(list(SYS_ARGS.keys())) & set(['signup','init']):
# #
# This command will essentially get a new copy of the configurations # This command will essentially get a new copy of the configurations
@ -214,10 +252,10 @@ if __name__ == '__main__' :
# #
email = SYS_ARGS['signup'].strip() if 'signup' in SYS_ARGS else SYS_ARGS['init'] email = SYS_ARGS['signup'].strip() if 'signup' in SYS_ARGS else SYS_ARGS['init']
url = SYS_ARGS['url'] if 'url' in SYS_ARGS else 'https://healthcareio.the-phi.com' url = SYS_ARGS['url'] if 'url' in SYS_ARGS else URL
store = SYS_ARGS['store'] if 'store' in SYS_ARGS else 'sqlite' store = SYS_ARGS['store'] if 'store' in SYS_ARGS else 'sqlite'
db='healthcareio' if 'db' not in SYS_ARGS else SYS_ARGS['db'] db='healthcareio' if 'db' not in SYS_ARGS else SYS_ARGS['db']
register(email=email,url=url,store=store,db=db) signup(email=email,url=url,store=store,db=db)
# else: # else:
# m = """ # m = """
# usage: # usage:
@ -241,51 +279,31 @@ if __name__ == '__main__' :
if 'file' in SYS_ARGS : if 'file' in SYS_ARGS :
files = [SYS_ARGS['file']] if not os.path.isdir(SYS_ARGS['file']) else [] files = [SYS_ARGS['file']] if not os.path.isdir(SYS_ARGS['file']) else []
if 'folder' in SYS_ARGS and os.path.exists(SYS_ARGS['folder']): if 'folder' in SYS_ARGS and os.path.exists(SYS_ARGS['folder']):
names = os.listdir(SYS_ARGS['folder']) for root,_dir,f in os.walk(SYS_ARGS['folder']) :
files += [os.sep.join([SYS_ARGS['folder'],name]) for name in names if not os.path.isdir(os.sep.join([SYS_ARGS['folder'],name]))]
if f :
files += [os.sep.join([root,name]) for name in f]
# names = os.listdir(SYS_ARGS['folder'])
# files += [os.sep.join([SYS_ARGS['folder'],name]) for name in names if not os.path.isdir(os.sep.join([SYS_ARGS['folder'],name]))]
else: else:
# #
# raise an erro # raise an error
pass pass
# #
# if the user has specified to resume, we should look into the logs and pull the files processed and those that haven't # if the user has specified to resume, we should look into the logs and pull the files processed and those that haven't
# #
if 'resume' in SYS_ARGS : if 'resume' in SYS_ARGS :
files = resume(files,SYS_ARGS['parse'],info) store_config = json.loads( (open(os.sep.join([PATH,'config.json']))).read() )
print (["Found ",len(files)," files unprocessed"]) files = proxy.get.resume(files,store_config )
# print (["Found ",len(files)," files unprocessed"])
# #
# @TODO: Log this here so we know what is being processed or not # @TODO: Log this here so we know what is being processed or not
SCOPE = None SCOPE = None
if files : #and ('claims' in SYS_ARGS['parse'] or 'remits' in SYS_ARGS['parse']): if files : #and ('claims' in SYS_ARGS['parse'] or 'remits' in SYS_ARGS['parse']):
# logger = factory.instance(type='disk.DiskWriter',args={'path':os.sep.join([info['out-folder'],SYS_ARGS['parse']+'.log'])})
# if info['store']['type'] == 'disk.DiskWriter' :
# info['store']['args']['path'] += (os.sep + 'healthcare-io.json')
# elif info['store']['type'] == 'disk.SQLiteWriter' :
# # info['store']['args']['path'] += (os.sep + 'healthcare-io.db3')
# pass
# if info['store']['type'] == 'disk.SQLiteWriter' :
# info['store']['args']['table'] = SYS_ARGS['parse'].strip().lower()
# _info = json.loads(json.dumps(info['store']))
# _info['args']['table']='logs'
# else:
# #
# # if we are working with no-sql we will put the logs in it (performance )?
# info['store']['args']['doc'] = SYS_ARGS['parse'].strip().lower()
# _info = json.loads(json.dumps(info['store']))
# _info['args']['doc'] = 'logs'
# logger = factory.instance(**_info)
# writer = factory.instance(**info['store'])
#
# we need to have batches ready for this in order to run some of these queries in parallel
# @TODO: Make sure it is with a persistence storage (not disk .. not thread/process safe yet)
# - Make sure we can leverage this on n-cores later on, for now the assumption is a single core
#
BATCH_COUNT = 1 if 'batch' not in SYS_ARGS else int (SYS_ARGS['batch']) BATCH_COUNT = 1 if 'batch' not in SYS_ARGS else int (SYS_ARGS['batch'])
files = np.array_split(files,BATCH_COUNT) files = np.array_split(files,BATCH_COUNT)
@ -304,27 +322,7 @@ if __name__ == '__main__' :
while len(procs) > 0 : while len(procs) > 0 :
procs = [proc for proc in procs if proc.is_alive()] procs = [proc for proc in procs if proc.is_alive()]
time.sleep(2) time.sleep(2)
# for filename in files :
# if filename.strip() == '':
# continue
# # content,logs = get_content(filename,CONFIG,CONFIG['SECTION'])
# #
# try:
# content,logs = parse(filename = filename,type=SYS_ARGS['parse'])
# if content :
# writer.write(content)
# if logs :
# [logger.write(dict(_row,**{"parse":SYS_ARGS['parse']})) for _row in logs]
# else:
# logger.write({"parse":SYS_ARGS['parse'],"name":filename,"completed":True,"rows":len(content)})
# except Exception as e:
# logger.write({"parse":SYS_ARGS['parse'],"filename":filename,"completed":False,"rows":-1,"msg":e.args[0]})
# # print ([filename,len(content)])
# #
# # @TODO: forward this data to the writer and log engine
# #
pass pass
@ -337,103 +335,71 @@ if __name__ == '__main__' :
# PATH= SYS_ARGS['config'] if 'config' in SYS_ARGS else os.sep.join([os.environ['HOME'],'.healthcareio','config.json']) # PATH= SYS_ARGS['config'] if 'config' in SYS_ARGS else os.sep.join([os.environ['HOME'],'.healthcareio','config.json'])
e = analytics.engine(os.sep.join([PATH,'config.json'])) #--@TODO: make the configuration file globally accessible if os.path.exists(os.sep.join([PATH,'config.json'])) :
e.apply(type='claims',serialize=True) e = analytics.engine(os.sep.join([PATH,'config.json'])) #--@TODO: make the configuration file globally accessible
SYS_ARGS['engine'] = e e.apply(type='claims',serialize=True)
SYS_ARGS['engine'] = e
SYS_ARGS['config'] = json.loads(open(os.sep.join([PATH,'config.json'])).read())
else:
SYS_ARGS['config'] = {"owner":None,"store":None}
if 'args' not in SYS_ARGS['config'] :
SYS_ARGS['config']["args"] = {"batch":1,"resume":True,"folder":"/data"}
me = pd.DataFrame(smart.top.read(name='healthcare-io.py')).args.unique().tolist()
SYS_ARGS['me'] = me[0] #-- This key will identify the current process
pointer = lambda : server.app.run(host='0.0.0.0',port=PORT,debug=DEBUG,threaded=False) pointer = lambda : server.app.run(host='0.0.0.0',port=PORT,debug=DEBUG,threaded=False)
pthread = Process(target=pointer,args=()) pthread = Process(target=pointer,args=())
pthread.start() pthread.start()
elif 'check-update' in SYS_ARGS :
_args = {"url":SYS_ARGS['url']}
try:
if os.path.exists(os.sep.join([PATH,'config.json'])) :
SYS_ARGS['config'] = json.loads((open(os.sep.join([PATH,'config.json']))).read())
else:
SYS_ARGS['config'] = {}
if 'version' in SYS_ARGS['config'] :
_args['version'] = SYS_ARGS['config']['version']
version = check(**_args)
_version = {"current":0.0}if 'version' not in SYS_ARGS['config'] else SYS_ARGS['config']['version']
if _version['current'] != version['current'] :
print ()
print ("You need to upgrade your system to version to ",version['current'])
print ("\t- signup (for new configuration)")
print ("\t- use pip to upgrade the codebase")
else:
print ()
print ("You are running the current configuraiton version ",_version['current'])
except Exception as e:
print (e)
pass
elif 'export' in SYS_ARGS: elif 'export' in SYS_ARGS:
# #
# this function is designed to export the data to csv # this function is designed to export the data to csv
# #
format = SYS_ARGS['format'] if 'format' in SYS_ARGS else 'csv' path = SYS_ARGS['config']
format = format.lower() TYPE = SYS_ARGS['export'] if 'export' in SYS_ARGS else '835'
if set([format]) not in ['xls','csv'] : if not os.path.exists(path) or TYPE not in ['835','837']:
format = 'csv' print (HELP_MESSAGE)
else:
else: #
msg = """ # Let's run the export function ..., This will push files into a data-store of choice Redshift, PostgreSQL, MySQL ...
cli: #
_store = {"type":"sql.SQLWriter","args":json.loads( (open(path) ).read())}
healthcare-io.py --<[signup|init]> <email> --store <sqlite|mongo> [--batch <value>]
healthcare-io.py --parse claims --folder <path> [--batch <value>]
healthcare-io.py --parse remits --folder <path> [--batch <value>] [--resume]
parameters :
--<[signup|init]> signup or get a configuration file from a parsing server
--store data store mongo or sqlite or mongodb
--resume will attempt to resume if there was an interruption
"""
print(msg)
pass
# """
# The program was called from the command line thus we are expecting
# parse in [claims,remits]
# config os.sep.path.exists(path)
# folder os.sep.path.exists(path)
# store store ()
# """
# p = len( set(['store','config','folder']) & set(SYS_ARGS.keys())) == 3 and ('db' in SYS_ARGS or 'path' in SYS_ARGS)
# TYPE = {
# 'mongo':'mongo.MongoWriter',
# 'couch':'couch.CouchWriter',
# 'disk':'disk.DiskWriter'
# }
# INFO = {
# '837':{'scope':'claims','section':'HL'},
# '835':{'scope':'remits','section':'CLP'}
# }
# if p :
# args = {}
# scope = SYS_ARGS['config'][:-5].split(os.sep)[-1]
# CONTEXT = INFO[scope]['scope']
# #
# # @NOTE:
# # improve how database and data stores are handled.
# if SYS_ARGS['store'] == 'couch' :
# args = {'url': SYS_ARGS['url'] if 'url' in SYS_ARGS else 'http://localhost:5984'}
# args['dbname'] = SYS_ARGS['db']
# elif SYS_ARGS ['store'] == 'mongo': pipes = export.Factory.instance(type=TYPE,write_store=_store) #"inspect":0,"cast":0}})
# args = {'host':SYS_ARGS['host']if 'host' in SYS_ARGS else 'localhost:27017'} # pipes[0].run()
# if SYS_ARGS['store'] in ['mongo','couch']: for thread in pipes:
# args['dbname'] = SYS_ARGS['db'] if 'db' in SYS_ARGS else 'claims_outcomes' thread.start()
# args['doc'] = CONTEXT time.sleep(1)
while pipes :
pipes = [thread for thread in pipes if thread.is_alive()]
time.sleep(1)
# TYPE = TYPE[SYS_ARGS['store']]
# writer = factory.instance(type=TYPE,args=args)
# if SYS_ARGS['store'] == 'disk':
# writer.init(path = 'output-claims.json')
# logger = factory.instance(type=TYPE,args= dict(args,**{"doc":"logs"}))
# files = os.listdir(SYS_ARGS['folder'])
# CONFIG = json.loads(open(SYS_ARGS['config']).read())
# SECTION = INFO[scope]['section']
# for file in files : else:
# if 'limit' in SYS_ARGS and files.index(file) == int(SYS_ARGS['limit']) :
# break print(HELP_MESSAGE)
# else:
# filename = os.sep.join([SYS_ARGS['folder'],file])
# try:
# content,logs = get_content(filename,CONFIG,SECTION)
# except Exception as e:
# if sys.version_info[0] > 2 :
# logs = [{"filename":filename,"msg":e.args[0]}]
# else:
# logs = [{"filename":filename,"msg":e.message}]
# content = None
# if content :
# writer.write(content)
# if logs:
# logger.write(logs)
# pass
# else:
# print (__doc__)

@ -3,7 +3,78 @@ from healthcareio.params import SYS_ARGS
import healthcareio.analytics import healthcareio.analytics
import os import os
import json import json
import time
import smart
import transport
import pandas as pd
import numpy as np
from healthcareio import x12
from healthcareio.export import export
from multiprocessing import Process
# from flask_socketio import SocketIO, emit, disconnect,send
from healthcareio.server import proxy
PATH = os.sep.join([os.environ['HOME'],'.healthcareio','config.json'])
app = Flask(__name__) app = Flask(__name__)
# socket_ = SocketIO(app)
def resume (files):
_args = SYS_ARGS['config']['store'].copy()
if 'mongo' in SYS_ARGS['config']['store']['type'] :
_args['type'] = 'mongo.MongoReader'
reader = transport.factory.instance(**_args)
_files = []
try:
pipeline = [{"$match":{"completed":{"$eq":True}}},{"$group":{"_id":"$name"}},{"$project":{"name":"$_id","_id":0}}]
_args = {"aggregate":"logs","cursor":{},"allowDiskUse":True,"pipeline":pipeline}
_files = reader.read(mongo = _args)
_files = [item['name'] for item in _files]
except Exception as e :
pass
return list(set(files) - set(_files))
def run ():
#
# let's get the files in the folder (perhaps recursively traverse them)
#
FILES = []
BATCH = int(SYS_ARGS['config']['args']['batch']) #-- number of processes (poorly named variable)
for root,_dir,f in os.walk(SYS_ARGS['config']['args']['folder']) :
if f :
FILES += [os.sep.join([root,name]) for name in f]
FILES = resume(FILES)
FILES = np.array_split(FILES,BATCH)
procs = []
for FILE_GROUP in FILES :
FILE_GROUP = FILE_GROUP.tolist()
# logger.write({"process":index,"parse":SYS_ARGS['parse'],"file_count":len(row)})
# proc = Process(target=apply,args=(row,info['store'],_info,))
parser = x12.Parser(PATH) #os.sep.join([PATH,'config.json']))
parser.set.files(FILE_GROUP)
parser.start()
procs.append(parser)
SYS_ARGS['procs'] = procs
# @socket_.on('data',namespace='/stream')
def push() :
_args = dict(SYS_ARGS['config']['store'].copy(),**{"type":"mongo.MongoReader"})
reader = transport.factory.instance(**_args)
pipeline = [{"$group":{"_id":"$parse","claims":{"$addToSet":"$name"}}},{"$project":{"_id":0,"type":"$_id","count":{"$size":"$claims"}}}]
_args = {"aggregate":"logs","cursor":{},"allowDiskUse":True,"pipeline":pipeline}
r = pd.DataFrame(reader.read(mongo=_args))
r = healthcareio.analytics.Apex.apply({"chart":{"type":"donut","axis":{"x":"count","y":"type"}},"data":r})
# emit("update",r,json=True)
return r
# @socket_.on('connect')
# def client_connect(**r):
# print ('Connection received')
# print (r)
# push()
# pass
@app.route("/favicon.ico") @app.route("/favicon.ico")
def _icon(): def _icon():
return send_from_directory(os.path.join([app.root_path, 'static','img','logo.svg']), return send_from_directory(os.path.join([app.root_path, 'static','img','logo.svg']),
@ -12,7 +83,7 @@ def _icon():
def init(): def init():
e = SYS_ARGS['engine'] e = SYS_ARGS['engine']
sections = {"remits":e.info['835'],"claims":e.info['837']} sections = {"remits":e.info['835'],"claims":e.info['837']}
_args = {"sections":sections} _args = {"sections":sections,"store":SYS_ARGS["config"]["store"],"owner":SYS_ARGS['config']['owner'],"args":SYS_ARGS["config"]["args"]}
return render_template("index.html",**_args) return render_template("index.html",**_args)
@app.route("/format/<id>/<index>",methods=['POST']) @app.route("/format/<id>/<index>",methods=['POST'])
def _format(id,index): def _format(id,index):
@ -21,43 +92,117 @@ def _format(id,index):
key = '837' if id == 'claims' else '835' key = '837' if id == 'claims' else '835'
index = int(index) index = int(index)
# p = e.info[key][index] # p = e.info[key][index]
p = e.apply(type=id,index=index) p = e.filter(type=id,index=index)
#
r = [] r = []
for item in p[0]['pipeline'] : for item in p['pipeline'] :
_item= dict(item) _item= dict(item)
del _item['sql']
del _item ['data']
_item = dict(_item,**healthcareio.analytics.Apex.apply(item)) _item = dict(_item,**healthcareio.analytics.Apex.apply(item))
del _item['data']
if 'apex' in _item or 'html' in _item: if 'apex' in _item or 'html' in _item:
r.append(_item) r.append(_item)
r = {"id":p[0]['id'],"pipeline":r}
r = {"id":p['id'],"pipeline":r}
return json.dumps(r),200 return json.dumps(r),200
@app.route("/get/<id>/<index>",methods=['GET']) @app.route("/get/<id>/<index>",methods=['GET'])
def get(id,index): def get(id,index):
e = SYS_ARGS['engine'] e = SYS_ARGS['engine']
key = '837' if id == 'claims' else '835' key = '837' if id == 'claims' else '835'
index = int(index) index = int(index)
# p = e.info[key][index] # p = e.info[key][index]
p = e.apply(type=id,index=index) p = e.filter(type=id,index=index)
r = {} r = {}
for item in p[0]['pipeline'] : for item in p[0]['pipeline'] :
_item= [dict(item)] _item= [dict(item)]
r[item['label']] = item['data'].to_dict(orient='record') # r[item['label']] = item['data'].to_dict(orient='record')
# del _item['sql'] r[item['label']] = item['data'].to_dict('record')
# del _item ['data']
# print (item['label'])
# _item['apex'] = healthcareio.analytics.Apex.apply(item)
# if _item['apex']:
# r.append(_item)
# r = {"id":p[0]['id'],"pipeline":r}
return json.dumps(r),200 return json.dumps(r),200
@app.route("/reset",methods=["POST"])
def reset():
return "1",200
@app.route("/data",methods=['GET'])
def get_data ():
"""
This function will return statistical data about the services i.e general statistics about what has/been processed
"""
HEADER = {"Content-type":"application/json"}
_args = SYS_ARGS['config']
options = dict(proxy.get.files(_args),**proxy.get.processes(_args))
return json.dumps(options),HEADER
@app.route("/log/<id>",methods=["POST","PUT","GET"])
def log(id) :
HEADER = {"Content-Type":"application/json; charset=utf8"}
if id == 'params' and request.method in ['PUT', 'POST']:
info = request.json
_args = {"batch":info['batch'] if 'batch' in info else 1,"resume":True}
#
# We should update the configuration
SYS_ARGS['config']['args'] = _args
PATH = os.sep.join([os.environ['HOME'],'.healthcareio','config.json'])
write = lambda content: (open(PATH,'w')).write(json.dumps(content))
proc = Process(target=write,args=(SYS_ARGS['config'],))
proc.start()
return "1",HEADER
pass
@app.route("/io/<id>",methods=['POST'])
def io_data(id):
if id == 'params' :
_args = request.json
#
# Expecting batch,folder as parameters
_args = request.json
_args['resume'] = True
print (_args)
#
# We should update the configuration
SYS_ARGS['config']['args'] = _args
# PATH = os.sep.join([os.environ['HOME'],'.healthcareio','config.json'])
try:
write = lambda content: (open(PATH,'w')).write(json.dumps(content))
proc = Process(target=write,args=(SYS_ARGS['config'],))
proc.start()
# proc.join()
return "1",200
except Exception as e :
return "0",403
pass
elif id == 'stop' :
stop()
pass
elif id == 'run' :
# run()
_args = {"args":SYS_ARGS['config']['args'],"store":SYS_ARGS["config"]["store"]}
proxy.run(_args)
return "1",200
pass
@app.route("/export")
def export_form():
_args = {"context":SYS_ARGS['context']}
return render_template("store.html",**_args)
@app.route("/export",methods=['POST','PUT'])
def apply_etl():
_info = request.json
m = {'s3':'s3.s3Writer','mongo':'mongo.MongoWriter'}
if _info :
dest_args = {'type':m[_info['type']],"args": _info['content'] }
src_args = SYS_ARGS['config']['store']
# print (_args)
# writer = transport.factory.instance(**_args)
proxy.publish(src_args,dest_args)
return "1",405
else:
return "0",404
@app.route("/update")
def update():
pass
return "0",405
@app.route("/reload",methods=['POST']) @app.route("/reload",methods=['POST'])
def reload(): def reload():
# e = SYS_ARGS['engine'] # e = SYS_ARGS['engine']
@ -74,11 +219,20 @@ if __name__ == '__main__' :
PORT = int(SYS_ARGS['port']) if 'port' in SYS_ARGS else 5500 PORT = int(SYS_ARGS['port']) if 'port' in SYS_ARGS else 5500
DEBUG= int(SYS_ARGS['debug']) if 'debug' in SYS_ARGS else 0 DEBUG= int(SYS_ARGS['debug']) if 'debug' in SYS_ARGS else 0
SYS_ARGS['context'] = SYS_ARGS['context'] if 'context' in SYS_ARGS else '' SYS_ARGS['context'] = SYS_ARGS['context'] if 'context' in SYS_ARGS else ''
# #
# #
PATH= SYS_ARGS['config'] if 'config' in SYS_ARGS else os.sep.join([os.environ['HOME'],'.healthcareio','config.json']) PATH= SYS_ARGS['config'] if 'config' in SYS_ARGS else os.sep.join([os.environ['HOME'],'.healthcareio','config.json'])
#
# Adjusting configuration with parameters (batch,folder,resume)
if 'args' not in SYS_ARGS['config'] :
SYS_ARGS['config']["args"] = {"batch":1,"resume":True,"folder":"/data"}
SYS_ARGS['procs'] = []
# SYS_ARGS['path'] = os.sep.join([os.environ['HOME'],'.healthcareio','config.json'])
e = healthcareio.analytics.engine(PATH) e = healthcareio.analytics.engine(PATH)
# e.apply(type='claims',serialize=True) e.apply(type='claims',serialize=False)
SYS_ARGS['engine'] = e SYS_ARGS['engine'] = e
app.run(host='0.0.0.0',port=PORT,debug=DEBUG,threaded=True) app.run(host='0.0.0.0',port=PORT,debug=DEBUG,threaded=True)

@ -12,8 +12,9 @@ def _icon():
def init(): def init():
e = SYS_ARGS['engine'] e = SYS_ARGS['engine']
sections = {"remits":e.info['835'],"claims":e.info['837']} sections = {"remits":e.info['835'],"claims":e.info['837']}
_args = {"sections":sections} _args = {"sections":sections,"store":SYS_ARGS['config']['store']}
return render_template("index.html",**_args) print (SYS_ARGS['config']['store'])
return render_template("setup.html",**_args)
@app.route("/format/<id>/<index>",methods=['POST']) @app.route("/format/<id>/<index>",methods=['POST'])
def _format(id,index): def _format(id,index):

@ -0,0 +1,170 @@
"""
This file serves as proxy to healthcare-io, it will be embedded into the API
"""
import os
import transport
import numpy as np
from healthcareio import x12
import pandas as pd
import smart
from healthcareio.analytics import Apex
import time
class get :
PROCS = []
PATH = os.sep.join([os.environ['HOME'],'.healthcareio','config.json'])
@staticmethod
def resume (files,args):
"""
This function will determine the appropriate files to be processed by performing a simple complementary set operation against the logs
@TODO: Support data-stores other than mongodb
:param files list of files within a folder
:param _args configuration
"""
_args = args['store'].copy()
if 'mongo' in _args['type'] :
_args['type'] = 'mongo.MongoReader'
reader = transport.factory.instance(**_args)
_files = []
try:
pipeline = [{"$match":{"completed":{"$eq":True}}},{"$group":{"_id":"$name"}},{"$project":{"name":"$_id","_id":0}}]
_args = {"aggregate":"logs","cursor":{},"allowDiskUse":True,"pipeline":pipeline}
_files = reader.read(mongo = _args)
_files = [item['name'] for item in _files]
except Exception as e :
pass
print ( [len(list(set(files) - set(_files))),' files to be processed'])
return list(set(files) - set(_files))
@staticmethod
def processes(_args):
_info = pd.DataFrame(smart.top.read(name='healthcare-io.py'))[['name','cpu','mem']]
if _info.shape[0] == 0 :
_info = pd.DataFrame({"name":["healthcare-io.py"],"cpu":[0],"mem":[0]})
# _info = pd.DataFrame(_info.groupby(['name']).sum())
# _info['name'] = ['healthcare-io.py']
m = {'cpu':'CPU','mem':'RAM','name':'name'}
_info.columns = [m[name] for name in _info.columns.tolist()]
_info.index = np.arange(_info.shape[0])
charts = []
for label in ['CPU','RAM'] :
value = _info[label].sum()
df = pd.DataFrame({"name":[label],label:[value]})
charts.append (
Apex.apply(
{"data":df, "chart":{"type":"radial","axis":{"x":label,"y":"name"}}}
)['apex']
)
#
# This will update the counts for the processes, upon subsequent requests so as to show the change
#
N = 0
lprocs = []
for proc in get.PROCS :
if proc.is_alive() :
lprocs.append(proc)
N = len(lprocs)
get.PROCS = lprocs
return {"process":{"chart":charts,"counts":N}}
@staticmethod
def files (_args):
_info = smart.folder.read(path='/data')
N = _info.files.tolist()[0]
if 'mongo' in _args['store']['type'] :
store_args = dict(_args['store'].copy(),**{"type":"mongo.MongoReader"})
# reader = transport.factory.instance(**_args)
pipeline = [{"$group":{"_id":"$name","count":{"$sum":{"$cond":[{"$eq":["$completed",True]},1,0]}} }},{"$group":{"_id":None,"count":{"$sum":"$count"}}},{"$project":{"_id":0,"status":"completed","count":1}}]
query = {"mongo":{"aggregate":"logs","allowDiskUse":True,"cursor":{},"pipeline":pipeline}}
# _info = pd.DataFrame(reader.read(mongo={"aggregate":"logs","allowDiskUse":True,"cursor":{},"pipeline":pipeline}))
pipeline = [{"$group":{"_id":"$parse","claims":{"$addToSet":"$name"}}},{"$project":{"_id":0,"type":"$_id","count":{"$size":"$claims"}}}]
_query = {"mongo":{"aggregate":"logs","cursor":{},"allowDiskUse":True,"pipeline":pipeline}} #-- distribution claims/remits
else:
store_args = dict(_args['store'].copy(),**{"type":"disk.SQLiteReader"})
store_args['args']['table'] = 'logs'
query= {"sql":"select count(distinct json_extract(data,'$.name')) as count, 'completed' status from logs where json_extract(data,'$.completed') = true"}
_query={"sql":"select json_extract(data,'$.parse') as type,count(distinct json_extract(data,'$.name')) as count from logs group by type"} #-- distribution claim/remits
reader = transport.factory.instance(**store_args)
_info = pd.DataFrame(reader.read(**query))
if not _info.shape[0] :
_info = pd.DataFrame({"status":["completed"],"count":[0]})
_info['count'] = np.round( (_info['count'] * 100 )/N,2)
charts = [Apex.apply({"data":_info,"chart":{"type":"radial","axis":{"y":"status","x":"count"}}})['apex']]
#
# Let us classify the files now i.e claims / remits
#
# pipeline = [{"$group":{"_id":"$parse","claims":{"$addToSet":"$name"}}},{"$project":{"_id":0,"type":"$_id","count":{"$size":"$claims"}}}]
# _args = {"aggregate":"logs","cursor":{},"allowDiskUse":True,"pipeline":pipeline}
# r = pd.DataFrame(reader.read(mongo=_args))
r = pd.DataFrame(reader.read(**_query)) #-- distribution claims/remits
r = Apex.apply({"chart":{"type":"donut","axis":{"x":"count","y":"type"}},"data":r})['apex']
r['chart']['height'] = '100%'
r['legend']['position'] = 'bottom'
charts += [r]
return {"files":{"counts":N,"chart":charts}}
pass
#
# Process handling ....
def run (_args) :
"""
This function will run the jobs and insure as processes (as daemons).
:param _args system configuration
"""
FILES = []
BATCH = int(_args['args']['batch']) #-- number of processes (poorly named variable)
for root,_dir,f in os.walk(_args['args']['folder']) :
if f :
FILES += [os.sep.join([root,name]) for name in f]
FILES = get.resume(FILES,_args)
FILES = np.array_split(FILES,BATCH)
for FILE_GROUP in FILES :
FILE_GROUP = FILE_GROUP.tolist()
# logger.write({"process":index,"parse":_args['parse'],"file_count":len(row)})
# proc = Process(target=apply,args=(row,info['store'],_info,))
parser = x12.Parser(get.PATH) #os.sep.join([PATH,'config.json']))
parser.set.files(FILE_GROUP)
parser.daemon = True
parser.start()
get.PROCS.append(parser)
time.sleep(3)
#
# @TODO:consider submitting an update to clients via publish/subscribe framework
#
return get.PROCS
def stop(_args):
for job in get.PROCS :
if job.is_alive() :
job.terminate()
get.PROCS = []
#
# @TODO: consider submitting an update to clients via publish/subscribe framework
pass
def write(src_args,dest_args,files) :
#
# @TODO: Support for SQLite
pass
def publish (src_args,dest_args,folder="/data"):
FILES = []
for root,_dir,f in os.walk(folder) :
if f :
FILES += [os.sep.join([root,name]) for name in f]
#
# @TODO: Add support for SQLite ....
FILES = np.array_split(FILES,4)

@ -1,3 +1,4 @@
.active { .active {
padding:4px; padding:4px;
cursor:pointer; cursor:pointer;
@ -6,3 +7,51 @@
.active:hover{ .active:hover{
border-bottom:2px solid #ff6500; border-bottom:2px solid #ff6500;
} }
input[type=text]{
border:1px solid transparent;
background-color:#f3f3f3;
outline: 0px;
padding:8px;
font-weight:normal;
font-family:sans-serif;
color:black;
}
.active-button {
display:grid;
grid-template-columns: 32px auto;
gap:2px;
align-items:center;
border:2px solid #CAD5E0;
cursor:pointer;
}
.active-button i {padding:4px;;}
.active-button:hover { border-color:#ff6500}
.system {display:grid; grid-template-columns: 45% 1px auto; gap:20px; margin-left:5%; width:90%;}
.system .status .item {display:grid; grid-template-columns: 75px 8px auto; gap:2px;}
.input-form {display:grid; gap:2px;}
.input-form .item {display:grid; grid-template-columns: 125px auto; gap:2px; align-items:center;}
.input-form .item .label { font-weight:bold; padding-left:10px}
.fa-cog {color:#4682B4}
.fa-check {color:#00c6b3}
.fa-times {color:maroon}
.code {
margin:4px;
background:#000000 ;
padding:8px;
font-family: 'Courier New', Courier, monospace;
color:#d3d3d3;
font-size:12px;
line-height: 2;
}
.tabs {display:grid; grid-template-columns: repeat(3,1fr) auto; gap:0px; align-items:center; text-align: center;}
.tab {border:1px solid transparent; border-bottom-color:#D3D3D3; font-weight:bold; padding:4px}
.tabs .selected {border-color:#CAD5E0; border-bottom-color:transparent; }
.system iframe {width:100%; height:100%; border:1px solid transparent;}
.data-info {height:90%; padding:8px;}
.fa-cloud {color:#4682B4}
.fa-database{color:#cc8c91}

@ -0,0 +1,21 @@
<div class="dialog">
<div class="title-bar">
<div class="title bold" ></div>
<div class="active close" align="center"><i class="fas fa-times"></i></div>
</div>
<div class="message">
<div class="icon" align="center">
<i id="msg-icon"></i>
</div>
<div class="text"></div>
</div>
<div class="action">
<div class="active-button border-round" align="center">
<div align="center">
<i class="fas fa-check"></i>
</div>
<div class="bold">Ok</div>
</div>
</div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@ -0,0 +1,75 @@
/***
* This file will handle the dialog boxes as they and their associated configurations and function binding
*/
if (!dialog){
var dialog = {}
}
dialog.open = function(title,msg,pointer){
if (sessionStorage.dialog == null){
var http = HttpClient.instance()
http.get(sessionStorage.io_context+'/static/dialog.html',function(x){
var html = x.responseText
jx.modal.show({html:html,id:'dialog'})
$('.dialog .title').text(title)
$('.dialog .message .text').text(msg)
dialog.status.ask()
$('.dialog .action .active-button').on('click',pointer)
$('.dialog .title-bar .close').on('click',function(){dialog.close(0)})
})
}else{
var html = sessionStorage.dialog
jx.modal.show({html:html,id:'dialog'})
dialog.status.ask()
$('.dialog .action .active-button').on('click',pointer)
$('.dialog .title-bar .close').on('click',function(){dialog.close(0)})
}
}
dialog.bind = function(pointer){
if (pointer == null){
pointer = dialog.close
}
$('.dialog .action .active-button').off()
$('.dialog .action .active-button').on('click',pointer)
}
dialog.close = function(delay){
delay = (delay == null)?1750:delay
setTimeout(function(){
if ( $('.dialog').length > 0){
jx.modal.close()
}
},delay)
}
dialog.status = {}
dialog.status.wait = function(){
$('.dialog .action .active-button').hide()
}
dialog.status.confirm = function(){
$('.dialog .action .active-button').show()
}
dialog.status.busy = function(){
$('.dialog .message #msg-icon').removeClass()
$('.dialog .message #msg-icon').addClass('fas fa-cog fa-4x fa-spin')
}
dialog.status.fail = function(){
$('.dialog .message #msg-icon').removeClass()
$('.dialog .message #msg-icon').addClass('fas fa-times fa-4x')
}
dialog.status.ask = function(){
$('.dialog .message #msg-icon').removeClass()
$('.dialog .message #msg-icon').addClass('far fa-question-circle fa-4x')
}
dialog.status.warn = function(){
$('.dialog .message #msg-icon').removeClass()
$('.dialog .message #msg-icon').addClass('fas fa-exclamation-triangle fa-4x')
}
dialog.status.success = function(){
$('.dialog .message #msg-icon').removeClass()
$('.dialog .message #msg-icon').addClass('fas fa-check fa-4x')
}

@ -0,0 +1,15 @@
if (!healthcare) {
var healthcare = {io:{}}
}
healthcare.io = {'dialog':dialog,'confirmed':confirmed,'reset':reset,'update':update,'run':run,'publish':publish}
healthcare.io.apply = function(){
var value = $('.input-form .item .procs').val()
var folder= $('.input-form .item .folder').val()
$('.code .batch').html(value)
var http = HttpClient.instance()
http.setData({"batch":value,"resume":true,"folder":folder},"application/json")
http.post(sessionStorage.io_context+'/io/params',function(x){})
}

@ -0,0 +1,182 @@
/**
* This file will depend on dialog.js (soft dependency). Some functions here will make calls to resources in dialog.js
*/
var reset = function(){
dialog.open('Healthcare/IO::Parser', 'Are you sure you would like to delete all data parsed? Click Ok to confirm',confirmed.reset)
}
var update= function(){
dialog.open('Healthcare/IO::Parser','Update will change parsing configuration. Would you like to continue ?',confirmed.update)
}
var run = function(){
dialog.open('Healthcare/IO::Parser','Preparing parser, confirm to continue',confirmed.run)
}
var _queue = {socket:null}
var confirmed = {}
confirmed.run = function(){
dialog.status.busy()
dialog.status.wait()
$('.dialog .message .text').html('Initiating Parsing ...')
setTimeout(function(){
var http = HttpClient.instance()
http.post(sessionStorage.io_context+'/io/run',function(x){
// dialog.handler = setInterval(function(){monitor.data()},750)
monitor.data()
//dialog.close()
})
},1000)
}
confirmed.reset = function(){
var uri = sessionStorage.io_context+'/reset'
var http= HttpClient.instance()
dialog.status.busy()
dialog.status.wait()
http.post(uri,function(x){
setTimeout(function(){
if (x.status == 200 && x.responseText == "1"){
dialog.status.success()
$('.dialog .message .text').html('Reset Healthcare/IO::Parser was successful!<br><div align="center">Dialog will be closing</div>')
dialog.close()
}else{
dialog.status.fail()
}
},2000)
})
}
confirmed.update = function(){
var uri = sessionStorage.io_context+'/update'
var email = $('#email').val()
//
//-- validate the email
if (email.match(/^([^\s]+)@([^\s@]+)\.(org|com|edu|io)$/i)){
dialog.status.wait()
dialog.status.busy()
var http = HttpClient.instance()
http.setData({"email":email},"application/son")
setTimeout(function(){
http.post(uri,function(x){
if(x.status == 200 && x.responseText == "1"){
dialog.status.success()
}else{
dialog.status.fail()
$('.dialog .message .text').html('Error code '+x.status)
dialog.bind()
dialog.status.confirm()
$('.dialog .title-bar .title').html("Error found")
}
})
},1000)
}else{
dialog.status.fail()
dialog.bind()
$('.dialog .title-bar .title').text("Error found")
$('.dialog .message .text').html('Invvalid Email entered')
dialog.status.confirm()
}
}
/**
* This namespace is designed to export data to either the cloud or to a database
*/
var publish={set:{}}
publish.post = function(){
if($('.jxmodal').length > 0){
jx.modal.close()
}
dialog.open('Export/ETL','Please wait')
dialog.status.busy()
var http = HttpClient.instance()
http.setData(JSON.parse(sessionStorage.export),"application/json")
http.post(sessionStorage.io_context+'/export',function(x){
if (x.status != 200){
setTimeout(function(){
$('.dialog .message .text').html('An error occurred with code '+x.status)
dialog.status.fail()
dialog.status.wait()
},1500)
}
//
// @TODO: Have progress be monitored for this bad boy i.e open the connection to socket and read in ...
//
})
}
publish.set.file = function(){
var file = $('#file')[0].files[0]
$('.file .name').html(file.name)
var button = $('.cloud input').prop('disabled',true)
var div = $('.cloud .file .fa-file-upload')[0]
$(div).empty()
$(div).addClass('fas fa-cog fa-spin')
var reader = new FileReader()
reader.readAsText(file)
reader.onload = function(){
_args = {"type":$('.cloud .id').html().trim(),"content":reader.result}
// _args = JSON.stringify(_args)
if (_args.content.match(/^\{.+/i) == null){
content = _args.content.split('\n')[1].split(',')
_args.content = {'bucket':'healthcareio','access_key':content[0].trim(),'secret_key':content[1].trim()}
}
sessionStorage.export = JSON.stringify(_args)
}
reader.onloadend = function(){
setTimeout(function(){
var div = $('.cloud .file .fa-cog')[0]
$(div).empty()
$(div).addClass('fas fa-check')
$(div).removeClass('fa-spin')
// jx.modal.close()
//setTimeout(jx.modal.close,1500)
publish.post()
},2000)
}
}
publish.database = {}
publish.database.init = function(id){
//
// we are expecting id in {mongo,couch,postgresql,mysql,sqlite}
// @TODO: Account for cloud service brokers like dropbox, box, one-drive and google-drive
sessionStorage.export = "{}"
p = {'id':id}
if (id.match(/(mongodb|postgresql|mysql|sqlite|couchdb)/i)){
var hide_id = '.store .cloud'
var show_id = '.store .database'
}else{
//
// @TODO: generate an error message
var show_id = '.store .cloud'
var hide_id = '.store .database'
}
var http = HttpClient.instance()
http.get(sessionStorage.io_context+'/export',function(x){
var html = x.responseText
jx.modal.show({'html':html,'id':'dialog'})
$(hide_id).hide(function(){
$(show_id).show()
})
$('.store .id').text(id)
})
}

@ -12,119 +12,128 @@
* Improve on how returned data is handled (if necessary). * Improve on how returned data is handled (if necessary).
*/ */
if(!jx){ if(!jx){
var jx = {} var jx = {}
} }
/** /**
* These are a few parsers that can come in handy: * These are a few parsers that can come in handy:
* urlparser: This parser is intended to break down a url parameter string in key,value pairs * urlparser: This parser is intended to break down a url parameter string in key,value pairs
*/ */
function urlparser(url){ function urlparser(url){
if(url.toString().match(/\x3F/) != null){ if(url.toString().match(/\x3F/) != null){
url = url.split('\x3F')[1] url = url.split('\x3F')[1]
} }
var p = url.split('&') ; var p = url.split('&') ;
var r = {} ; var r = {} ;
r.meta = [] ; r.meta = [] ;
r.data = {} ; r.data = {} ;
var entry; var entry;
for(var i=0; i < p.length; i++){ for(var i=0; i < p.length; i++){
entry = p[i] ; entry = p[i] ;
key = (entry.match('(.*)=') !=null)? entry.match('(.*)=')[1]:null ; key = (entry.match('(.*)=') !=null)? entry.match('(.*)=')[1]:null ;
value = (entry.match('=(.*)$') != null)? entry.match('=(.*)$')[1]:null value = (entry.match('=(.*)$') != null)? entry.match('=(.*)$')[1]:null
if(key != null){ if(key != null){
key = key.replace('\x3F','') key = key.replace('\x3F','')
r.meta.push(key) ; r.meta.push(key) ;
r.data[key] = value ; r.data[key] = value ;
} }
} }
return r.data; return r.data;
} }
/** /**
* The following are corrections related to consistency in style & cohesion * The following are corrections related to consistency in style & cohesion
*/ */
jx.ajax = {} jx.ajax = {}
jx.ajax.get = {} ; jx.ajax.get = {} ;
jx.ajax.debug = null; jx.ajax.debug = null;
jx.ajax.get.instance = function(){ jx.ajax.get.instance = function(){
var factory = function(){ var factory = function(){
this.obj = {} this.obj = {}
this.obj.headers = {} this.obj.headers = {}
this.obj.async = true; this.obj.async = true;
this.setHeader = function(key,value){ this.setHeader = function(key,value){
if(key.constructor != String && value == null){ if(key.constructor != String && value == null){
this.obj.headers = key ; this.obj.headers = key ;
}else{ }else{
this.obj.headers[key] = value; this.obj.headers[key] = value;
} }
} }
this.setData = function(data){ this.setData = function(data,mimetype){
this.obj.data = data; if(mimetype == null)
} this.obj.data = data;
this.setAsync = function(flag){ else {
this.obj.async = (flag == true) ; this.obj.headers['Content-Type'] = mimetype
} if(mimetype.match(/application\/json/i)){
this.send = function(url,callback,method){ this.obj.data = JSON.stringify(data)
}
if(method == null){ }
method = 'GET'
} }
this.setAsync = function(flag){
p = jx.ajax.debug != null; this.obj.async = (flag == true) ;
q = false; }
if(p){ this.send = function(url,callback,method){
q = jx.ajax.debug[url] != null;
} if(method == null){
method = 'GET'
is_debuggable = p && q }
if(is_debuggable){ p = jx.ajax.debug != null;
x = {} ; q = false;
x.responseText = jx.ajax.debug [url] ; if(p){
callback(x) q = jx.ajax.debug[url] != null;
}else{ }
var http = new XMLHttpRequest() ;
http.onreadystatechange = function(){ is_debuggable = p && q
if(http.readyState == 4){
if(is_debuggable){
callback(http) x = {} ;
} x.responseText = jx.ajax.debug [url] ;
} callback(x)
// }else{
// In order to insure backward compatibility var http = new XMLHttpRequest() ;
// Previous versions allowed the user to set the variable on the wrapper (poor design) http.onreadystatechange = function(){
if(this.async != null){ if(http.readyState == 4){
this.setAsync(this.async) ;
} callback(http)
http.open(method,url,this.obj.async) ; }
for(key in this.obj.headers){ }
value = this.obj.headers[key] ; //
// In order to insure backward compatibility
http.setRequestHeader(key,value) // Previous versions allowed the user to set the variable on the wrapper (poor design)
} if(this.async != null){
this.setAsync(this.async) ;
http.send(this.obj.data) }
} http.open(method,url,this.obj.async) ;
for(key in this.obj.headers){
value = this.obj.headers[key] ;
}
this.put = function(url,callback){ http.setRequestHeader(key,value)
this.send(url,callback,'PUT') ; }
}
this.get = function(url,callback){ http.send(this.obj.data)
this.send(url,callback,'GET') ; }
}
this.post = function(url,callback){
this.send(url,callback,'POST') ; }
} this.put = function(url,callback){
}//-- end of the factory method this.send(url,callback,'PUT') ;
return new factory() ; }
} this.get = function(url,callback){
this.send(url,callback,'GET') ;
// }
// backward compatibility this.post = function(url,callback){
jx.ajax.getInstance = jx.ajax.get.instance ; this.send(url,callback,'POST') ;
var HttpClient = jx.ajax.get ; }
}//-- end of the factory method
return new factory() ;
}
//
// backward compatibility
jx.ajax.getInstance = jx.ajax.get.instance ;
var HttpClient = jx.ajax.get ;

@ -0,0 +1,29 @@
<meta charset="utf8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<link rel="shortcut icon" href="{{context}}/static/img/logo.svg" type="image/icon type">
<link rel="stylesheet" href="{{context}}/static/css/default.css" type="text/css">
<script src="{{context}}/static/js/jx/rpc.js"></script>
<script src="{{context}}/static/js/jx/dom.js"></script>
<script src="{{context}}/static/js/jx/utils.js"></script>
<script src="{{context}}/static/js/jquery.js"></script>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<link href="{{context}}/static/css/borders.css" type="text/css" rel="stylesheet">
<link href="{{context}}/static/css/fa/css/all.css" type="text/css" rel="stylesheet">
<script src="{{context}}/static/css/fa/js/all.js"></script>
<div class="border-round border menu-bar">
<div class="menu">
Admin
<div class="menu-items border">
<div class="item">Setup</div>
</div>
</div>
<div class="menu">
Claims & Remits
</div>
</div>

@ -8,6 +8,7 @@
<script src="{{context}}/static/js/jx/rpc.js"></script> <script src="{{context}}/static/js/jx/rpc.js"></script>
<script src="{{context}}/static/js/jx/dom.js"></script> <script src="{{context}}/static/js/jx/dom.js"></script>
<script src="{{context}}/static/js/jx/utils.js"></script> <script src="{{context}}/static/js/jx/utils.js"></script>
<script src="{{context}}/static/js/jx/ext/modal.js"></script>
<script src="{{context}}/static/js/jquery.js"></script> <script src="{{context}}/static/js/jquery.js"></script>
@ -15,6 +16,9 @@
<link href="{{context}}/static/css/borders.css" type="text/css" rel="stylesheet"> <link href="{{context}}/static/css/borders.css" type="text/css" rel="stylesheet">
<link href="{{context}}/static/css/fa/css/all.css" type="text/css" rel="stylesheet"> <link href="{{context}}/static/css/fa/css/all.css" type="text/css" rel="stylesheet">
<script src="{{context}}/static/css/fa/js/all.js"></script> <script src="{{context}}/static/css/fa/js/all.js"></script>
<script src="{{context}}/static/js/io/dialog.js"></script>
<script src="{{context}}/static/js/io/io.js"></script>
<script src="{{context}}/static/js/io/healthcare.js"></script>
<style> <style>
body { body {
font-size:16px; font-size:16px;
@ -64,6 +68,7 @@
scroll-behavior: smooth; scroll-behavior: smooth;
gap:2px; gap:2px;
padding:4px; padding:4px;
height:95%;
} }
@ -81,12 +86,12 @@
} }
.dashboard .chart-pane .chart { .dashboard .chart-pane .chart2 {
max-height:99%; max-height:99%;
min-height:99%; min-height:99%;
height:99%; height:99%;
} }
.dashboard .chart-pane .chart .graph { .dashboard .chart-pane .chart2 .graph {
max-height:100%; max-height:100%;
@ -95,7 +100,7 @@
} }
.dashboard .chart-pane .chart .graph .apexcharts-svg { .dashboard .chart-pane .chart2 .graph .apexcharts-svg {
/*border-radius:8px;*/ /*border-radius:8px;*/
background-color:#f3f3f3; background-color:#f3f3f3;
max-height:100%; max-height:100%;
@ -161,7 +166,7 @@
} }
.gradient { background-image: linear-gradient(to top,#F3F3F3, #D3D3D3, #F3F3F3);} .gradient { background-image: linear-gradient(to top,#F3F3F3, #FFFFFF, #FFFFFF);}
.white {color:#ffffff} .white {color:#ffffff}
.scalar { .scalar {
display:grid; display:grid;
@ -172,23 +177,39 @@
} }
.shadow { .shadow {
box-shadow: 0px 4px 4px #d3d3d3; box-shadow: 0px 4px 4px #d3d3d3;
} }
.scalar-title { padding:8px; text-transform: capitalize; } .scalar-title { padding:8px; text-transform: capitalize; }
.scalar .value {font-size:32px; font-weight:bold; margin:4%;} .scalar .value {font-size:32px; margin:4%;}
.scalar .label {font-size:12px; text-transform:capitalize; text-overflow: ellipsis; display:grid; align-items: flex-end; text-align:center ;} .scalar .label {font-size:12px; text-transform:capitalize; text-overflow: ellipsis; display:grid; align-items: flex-end; text-align:center ;}
.monthly_patient_count, .taxonomy_code_distribution, .top_adjustment_codes, .adjustment_reasons {
grid-row:1 / span 3 ;
}
</style> </style>
<script> <script>
sessionStorage.io_context = "{{context}}" sessionStorage.io_context = "{{context}}"
var plot = function(id,index){ var plot = function(id,index){
$('.system').slideUp(function(){
$('.dashboard').slideDown()
})
var uri = ([sessionStorage.io_context,'format',id,index]).join('/') var uri = ([sessionStorage.io_context,'format',id,index]).join('/')
var httpclient = HttpClient.instance() var httpclient = HttpClient.instance()
// //
// @TODO: Let the user know something is going on .. spinner // @TODO: Let the user know something is going on .. spinner
httpclient.post(uri,function(x){ httpclient.post(uri,function(x){
var r = JSON.parse(x.responseText) var r = JSON.parse(x.responseText)
var pane = jx.dom.get.instance('DIV') var pane = jx.dom.get.instance('DIV')
var scalar_pane = jx.dom.get.instance('DIV') var scalar_pane = jx.dom.get.instance('DIV')
pane.id = r.id pane.id = r.id
@ -202,9 +223,9 @@
var p = jx.utils.patterns.visitor(r.pipeline,function(item){ var p = jx.utils.patterns.visitor(r.pipeline,function(item){
var div = jx.dom.get.instance('DIV') var div = jx.dom.get.instance('DIV')
var frame = jx.dom.get.instance('DIV') var frame = jx.dom.get.instance('DIV')
//div.className = 'chart border-round border' //div.className = 'chart2 border-round border'
frame.className = 'chart border' frame.className = 'chart2 border ' + item.label.toLowerCase().replace(/ /g,'_')
div.className = 'graph' div.className = 'graph '
//frame.append(div) //frame.append(div)
//pane.append(frame) //pane.append(frame)
@ -212,8 +233,11 @@
if(item.apex != null){ item.apex.title = {text:item.label} if(item.apex != null){ item.apex.title = {text:item.label}
frame.append(div) frame.append(div)
pane.append(frame) pane.append(frame)
delete item.apex.colors if (item.apex.colors ){
item.apex.theme= { delete item.apex.colors
}
/*item.apex.theme= {
mode: 'material', mode: 'material',
palette: 'palette6', palette: 'palette6',
monochrome: { monochrome: {
@ -222,8 +246,11 @@
shadeTo: 'light', shadeTo: 'light',
shadeIntensity: 0.65 shadeIntensity: 0.65
}, },
} }*/
item.apex.chart.height = '100%' item.apex.chart.height = '100%'
delete item.apex.chart.width
return new ApexCharts(div,item.apex) return new ApexCharts(div,item.apex)
}else{ }else{
//frame.className = '' //frame.className = ''
@ -283,50 +310,80 @@
} }
} }
$(document).ready(function(){ $(document).ready(function(){
$('.dashabord').hide()
$('.item-group').slideUp() $('.item-group').slideUp()
var index = 0;
jx.utils.patterns.visitor($('.menu .items'), function(_item){
var node = $(_item).children()[0]
$(node).attr('index',index)
node.onclick = function(){ toggle($(this).attr('index')) }
index += 1;
})
var year = (new Date()).getFullYear()
$('.year').text(year)
}) })
</script> </script>
<title>Healthcare/IO Analytics</title> <title>Healthcare/IO Analytics</title>
<body> <body>
<div class="pane border"> <div class="pane">
<div class="header border-bottom"> <div class="header border-bottom">
<div class="caption">Healthcare/IO</div> <div class="caption">Healthcare/IO :: Parser</div>
<div class="small">Analytics Dashboard</div> <div class="small">Dashboard</div>
</div> </div>
<div class="menu border-right"> <div class="menu">
<div> <div>
<div class="items">
<div class="bold active" style="margin:4px; height:28px; display:grid; gap:2px; grid-template-columns:auto 32px;">
<div>Setup</div>
<div align="center" class="glyph" >
<i class="fas fa-angle-down"></i>
</div>
</div>
<div class="item-group border border-round">
<div class="item small active" onclick="setup.open()">Configure Parser</div>
<div class="item small active" onclick="healthcare.io.reset()">Reset Parser</div>
</div>
</div>
{% for key in sections %} {% for key in sections %}
<div class="items"> <div class="items">
<div class="bold active" onclick="toggle({{loop.index -1}})" style="margin:4px; height:28px; display:grid; gap:2px; grid-template-columns:auto 32px;"> <div class="bold active" style="margin:4px; height:28px; display:grid; gap:2px; grid-template-columns:auto 32px;">
<div>{{key|safe}}</div> <div>{{key|safe}}</div>
<div align="center" class="glyph" > <div align="center" class="glyph" >
<i class="fas fa-angle-down"></i>
</div>
</div>
<div class="item-group border border-round">
<i class="fas fa-angle-down"></i> {% for item in sections[key] %}
<div class="item small active" onclick="plot('{{key}}',{{loop.index-1}})">{{item.id}}</div>
{% endfor %}
</div> </div>
</div>
<div class="item-group border">
{% for item in sections[key] %}
<div class="item small active" onclick="plot('{{key}}',{{loop.index-1}})">{{item.id}}</div>
{% endfor %}
</div> </div>
</div> {% endfor %}
{% endfor %}
</div> </div>
<div style="display:grid; align-items:flex-end"> <div style="display:none; align-items:flex-end">
<div class="logs border" style="height:250px"></div> <div class="logs chart" style=" align-items:center; display:grid" align="center"></div>
</div> </div>
</div> </div>
<div class="dashboard"> <div>
<div class="dashboard" style="display:none"></div>
</div> {%include 'setup.html' %}
</div>
</div> </div>
<div class="footer small"> <div class="footer small">
&copy; Vanderbilt University Medical Center Healthcare/IO :: Parser &copy; <span class="year"> </span>
</div> </div>
</body> </body>

@ -0,0 +1,391 @@
<style>
.system {height:99%; overflow:hidden;}
.data-info .board{ height:300px; display:grid; grid-template-columns:auto 200px 200px; gap:20px; align-items:center}
/*.board { background-image: linear-gradient(to bottom, #ffffff,#ffffff,#f3f3f3,#d3d3d3d3)}*/
.number {font-size:48px; font-family:courier;padding:8px; ;}
.etl {display:grid; grid-template-columns: 250px auto; gap:2;}
.chart {box-shadow : 0px 1px 4px 2px #d3d3d3; width:200px; height:250px;
display:grid; align-items:center;
background-image: linear-gradient(to bottom,#f3f3f3,#ffffff);
overflow:hidden;
}
.dialog { width:450px; min-height:200px; display:grid; grid-template-rows: 40px 80% auto; gap:4px}
.dialog .title-bar { border-top-left-radius: 8px; border-top-right-radius: 8px ; padding:4px; background-color:#f3f3f3; gap:2px; display:grid; grid-template-columns: auto 32px; align-items:center}
.dialog .action {display:grid; align-items: flex-end; padding-left:25%; padding-right:25%;}
.dialog .message {display:grid; align-items: center; grid-template-columns: 20% auto;}
.dialog .message .text {line-height:2; text-transform: capitalize;}
.fa-exclamation-triangle {color:orange}
.fa-question-circle{color:#009df7}
</style>
<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>
<script src="{{context}}/static/js/io/dialog.js"></script>
<script src="{{context}}/static/js/io/io.js"></script>
<script src="{{context}}/static/js/io/healthcare.js"></script>
<script>
var select = function(node){
var value = $($(node).children()[0]).attr('data-value')
jx.utils.patterns.visitor($('.tab'),function(_item){
var button = $(_item).children()[0]
$(_item).removeClass('selected')
//alert([$(button).attr('data-value'),value])
if($(button).attr('data-value') == value){
$(node).addClass('selected')
$('.'+value).show()
}else{
var m = '.'+ $(button).attr('data-value')
$(m).hide()
}
})
}
var monitor = {}
monitor.listen = {handler:null}
monitor.data = function(){
var http = HttpClient.instance()
http.get("/data",function(x){
var r = JSON.parse(x.responseText)
var keys = jx.utils.keys(r) //-- process,files
for (var i in keys){
var prefix = keys[i]
if(prefix == 'process'){
if(r[prefix].counts != 0){
//
// We should insure the listeners are enabled
if(monitor.listen.handler == null){
monitor.listen.handler = setInterval(
function(){
console.log('running ...')
monitor.data()},5000)
}
}else{
if (monitor.listen.handler != null){
clearInterval(monitor.listen.handler)
}
dialog.close()
}
}
monitor.render(prefix,r[prefix])
}
})
}
monitor.render = function(prefix,r){
prefix = '.'+prefix
var div = jx.dom.get.instance('DIV')
var label = jx.dom.get.instance('DIV')
div.align = 'center'
div.innerHTML = r.counts
div.className = 'number'
label.innerHTML = prefix.replace(/\./,'')
label.style.textTransform = 'capitalize'
label.className = 'small bold border-top'
div.append(label)
$(prefix + ' .board').empty()
$(prefix+' .board').append(div)
var charts = jx.utils.patterns.visitor(r.chart,function(option){
var div = jx.dom.get.instance('div')
div.className = 'chart'
div.align='center'
$(prefix+' .board').append(div)
var chart = new ApexCharts($(div)[0],option)
//chart.render()
div.chart = chart
return chart
})
var observers = jx.utils.patterns.visitor(charts,function(_item){
var m = function(_chart){
this.chart = _chart ;
this.apply = function(caller){this.chart.render();
caller.notify()
}
}
return new m(_item)
})
jx.utils.patterns.observer(observers,'apply')
//jx.utils.patterns.iterator(charts,'render')
/*setTimeout(function(){
jx.utils.patterns.visitor(charts,function(_item){_item.render()})
},1000) */
}
var setup = {}
setup.open = function(){
$('.dashboard').slideUp(
function(){
$('.setup').slideDown()
}
)
}
$(document).ready(function(){
/*var shandler = new io();
if (shandler.disconnected ==false){
shandler.disconnect()
}
var socket = io.connect()
socket.on('connect',function(e){
socket.emit('connect',{name:'steve'})
})
socket.on('update',function(e){
console.log(e)
console.log()
})
var socket = io.connect('http://localhost:81',{cors:{AccessControlAllowOrigin:'*'}}) //('http://localhost:81/stream')
socket.on('procs',function(e){
})
socket.on('data',function(e){
$('.logs').empty()
var div = $('.logs')
var option = e.apex
option.plotOptions.pie.size = 220
option.plotOptions.pie = {dataLabels: {show:true,name:{show:true},value:{show:true}}}
option.legend.show = false
console.log(option)
c = new ApexCharts(div[0],option)
c.render()
socket.emit("procs",{"name":"steve"})
})*/
select($('.tab')[0])
monitor.data()
$('.email').text($('#email').val())
})
</script>
<div class="system setup">
<div class="status">
{% if not store.type %}
<div >
<span class="caption bold border-bottom" style="padding-right:10">Current Configuration</span>
<p></p>
<div style="display:grid; align-items:center; grid-template-columns:32px auto;">
<i class="fa fa-times" style="font-size:28; margin:4px;"></i> <span>System needs to be initialized !</span>
</div>
<p></p>
<div class="active-button border-round" style="width:50%">
<div class="icon">
<i class="fas fa-cog" style="font-size:28"></i>
</div>
<div class="bold" align="center">Initialize</div>
</div>
</div>
{% else %}
<div class="border-right">
<span class="caption bold border-bottom" style="padding-right:10">Current Configuration</span>
<p>
</p>
<div class="item" style="display:grid; align-items:center">
<div class="bold" style="text-transform: capitalize;">Owner </div><div class="bold">:</div>
<div>
<input type="text" id="email" value="{{owner}}">
</div>
</div>
<div class="item">
<div class="bold" style="text-transform: capitalize;">store</div><div class="bold">:</div>
<div class="">{{store.type}}</div>
</div>
<p></p>
<div class="active-button border-round" style="width:50%" onclick="healthcare.io.update()">
<div class="icon">
<I class="fas fa-download" style="font-size:28"></I>
</div>
<div class="bold" align="center">Update Config</div>
</div>
<p>
<div class="code">
#<br>
healthcare-io.py --init <span class="email"></span> --store mongo
</div>
</p>
</div>
{%endif%}
<p></p>
<br>
<div class="border-right">
<span class="caption bold border-bottom" style="padding-right:10">Manage Plan</span>
<p></p>
<div style="line-height: 2;">Insure your account is tied to a cloud service provider.
<br>We support <span class="bold">google-drive, dropbox, one-drive or box. </span>
</div>
<p>
<div class="bold active-button border-round" style="width:50%" onclick="jx.modal.show({url:'https://healthcareio.the-phi.com/store/healthcareio/plans'})">
<div>
<img src="{{context}}/static/img/logo.svg" />
</div>
<div align="center">Open Plan Console</div>
</div>
</p>
</div>
<br>
<div class="border-right" style="height:30%"></div>
</div>
<div class="_border-right"></div>
<div >
<span class="caption bold border-bottom" style="padding-right:10">
Manage Processes</span>
<p>
<div class="input-form" style="grid-template-columns: 30% auto;">
<div class="item" style="grid-row:1; grid-column:1; ">
<div class="label">Process #</div>
<input type="text" class="procs batch"placeholder="#" style="width:64px; text-align:right" value="{{args.batch}}" onchange="healthcare.io.apply()"/>
</div>
<div class="item" style="grid-row:1; grid-column:2 ">
<div class="label">Folder #</div>
<input type="text" placeholder="Process counts" value="/data"/ class="data folder" disabled>
</div>
</div>
<div style="display:grid; grid-template-columns:repeat(2,215px); gap:2px;">
<div class="active-button border-round bold io-apply" style="margin-top:32; display:none" onclick="healthcare.io.apply()">
<div class="icon"><i class="far fa-save" style="font-size:28; color:#4682B4"></i></div>
<div align="center">Apply</div>
</div>
<div class="active-button border-round bold" style="margin-top:32" onclick="healthcare.io.stop()">
<i class="far fa-stop-circle" style="font-size:28; color:maroon"></i>
<div align="center">Stop</div>
</div>
<div class="active-button border-round bold" style="margin-top:32" onclick="healthcare.io.run()">
<i class="fas fa-running" style="font-size:28; color:green"></i>
<div align="center">Run</div>
</div>
</div>
</p>
<p>
<div class="code">
<div class="bold"># The command that will be executed</div>
<div>healthcare-io.py --parse --folder /data --batch <span class="batch">{{args.batch}}</span></div>
</div>
</p>
<p>
<div style="display:grid; grid-template-columns:auto 48px ; gap:2px">
<div class="bold caption border-bottom">Process Monitoring</div>
<div class="active" align="center" title="reload" onclick="monitor.data()"><i class="fas fa-sync"></i></div>
</div>
<div class="small">Powered by smart-top</div>
<p></p>
<div class="tabs">
<div class="tab selected" onclick="select(this)">
<div class="active" data-value="process" >
<i class="far fa-clock" style="color:maroon"></i>
<span>Process</span>
</div>
</div>
<div class="tab" onclick="select(this)">
<div class="active" data-value="files"><i class="fas fa-file-alt"></i> Files</div>
</div>
<div class="tab" onclick="select(this)">
<div class="active" data-value="export"><i class="fas fa-upload"></i> Export</div>
</div>
</div>
<div class="data-info">
<div class="process ">
<div class="board"></div>
<div class="small" align="center">
<div class="border-top bold" style="color:#4682B4;">Running Processes and resource usage</div>
</div>
</div>
<div class="files">
<div class="board"></div>
<div class="small" align="center">
<div class="border-top bold" style="color:#4682B4;">Summary of files found and processed</div>
</div>
</div>
<div class="export">
<p></p>
<div class="etl">
<div class="" >
<div class="menu" style="position:absolute; width:200">
<div class="items ">
<div class="bold active" style="display:grid; grid-template-columns:80% auto;">
<span>
<i class="fas fa-cloud"></i>
Cloud</span>
<span class="glyph">
<i class="fas fa-angle-down"></i>
</span>
</div>
<div class="item-group border-round border small">
<div class="item" onclick="healthcare.io.publish.database.init('s3')">AWS S3</div>
<div class="item" onclick="healthcare.io.publish.database.init('bigquery')">Google Bigquery</div>
</div>
</div>
<div class="items ">
<div class="bold active"style="display:grid; grid-template-columns:80% auto;">
<span>
<i class="fas fa-database"></i>
Database</span>
<span class="glyph">
<i class="fas fa-angle-down"></i>
</span>
</div>
<div class="item-group border-round border small">
<div class="bold">SQL</div>
<div class="item" style="margin-left:15px; margin-right:32px" onclick="healthcare.io.publish.database.init('postgresql')">PostgreSQL</div>
<div class="item" style="margin-left:15px; margin-right:32px" onclick="healthcare.io.publish.database.init('mysql')">MySQL</div>
<div class="bold">NoSQL</div>
<div class="item" style="margin-left:15px; margin-right:32px" onclick="healthcare.io.publish.database.init('mongodb')">Mongodb</div>
<div class="item" style="margin-left:15px; margin-right:32px" onclick="healthcare.io.publish.database.init('couchdb')">Couchdb</div>
</div>
</div>
</div>
</div>
<div>
<div class="active-button border-round" style="width:50%">
<div class="icon"><i class="fas fa-running" style="font-size:28"></i></div> <div class="bold" align="center">Start</div>
</div>
</div>
</div>
</div>
</div>
</p>
</div>
</div>

@ -0,0 +1,78 @@
<link href="{{context}}/static/css/fa/css/all.css" type="text/css" rel="stylesheet">
<link rel="stylesheet" href="{{context}}/static/css/default.css" type="text/css">
<link href="{{context}}/static/css/borders.css" type="text/css" rel="stylesheet">
<style>
.form , input{font-family:sans-serif; font-size:18px}
.form .small {font-size:14px; line-height:2}
.mongo, .couchdb{
display:grid;
gap:2px;
}
.grid-full {display:grid; grid-template-columns: 100%;}
.grid-split-half {display:grid; grid-template-columns: 50% 50%; gap:2px;}
.store .title-bar {display:grid; align-items:center; grid-template-columns: auto 32px; padding:8px;}
.file {display:grid; align-items:center; grid-template-columns: 40% auto; gap:2px; font-family:sans-serif; padding:8px}
.file input {display:none}
.file label {padding:8px;}
</style>
<div class="store">
<div class="title-bar">
<div class="caption">Export Module <span class="bold id"></span></div>
<div class="active" align="center" onclick="jx.modal.close()">
<i class="fas fa-times"></i>
</div>
</div>
<p></p>
<div class="cloud form border-round">
<div class="small border-round">
Please provide select access-key file or service account key file to perform ETL
to <span class="bold id"></span>. <br>The files will be re-created in JSON format
</div>
<div class="file">
<label class="active-button border-round">
<span style="font-family:sans-serif">
<i class="icon fas fa-file-upload" style="font-size:24px"></i>
</span>
<div>Select key file</div>
<input type="file" id="file" aria-label="File browser example" onchange="publish.set.file()">
</label>
<div class="name small black bold" style="padding-left:24px"></div>
</div>
</div>
<div class="database form border-round">
<div class="small border-round">
Tables / collections will be automatically inferred in the <span class="bold id"></span>
</div>
<div class="mongo">
<div class="grid-split-half">
<input type="text" class="host" placeholder="host:port"/>
<input type="text" class="host" placeholder="database"/>
</div>
<div class="grid-split-half">
<input type="text" placeholder="user"/>
<input type="text" placeholder="password"/>
</div>
</div>
<p></p>
<div>
<br>
<div class="active-button border-round" style="margin-left:30%; margin-right:30%">
<div class="icon">
<i class="fas fa-check"></i>
</div>
<div class="bold" align="center">Export Now</div>
</div>
</div>
</div>
</div>

@ -24,6 +24,7 @@ import sys
from itertools import islice from itertools import islice
from multiprocessing import Process from multiprocessing import Process
import transport import transport
import jsonmerge
class void : class void :
pass pass
class Formatters : class Formatters :
@ -49,8 +50,9 @@ class Formatters :
""" """
This function is designed to split an x12 row and This function is designed to split an x12 row and
""" """
value = []
if row.startswith(prefix) is False: if row.startswith(prefix) is False:
value = []
for row_value in row.replace('~','').split(sep) : for row_value in row.replace('~','').split(sep) :
@ -65,10 +67,12 @@ class Formatters :
else : else :
value.append(row_value.replace('\n','')) value.append(row_value.replace('\n',''))
return [xchar.replace('\r','') for xchar in value] #row.replace('~','').split(sep) value = [xchar.replace('\r','') for xchar in value] #row.replace('~','').split(sep)
else: else:
return [ [prefix]+ self.split(item,'>') for item in row.replace('~','').split(sep)[1:] ] value = [ [prefix]+ self.split(item,'>') for item in row.replace('~','').split(sep)[1:] ]
return value if type(value) == list and type(value[0]) != list else value[0]
def get_config(self,config,row): def get_config(self,config,row):
""" """
This function will return the meaningfull parts of the configuration for a given item This function will return the meaningfull parts of the configuration for a given item
@ -92,7 +96,6 @@ class Formatters :
if _row[0] in config['SIMILAR'] : if _row[0] in config['SIMILAR'] :
key = config['SIMILAR'][_row[0]] key = config['SIMILAR'][_row[0]]
_info = config[key] _info = config[key]
return _info return _info
def hash(self,value): def hash(self,value):
@ -130,7 +133,7 @@ class Formatters :
terms = value[1].split('>') terms = value[1].split('>')
return {'type':terms[0],'code':terms[1],"amount":float(value[2])} return {'type':terms[0],'code':terms[1],"amount":float(value[2])}
else: else:
return {"code":value[2],"type":value[1],"amount":float(value[3])} return {"code":value[2],"type":value[1],"amount":float(value[3])}
def sv2(self,value): def sv2(self,value):
# #
@ -170,27 +173,56 @@ class Formatters :
def pos(self,value): def pos(self,value):
""" """
formatting place of service information within a segment (REF) formatting place of service information within a segment (REF)
@TODO: In order to accomodate the other elements they need to be specified in the configuration
Otherwise it causes problems on export
""" """
xchar = '>' if '>' in value else ':' xchar = '>' if '>' in value else ':'
x = value.split(xchar) x = value.split(xchar)
x = {"code":x[0],"indicator":x[1],"frequency":x[2]} if len(x) == 3 else {"code":x[0],"indicator":None,"frequency":None} x = {"code":x[0],"indicator":x[1],"frequency":x[2]} if len(x) == 3 else {"code":x[0],"indicator":None,"frequency":None}
return x return x['code']
class Parser (Process): class Parser (Process):
def __init__(self,path): def __init__(self,path):
"""
:path path of the configuration file (it can be absolute)
"""
Process.__init__(self) Process.__init__(self)
self.utils = Formatters() self.utils = Formatters()
self.get = void() self.get = void()
self.get.value = self.get_map self.get.value = self.get_map
self.get.default_value = self.get_default_value self.get.default_value = self.get_default_value
_config = json.loads(open(path).read()) _config = json.loads(open(path).read())
self._custom_config = self.get_custom(path)
self.config = _config['parser'] self.config = _config['parser']
self.store = _config['store'] self.store = _config['store']
self.files = [] self.files = []
self.set = void() self.set = void()
self.set.files = self.set_files self.set.files = self.set_files
self.emit = void()
self.emit.pre = None
self.emit.post = None
def get_custom(self,path) :
"""
:path path of the configuration file (it can be absolute)
"""
#
#
_path = path.replace('config.json','')
if _path.endswith(os.sep) :
_path = _path[:-1]
_config = {}
_path = os.sep.join([_path,'custom'])
if os.path.exists(_path) :
files = os.listdir(_path)
if files :
fullname = os.sep.join([_path,files[0]])
_config = json.loads ( (open(fullname)).read() )
return _config
def set_files(self,files): def set_files(self,files):
self.files = files self.files = files
def get_map(self,row,config,version=None): def get_map(self,row,config,version=None):
@ -241,15 +273,18 @@ class Parser (Process):
value = {key:value} if key not in value else value value = {key:value} if key not in value else value
else: else:
if 'syn' in config and value in config['syn'] : if 'syn' in config and value in config['syn'] :
value = config['syn'][value] value = config['syn'][value]
if type(value) == dict : if type(value) == dict :
object_value = dict(object_value, **value) object_value = dict(object_value, **value)
else: else:
object_value[key] = value object_value[key] = value
else: else:
# #
# we are dealing with a complex object # we are dealing with a complex object
@ -269,25 +304,35 @@ class Parser (Process):
return object_value return object_value
def apply(self,content,_code) : def apply(self,content,_code) :
""" """
:file content i.e a segment with the envelope :content content of a file i.e a segment with the envelope
:_code 837 or 835 (helps get the appropriate configuration) :_code 837 or 835 (helps get the appropriate configuration)
""" """
util = Formatters() util = Formatters()
# header = default_value.copy() # header = default_value.copy()
value = {} value = {}
for row in content[:] : for row in content[:] :
row = util.split(row.replace('\n','').replace('~','')) row = util.split(row.replace('\n','').replace('~',''))
_info = util.get.config(self.config[_code][0],row) _info = util.get.config(self.config[_code][0],row)
if self._custom_config and _code in self._custom_config:
_cinfo = util.get.config(self._custom_config[_code],row)
else:
_cinfo = {}
# _info = self.consolidate(row=row,type=_code,config=_info,util=util)
# print ([row[0],_info])
# print ()
# continue
# _cinfo = util.get.config(self._custom_config[_code],row)
if _info : if _info :
try: try:
_info = jsonmerge.merge(_info,_cinfo)
tmp = self.get.value(row,_info) tmp = self.get.value(row,_info)
# if 'P1080351470' in content[0] and 'PLB' in row:
# print (_info)
# print (row)
# print (tmp)
if not tmp : if not tmp :
continue continue
if 'label' in _info : if 'label' in _info :
@ -300,10 +345,10 @@ class Parser (Process):
else: else:
if label not in value: if label not in value:
value[label] = [tmp] value[label] = [tmp]
elif len(list(tmp.keys())) == 1 : # elif len(list(tmp.keys())) == 1 :
# print "\t",len(claim[label]),tmp # # print "\t",len(claim[label]),tmp
index = len(value[label]) -1 # index = len(value[label]) -1
value[label][index] = dict(value[label][index],**tmp) # value[label][index] = dict(value[label][index],**tmp)
else: else:
value[label].append(tmp) value[label].append(tmp)
tmp['_index'] = len(value[label]) -1 tmp['_index'] = len(value[label]) -1
@ -319,7 +364,9 @@ class Parser (Process):
elif 'field' in _info : elif 'field' in _info :
name = _info['field'] name = _info['field']
value[name] = tmp # value[name] = tmp
value = jsonmerge.merge(value,{name:tmp})
else: else:
@ -327,13 +374,14 @@ class Parser (Process):
pass pass
except Exception as e : except Exception as e :
print ('__',e.args) print ('__',e.args)
pass pass
return value if value else {} return value if value else {}
def get_default_value(self,content,_code): def get_default_value(self,content,_code):
util = Formatters() util = Formatters()
TOP_ROW = content[1].split('*') TOP_ROW = content[1].split('*')
CATEGORY= content[2].split('*')[1].strip() CATEGORY= content[2].split('*')[1].strip()
@ -352,6 +400,8 @@ class Parser (Process):
value['payer_id'] = SENDER_ID value['payer_id'] = SENDER_ID
else: else:
value['provider_id'] = SENDER_ID value['provider_id'] = SENDER_ID
#
# Let's parse this for default values
return value return value
def read(self,filename) : def read(self,filename) :
@ -374,8 +424,14 @@ class Parser (Process):
INITIAL_ROWS = file[:4] INITIAL_ROWS = file[:4]
if len(INITIAL_ROWS) < 3 : if len(INITIAL_ROWS) < 3 :
return None,[{"name":filename,"completed":False}],None return None,[{"name":filename,"completed":False}],None
section = 'HL' if INITIAL_ROWS[1].split('*')[1] == 'HC' else 'CLP' # section = 'HL' if INITIAL_ROWS[1].split('*')[1] == 'HC' else 'CLP'
_code = '837' if section == 'HL' else '835' # _code = '837' if section == 'HL' else '835'
# print ([_code,section])
_code = INITIAL_ROWS[2].split('*')[1].strip()
# section = 'CLP' if _code == '835' else 'HL'
section = self.config[_code][0]['SECTION'].strip()
#
# adjusting the
DEFAULT_VALUE = self.get.default_value(INITIAL_ROWS,_code) DEFAULT_VALUE = self.get.default_value(INITIAL_ROWS,_code)
DEFAULT_VALUE['name'] = filename.strip() DEFAULT_VALUE['name'] = filename.strip()
# #
@ -383,22 +439,30 @@ class Parser (Process):
# index 1 identifies file type i.e CLM for claim and CLP for remittance # index 1 identifies file type i.e CLM for claim and CLP for remittance
segment = [] segment = []
index = 0; index = 0;
_toprows = []
for row in file : for row in file :
row = row.replace('\r','')
if not segment and not row.startswith(section):
_toprows += [row]
if row.startswith(section) and not segment: if row.startswith(section) and not segment:
segment = [row] segment = [row]
continue continue
elif segment and not row.startswith(section): elif segment and not row.startswith(section):
segment.append(row) segment.append(row)
if len(segment) > 1 and row.startswith(section): if len(segment) > 1 and row.startswith(section):
# #
# process the segment somewhere (create a thread maybe?) # process the segment somewhere (create a thread maybe?)
# #
# default_claim = dict({"index":index},**DEFAULT_VALUE) # default_claim = dict({"index":index},**DEFAULT_VALUE)
# print (_toprows)
_claim = self.apply(segment,_code) _claim = self.apply(segment,_code)
# if _claim['claim_id'] == 'P1080351470' : # if _claim['claim_id'] == 'P1080351470' :
# print (_claim) # print (_claim)
# _claim = dict(DEFAULT_VALUE,**_claim) # _claim = dict(DEFAULT_VALUE,**_claim)
@ -418,12 +482,14 @@ class Parser (Process):
claim = self.apply(segment,_code) claim = self.apply(segment,_code)
if claim : if claim :
claim['index'] = len(claims) claim['index'] = len(claims)
claim = jsonmerge.merge(claim,self.apply(_toprows,_code))
claims.append(dict(DEFAULT_VALUE,**claim)) claims.append(dict(DEFAULT_VALUE,**claim))
if type(file) != list : if type(file) != list :
file.close() file.close()
# x12_file = open(filename.strip(),errors='ignore').read().split('\n') # x12_file = open(filename.strip(),errors='ignore').read().split('\n')
except Exception as e: except Exception as e:
logs.append ({"parse":_code,"completed":False,"name":filename,"msg":e.args[0]}) logs.append ({"parse":_code,"completed":False,"name":filename,"msg":e.args[0]})
return [],logs,None return [],logs,None
@ -432,6 +498,9 @@ class Parser (Process):
# self.finish(claims,logs,_code) # self.finish(claims,logs,_code)
return claims,logs,_code return claims,logs,_code
def run(self): def run(self):
if self.emit.pre :
self.emit.pre()
for filename in self.files : for filename in self.files :
content,logs,_code = self.read(filename) content,logs,_code = self.read(filename)
self.finish(content,logs,_code) self.finish(content,logs,_code)
@ -441,14 +510,22 @@ class Parser (Process):
if args['type'] == 'mongo.MongoWriter' : if args['type'] == 'mongo.MongoWriter' :
args['args']['doc'] = 'claims' if _code == '837' else 'remits' args['args']['doc'] = 'claims' if _code == '837' else 'remits'
_args['args']['doc'] = 'logs' _args['args']['doc'] = 'logs'
else:
args['args']['table'] = 'claims' if _code == '837' else 'remits'
_args['args']['table'] = 'logs'
if content : if content :
writer = transport.factory.instance(**args) writer = transport.factory.instance(**args)
writer.write(content) writer.write(content)
writer.close() writer.close()
if logs : if logs :
logger = transport.factory.instance(**_args) logger = transport.factory.instance(**_args)
logger.write(logs) logger.write(logs)
logger.close() logger.close()
if self.emit.post :
self.emit.post(content,logs)

@ -8,14 +8,15 @@ import sys
def read(fname): def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read() return open(os.path.join(os.path.dirname(__file__), fname)).read()
args = { args = {
"name":"healthcareio","version":"1.3.7", "name":"healthcareio","version":"1.4.8",
"author":"Vanderbilt University Medical Center", "author":"Vanderbilt University Medical Center",
"author_email":"steve.l.nyemba@vumc.org", "author_email":"steve.l.nyemba@vumc.org",
"include_package_data":True,
"license":"MIT", "license":"MIT",
"packages":find_packages(), "packages":find_packages(),
"keywords":["healthcare","edi","x12","analytics","835","837","data","transport","protocol"] "keywords":["healthcare","edi","x12","analytics","835","837","data","transport","protocol"]
} }
args["install_requires"] = ['seaborn','jinja2', 'weasyprint','data-transport@git+https://dev.the-phi.com/git/steve/data-transport.git','pymongo','numpy','cloudant','pika','boto','flask-session','smart_open'] args["install_requires"] = ['flask-socketio','seaborn','jinja2','jsonmerge', 'weasyprint','data-transport@git+https://healthcareio.the-phi.com/git/code/transport.git','pymongo','numpy','cloudant','pika','boto','botocore','flask-session','smart_open','smart-top@git+https://healthcareio.the-phi.com/git/code/smart-top.git@data-collector']
args['url'] = 'https://hiplab.mc.vanderbilt.edu' args['url'] = 'https://hiplab.mc.vanderbilt.edu'
args['scripts']= ['healthcareio/healthcare-io.py'] args['scripts']= ['healthcareio/healthcare-io.py']
# args['entry_points'] = { # args['entry_points'] = {

Loading…
Cancel
Save