Package Gnumed :: Package business :: Module gmIncomingData
[frames] | no frames]

Source Code for Module Gnumed.business.gmIncomingData

  1  # -*- coding: utf-8 -*- 
  2  """Handling of <INCOMING> area.""" 
  3  #============================================================ 
  4  __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>" 
  5  __license__ = "GPL v2 or later" 
  6   
  7   
  8  import sys 
  9  import os 
 10  import logging 
 11   
 12   
 13  if __name__ == '__main__': 
 14          sys.path.insert(0, '../../') 
 15   
 16  from Gnumed.pycommon import gmI18N 
 17  if __name__ == '__main__': 
 18          gmI18N.activate_locale() 
 19          gmI18N.install_domain() 
 20  from Gnumed.pycommon import gmTools 
 21  from Gnumed.pycommon import gmBusinessDBObject 
 22  from Gnumed.pycommon import gmPG2 
 23  from Gnumed.pycommon import gmDateTime 
 24   
 25   
 26  _log = logging.getLogger('gm.import') 
 27   
 28  #============================================================ 
 29  # class to handle unmatched incoming clinical data 
 30  #------------------------------------------------------------ 
 31  _SQL_get_incoming_data = """SELECT * FROM clin.v_incoming_data_unmatched WHERE %s""" 
 32   
33 -class cIncomingData(gmBusinessDBObject.cBusinessDBObject):
34 """Represents items of incoming data, say, HL7 snippets.""" 35 36 _cmd_fetch_payload = _SQL_get_incoming_data % "pk_incoming_data_unmatched = %s" 37 _cmds_store_payload = [ 38 """UPDATE clin.incoming_data_unmatched SET 39 fk_patient_candidates = %(pk_patient_candidates)s, 40 fk_identity_disambiguated = %(pk_identity_disambiguated)s, 41 fk_provider_disambiguated = %(pk_provider_disambiguated)s, 42 request_id = gm.nullify_empty_string(%(request_id)s), 43 firstnames = gm.nullify_empty_string(%(firstnames)s), 44 lastnames = gm.nullify_empty_string(%(lastnames)s), 45 dob = %(dob)s, 46 postcode = gm.nullify_empty_string(%(postcode)s), 47 other_info = gm.nullify_empty_string(%(other_info)s), 48 type = gm.nullify_empty_string(%(data_type)s), 49 gender = gm.nullify_empty_string(%(gender)s), 50 requestor = gm.nullify_empty_string(%(requestor)s), 51 external_data_id = gm.nullify_empty_string(%(external_data_id)s), 52 comment = gm.nullify_empty_string(%(comment)s) 53 WHERE 54 pk = %(pk_incoming_data_unmatched)s 55 AND 56 xmin = %(xmin_incoming_data_unmatched)s 57 RETURNING 58 xmin as xmin_incoming_data_unmatched, 59 octet_length(data) as data_size 60 """ 61 ] 62 # view columns that can be updated: 63 _updatable_fields = [ 64 'pk_patient_candidates', 65 'request_id', # request ID as found in <data> 66 'firstnames', 67 'lastnames', 68 'dob', 69 'postcode', 70 'other_info', # other identifying info in .data 71 'data_type', 72 'gender', 73 'requestor', # Requestor of data (e.g. who ordered test results) if available in source data. 74 'external_data_id', # ID of content of .data in external system (e.g. importer) where appropriate 75 'comment', # a free text comment on this row, eg. why is it here, error logs etc 76 'pk_identity_disambiguated', 77 'pk_provider_disambiguated' # The provider the data is relevant to. 78 ] 79 #--------------------------------------------------------
80 - def format(self):
81 return '%s' % self
82 #--------------------------------------------------------
84 tmp = '%s %s %s' % ( 85 gmTools.coalesce(self._payload[self._idx['lastnames']], '', 'last=%s'), 86 gmTools.coalesce(self._payload[self._idx['firstnames']], '', 'first=%s'), 87 gmTools.coalesce(self._payload[self._idx['gender']], '', 'gender=%s') 88 ) 89 if self._payload[self._idx['dob']] is not None: 90 tmp += ' dob=%s' % gmDateTime.pydt_strftime(self._payload[self._idx['dob']], '%Y %b %d') 91 return tmp
92 93 patient_identification = property(_format_patient_identification, lambda x:x) 94 95 #--------------------------------------------------------
96 - def update_data_from_file(self, fname=None):
97 # sanity check 98 if not (os.access(fname, os.R_OK) and os.path.isfile(fname)): 99 _log.error('[%s] is not a readable file' % fname) 100 return False 101 102 _log.debug('updating [pk=%s] from [%s]', self.pk_obj, fname) 103 gmPG2.file2bytea ( 104 query = "UPDATE clin.incoming_data_unmatched SET data = %(data)s::bytea WHERE pk = %(pk)s", 105 filename = fname, 106 args = {'pk': self.pk_obj} 107 ) 108 109 # must update XMIN now ... 110 self.refetch_payload() 111 return True
112 113 #--------------------------------------------------------
114 - def save_to_file(self, aChunkSize=0, filename=None):
115 116 if self._payload[self._idx['data_size']] == 0: 117 return None 118 119 if self._payload[self._idx['data_size']] is None: 120 return None 121 122 if filename is None: 123 filename = gmTools.get_unique_filename(prefix = 'gm-incoming_data_unmatched-') 124 125 success = gmPG2.bytea2file ( 126 data_query = { 127 'cmd': 'SELECT substring(data from %(start)s for %(size)s) FROM clin.incoming_data_unmatched WHERE pk = %(pk)s', 128 'args': {'pk': self.pk_obj} 129 }, 130 filename = filename, 131 chunk_size = aChunkSize, 132 data_size = self._payload[self._idx['data_size']] 133 ) 134 135 if not success: 136 return None 137 138 return filename
139 140 #--------------------------------------------------------
141 - def lock(self, exclusive=False):
142 return gmPG2.lock_row(table = 'clin.incoming_data_unmatched', pk = self.pk_obj, exclusive = exclusive)
143 144 #--------------------------------------------------------
145 - def unlock(self, exclusive=False):
146 return gmPG2.unlock_row(table = 'clin.incoming_data_unmatched', pk = self.pk_obj, exclusive = exclusive)
147 148 #------------------------------------------------------------
149 -def get_incoming_data(order_by=None, return_pks=False):
150 if order_by is None: 151 order_by = 'true' 152 else: 153 order_by = 'true ORDER BY %s' % order_by 154 cmd = _SQL_get_incoming_data % order_by 155 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True) 156 if return_pks: 157 return [ r['pk_incoming_data_unmatched'] for r in rows ] 158 return [ cIncomingData(row = {'data': r, 'idx': idx, 'pk_field': 'pk_incoming_data_unmatched'}) for r in rows ]
159 160 #------------------------------------------------------------
161 -def create_incoming_data(data_type, filename):
162 args = {'typ': data_type} 163 cmd = """ 164 INSERT INTO clin.incoming_data_unmatched (type, data) 165 VALUES (%(typ)s, 'new data'::bytea) 166 RETURNING pk""" 167 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False) 168 pk = rows[0]['pk'] 169 incoming = cIncomingData(aPK_obj = pk) 170 if not incoming.update_data_from_file(fname = filename): 171 _log.debug('cannot update newly created incoming_data record from file, deleting stub') 172 delete_incoming_data(incoming_data = pk) 173 return None 174 return incoming
175 176 #------------------------------------------------------------
177 -def delete_incoming_data(pk_incoming_data=None):
178 args = {'pk': pk_incoming_data} 179 cmd = "DELETE FROM clin.incoming_data_unmatched WHERE pk = %(pk)s" 180 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 181 return True
182 183 #============================================================ 184 # main 185 #------------------------------------------------------------ 186 if __name__ == "__main__": 187 188 if len(sys.argv) < 2: 189 sys.exit() 190 191 if sys.argv[1] != 'test': 192 sys.exit() 193 194 from Gnumed.pycommon import gmLog2 195 196 gmDateTime.init() 197 gmTools.gmPaths() 198 199 #-------------------------------------------------------
200 - def test_incoming_data():
201 for d in get_incoming_data(): 202 print(d)
203 204 #------------------------------------------------------- 205 test_incoming_data() 206