v2.0 upgrade #10
|
@ -1,5 +1,6 @@
|
||||||
"""
|
"""
|
||||||
This file serves as the interface (so to speak) to the x12 parser, plugin interface
|
This file serves as the interface (so to speak) to the x12 parser, plugin interface, We implement default plugins that will handle parsing,
|
||||||
|
In addition to the allow custom plugins to be written/loaded and these will be given priority over the default ones+6+++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
@TODO:
|
@TODO:
|
||||||
- How to write custom plugin
|
- How to write custom plugin
|
||||||
- Provide interface for meta-data (expected)
|
- Provide interface for meta-data (expected)
|
||||||
|
@ -11,11 +12,14 @@ from . import header
|
||||||
from . import body
|
from . import body
|
||||||
|
|
||||||
EDI = body.BODY
|
EDI = body.BODY
|
||||||
|
__version__ = '0.01'
|
||||||
|
__author__ = 'The Phi Technology'
|
||||||
def instance(**_args):
|
def instance(**_args):
|
||||||
pass
|
pass
|
||||||
|
#
|
||||||
# class Parser :
|
# defining commong functions that can/should be used accross the board
|
||||||
|
#
|
||||||
|
# # class Parser :
|
||||||
# def __init__(**_args):
|
# def __init__(**_args):
|
||||||
# folder = _args['path']
|
# folder = _args['path']
|
||||||
# files = [ os.sep.join(_name,folder) for _name in os.listdir(folder)]
|
# files = [ os.sep.join(_name,folder) for _name in os.listdir(folder)]
|
||||||
|
|
|
@ -21,13 +21,26 @@ class BODY (HEADER):
|
||||||
ref IL,40,41,82,85,PR ...
|
ref IL,40,41,82,85,PR ...
|
||||||
Information about entities (doctors, clearing house, provider). we should be mindful of the references
|
Information about entities (doctors, clearing house, provider). we should be mindful of the references
|
||||||
"""
|
"""
|
||||||
# _CODE_INDEX = 1
|
_CODE_INDEX = 1
|
||||||
|
CONTEXT_MAP = {
|
||||||
|
|
||||||
|
'2':{'field':'payer'},
|
||||||
|
'PR':{'field':'payer'},
|
||||||
|
'41':{'field':'header'},
|
||||||
|
'IL':{'field':'patient','map':{'type':2,'first_name':4,'last_name':3}},
|
||||||
|
'P5':{'field':'plan_sponsor'},
|
||||||
|
'82':{'field':'rendering_provider','map':{'type':2,'first_name':4,'last_name':3}},
|
||||||
|
'85':{'field':'billing_provider'}
|
||||||
|
|
||||||
|
}
|
||||||
|
_args ['plugin-context'] = {'@ref':CONTEXT_MAP}
|
||||||
# _map = {_CODE_INDEX:{'41':'submitter','40':'receiver','PR':'payer'}}
|
# _map = {_CODE_INDEX:{'41':'submitter','40':'receiver','PR':'payer'}}
|
||||||
_columns = ['type','name','id']
|
_columns = ['type','name','id']
|
||||||
_indexes = [1,3,-1]
|
_indexes = [1,3,-1]
|
||||||
# _info = [{'index':'40','field':'receiver'},{'index':'41','field':'submitter'},{'index':'PR','field':'payer'}]
|
# _info = [{'index':'40','field':'receiver'},{'index':'41','field':'submitter'},{'index':'PR','field':'payer'}]
|
||||||
|
|
||||||
_info = self.parse(_columns,_indexes,**_args)
|
_info = self.parse(_columns,_indexes,**_args)
|
||||||
|
self.lastelement = _info
|
||||||
return _info
|
return _info
|
||||||
def N3 (self,**_args):
|
def N3 (self,**_args):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -74,7 +74,7 @@ class X12DOCUMENT (Process):
|
||||||
_field = _config['field'] if 'field' in _config else {}
|
_field = _config['field'] if 'field' in _config else {}
|
||||||
_label = _config['label'] if 'label' in _config else {}
|
_label = _config['label'] if 'label' in _config else {}
|
||||||
return _field,_label
|
return _field,_label
|
||||||
def merge(self,**_args):
|
def consolidate(self,**_args):
|
||||||
#
|
#
|
||||||
# This function overrides the old configuration with the new configuration specifications
|
# This function overrides the old configuration with the new configuration specifications
|
||||||
#
|
#
|
||||||
|
@ -96,7 +96,7 @@ class X12DOCUMENT (Process):
|
||||||
_ref = _config['@ref']
|
_ref = _config['@ref']
|
||||||
|
|
||||||
for _anchor in _ref:
|
for _anchor in _ref:
|
||||||
# print ([_anchor,_anchor == _row[1].strip()])
|
|
||||||
if _anchor == _row[1].strip() :
|
if _anchor == _row[1].strip() :
|
||||||
_field,_label = self._getObjectAtributes(_ref[_anchor])
|
_field,_label = self._getObjectAtributes(_ref[_anchor])
|
||||||
|
|
||||||
|
@ -104,12 +104,16 @@ class X12DOCUMENT (Process):
|
||||||
|
|
||||||
if _map :
|
if _map :
|
||||||
_columns,_indexes = self._getColumnsIndexes([],[],_map)
|
_columns,_indexes = self._getColumnsIndexes([],[],_map)
|
||||||
|
else:
|
||||||
|
# print ([_anchor,_indexes,_columns])
|
||||||
|
_map = dict(zip(_columns,_indexes))
|
||||||
|
pass
|
||||||
|
|
||||||
break
|
break
|
||||||
# _columns,_indexes = _columns + _map.keys()
|
# _columns,_indexes = _columns + _map.keys()
|
||||||
|
|
||||||
return {'columns':_columns,'index':_indexes,'field':_field,'label':_label}
|
_out = {'columns':_columns,'index':_indexes,'field':_field,'label':_label}
|
||||||
|
return _out
|
||||||
def legacy(self,**_args):
|
def legacy(self,**_args):
|
||||||
#
|
#
|
||||||
# This function returns the legacy configuration (default parsing)
|
# This function returns the legacy configuration (default parsing)
|
||||||
|
@ -128,9 +132,17 @@ class X12DOCUMENT (Process):
|
||||||
def __init__(self,**_args):
|
def __init__(self,**_args):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._mode = _args['mode'] if 'mode' in _args else 'NAMES'
|
self._mode = _args['mode'] if 'mode' in _args else 'NAMES'
|
||||||
|
self.lastelement = {} # This to store in the loop
|
||||||
if 'files' in _args :
|
if 'files' in _args :
|
||||||
self.files = _args['files']
|
self.files = _args['files']
|
||||||
self._config = _args['config'] if 'config' in _args else {}
|
self._config = _args['config'] if 'config' in _args else {}
|
||||||
|
|
||||||
|
#
|
||||||
|
# NM1 is a fluid type and thus will be cached in order to recreate the hierarchy
|
||||||
|
# @TODO:
|
||||||
|
# -add this to the configuration
|
||||||
|
#
|
||||||
|
self._hierarchy = {'NM1':['N1','N2','N3','N4']}
|
||||||
self._document = []
|
self._document = []
|
||||||
|
|
||||||
self._x12FileType = None
|
self._x12FileType = None
|
||||||
|
@ -218,7 +230,15 @@ class X12DOCUMENT (Process):
|
||||||
# _field = _field if not _refField else _refField
|
# _field = _field if not _refField else _refField
|
||||||
# _label = _label if not _refLabel else _refLabel
|
# _label = _label if not _refLabel else _refLabel
|
||||||
|
|
||||||
_outInfo = self._configHandler.merge(row=_args['row'],columns=columns,index=index,config=_config)
|
#
|
||||||
|
# @TODO:
|
||||||
|
# There should be a priority in parsing i.e plugin - config
|
||||||
|
#
|
||||||
|
if 'plugin-context' in _args :
|
||||||
|
_config = _args['plugin-context'] #dict(_config,**_args['plugin-context'])
|
||||||
|
|
||||||
|
_outInfo = self._configHandler.consolidate(row=_args['row'],columns=columns,index=index,config=_config)
|
||||||
|
|
||||||
|
|
||||||
_field,_label = _outInfo['field'],_outInfo['label']
|
_field,_label = _outInfo['field'],_outInfo['label']
|
||||||
_columns,_index = _outInfo['columns'],_outInfo['index']
|
_columns,_index = _outInfo['columns'],_outInfo['index']
|
||||||
|
@ -240,42 +260,61 @@ class X12DOCUMENT (Process):
|
||||||
|
|
||||||
# _element = _row[0]
|
# _element = _row[0]
|
||||||
|
|
||||||
_configKeys = [] #list(self._config.keys())
|
# _configKeys = [] #list(self._config.keys())
|
||||||
_configTree = [] #list(self._config.values())
|
# _configTree = [] #list(self._config.values())
|
||||||
if 'config' in _args :
|
# if 'config' in _args :
|
||||||
_config = _args['config']
|
# _config = _args['config']
|
||||||
_configKeys = list(_config.keys())
|
# _configKeys = list(_config.keys())
|
||||||
_configTree = list(_config.values())
|
# _configTree = list(_config.values())
|
||||||
else:
|
# else:
|
||||||
_config = {}
|
# _config = {}
|
||||||
|
|
||||||
_info = dict(zip(_columns,_row[_index].tolist()))
|
_info = dict(zip(_columns,_row[_index].tolist()))
|
||||||
_document = _args['document'] if 'document' in _args else {}
|
_document = _args['document'] if 'document' in _args else {}
|
||||||
|
|
||||||
|
#
|
||||||
|
# @TODO:
|
||||||
|
# Apply parsing/casting function to the object retrieved
|
||||||
|
# _apply(_info) #-- the object will be processed accordingly
|
||||||
#
|
#
|
||||||
# Extracting configuration (minimal information)
|
|
||||||
# _config = _args['config'] if 'config' in _args else {}
|
|
||||||
# _config = self._config
|
|
||||||
|
|
||||||
|
|
||||||
# if '@ref' in _config :
|
|
||||||
# print (_config['@ref'])
|
|
||||||
# _values = _config['@ref']
|
|
||||||
# print (_values)
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# @TODO:
|
||||||
|
# The objects parsed must be augmented against the appropriate ones e.g: NM1 <- N1,N2,N3,N4
|
||||||
|
# - Find a way to drive this from a configuration ...
|
||||||
|
#
|
||||||
if _field :
|
if _field :
|
||||||
|
|
||||||
if not _field in _document :
|
if not _field in _document :
|
||||||
return {_field:_info}
|
_item = {_field:_info}
|
||||||
else:
|
else:
|
||||||
return self.merge(_document[_field],_info)
|
_item = self.merge(_document[_field],_info)
|
||||||
elif _label :
|
elif _label :
|
||||||
if not _label in _document :
|
if not _label in _document :
|
||||||
return {_label:[_info]}
|
_item = {_label:[_info]}
|
||||||
else:
|
else:
|
||||||
return _document[_label] + [_info]
|
_item = _document[_label] + [_info]
|
||||||
else:
|
else:
|
||||||
return _info
|
_item = _info
|
||||||
|
|
||||||
|
if _ELEMENT in self._hierarchy and _field:
|
||||||
|
# print ([_field,_item])
|
||||||
|
self.lastelement = _item
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
for key in self._hierarchy :
|
||||||
|
if _ELEMENT in self._hierarchy[key] :
|
||||||
|
|
||||||
|
_ikey = list(self.lastelement.keys())[0]
|
||||||
|
_oldinfo = self.lastelement[_ikey]
|
||||||
|
_item = {_ikey: self.merge(_oldinfo,_item)}
|
||||||
|
|
||||||
|
break
|
||||||
|
return _item
|
||||||
else:
|
else:
|
||||||
|
#
|
||||||
|
#
|
||||||
|
print (_config)
|
||||||
return columns
|
return columns
|
||||||
def elements(self):
|
def elements(self):
|
||||||
"""
|
"""
|
||||||
|
@ -347,16 +386,22 @@ class X12DOCUMENT (Process):
|
||||||
_header = self.apply(_info['header'])
|
_header = self.apply(_info['header'])
|
||||||
|
|
||||||
# print (json.dumps(_header))
|
# print (json.dumps(_header))
|
||||||
|
_tmp = {}
|
||||||
for _content in _info['blocks'] :
|
for _content in _info['blocks'] :
|
||||||
|
|
||||||
_body = self.apply(_content,header=_header)
|
_body = self.apply(_content,header=_header)
|
||||||
|
|
||||||
_doc = self.merge(_header,_body)
|
_doc = self.merge(_header,_body)
|
||||||
|
|
||||||
if _doc and 'claim_id' in _doc:
|
if _doc and 'claim_id' in _doc:
|
||||||
# X12DOCUMENT._queue.put(_document)
|
# X12DOCUMENT._queue.put(_document)
|
||||||
|
|
||||||
_documents += [_doc]
|
_documents += [self.merge(_tmp,_doc)]
|
||||||
|
_tmp = {}
|
||||||
|
else:
|
||||||
|
#
|
||||||
|
# The document is being built and not yet ready
|
||||||
|
_tmp = self.merge(_tmp,_doc)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in New Issue