From 3eb5c5b5683cebea89408381ef9be260d7eb2e25 Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Mon, 11 Sep 2023 11:40:26 -0500 Subject: [PATCH] bug fix --- healthcareio/x12/plugins/default/__init__.py | 12 +- healthcareio/x12/plugins/default/body.py | 17 ++- healthcareio/x12/plugins/default/common.py | 111 +++++++++++++------ 3 files changed, 101 insertions(+), 39 deletions(-) diff --git a/healthcareio/x12/plugins/default/__init__.py b/healthcareio/x12/plugins/default/__init__.py index ab7dc1e..f4c69bb 100644 --- a/healthcareio/x12/plugins/default/__init__.py +++ b/healthcareio/x12/plugins/default/__init__.py @@ -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: - How to write custom plugin - Provide interface for meta-data (expected) @@ -11,11 +12,14 @@ from . import header from . import body EDI = body.BODY - +__version__ = '0.01' +__author__ = 'The Phi Technology' def instance(**_args): pass - -# class Parser : +# +# defining commong functions that can/should be used accross the board +# +# # class Parser : # def __init__(**_args): # folder = _args['path'] # files = [ os.sep.join(_name,folder) for _name in os.listdir(folder)] diff --git a/healthcareio/x12/plugins/default/body.py b/healthcareio/x12/plugins/default/body.py index b191c9f..eac2dcc 100644 --- a/healthcareio/x12/plugins/default/body.py +++ b/healthcareio/x12/plugins/default/body.py @@ -21,16 +21,29 @@ class BODY (HEADER): ref IL,40,41,82,85,PR ... 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'}} _columns = ['type','name','id'] _indexes = [1,3,-1] # _info = [{'index':'40','field':'receiver'},{'index':'41','field':'submitter'},{'index':'PR','field':'payer'}] _info = self.parse(_columns,_indexes,**_args) + self.lastelement = _info return _info def N3 (self,**_args): - """ + """ Expected Element N3 """ diff --git a/healthcareio/x12/plugins/default/common.py b/healthcareio/x12/plugins/default/common.py index 4ad687d..125ad87 100644 --- a/healthcareio/x12/plugins/default/common.py +++ b/healthcareio/x12/plugins/default/common.py @@ -74,7 +74,7 @@ class X12DOCUMENT (Process): _field = _config['field'] if 'field' in _config else {} _label = _config['label'] if 'label' in _config else {} return _field,_label - def merge(self,**_args): + def consolidate(self,**_args): # # This function overrides the old configuration with the new configuration specifications # @@ -92,24 +92,28 @@ class X12DOCUMENT (Process): if '@ref' in _config : # _columns,_indexes = [],[] _row = _args['row'] - - _ref = _config['@ref'] + + _ref = _config['@ref'] for _anchor in _ref: - # print ([_anchor,_anchor == _row[1].strip()]) + if _anchor == _row[1].strip() : _field,_label = self._getObjectAtributes(_ref[_anchor]) _map = _ref[_anchor]['map'] if 'map' in _ref[_anchor] else {} - + if _map : _columns,_indexes = self._getColumnsIndexes([],[],_map) - + else: + # print ([_anchor,_indexes,_columns]) + _map = dict(zip(_columns,_indexes)) + pass break # _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): # # This function returns the legacy configuration (default parsing) @@ -128,9 +132,17 @@ class X12DOCUMENT (Process): def __init__(self,**_args): super().__init__() self._mode = _args['mode'] if 'mode' in _args else 'NAMES' + self.lastelement = {} # This to store in the loop if 'files' in _args : self.files = _args['files'] 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._x12FileType = None @@ -218,8 +230,16 @@ class X12DOCUMENT (Process): # _field = _field if not _refField else _refField # _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'] _columns,_index = _outInfo['columns'],_outInfo['index'] @@ -240,42 +260,61 @@ class X12DOCUMENT (Process): # _element = _row[0] - _configKeys = [] #list(self._config.keys()) - _configTree = [] #list(self._config.values()) - if 'config' in _args : - _config = _args['config'] - _configKeys = list(_config.keys()) - _configTree = list(_config.values()) - else: - _config = {} + # _configKeys = [] #list(self._config.keys()) + # _configTree = [] #list(self._config.values()) + # if 'config' in _args : + # _config = _args['config'] + # _configKeys = list(_config.keys()) + # _configTree = list(_config.values()) + # else: + # _config = {} _info = dict(zip(_columns,_row[_index].tolist())) _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 not _field in _document : - return {_field:_info} + _item = {_field:_info} else: - return self.merge(_document[_field],_info) + _item = self.merge(_document[_field],_info) elif _label : if not _label in _document : - return {_label:[_info]} + _item = {_label:[_info]} else: - return _document[_label] + [_info] + _item = _document[_label] + [_info] 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: + # + # + print (_config) return columns def elements(self): """ @@ -347,16 +386,22 @@ class X12DOCUMENT (Process): _header = self.apply(_info['header']) # print (json.dumps(_header)) + _tmp = {} for _content in _info['blocks'] : - _body = self.apply(_content,header=_header) + _body = self.apply(_content,header=_header) + _doc = self.merge(_header,_body) if _doc and 'claim_id' in _doc: # 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: #