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

Source Code for Module Gnumed.business.gmAllergy

  1  """GnuMed allergy related business object. 
  2  """ 
  3  #============================================================ 
  4  # $Source: /cvsroot/gnumed/gnumed/gnumed/client/business/gmAllergy.py,v $ 
  5  # $Id: gmAllergy.py,v 1.34 2009/06/29 14:49:42 ncq Exp $ 
  6  __version__ = "$Revision: 1.34 $" 
  7  __author__ = "Carlos Moro <cfmoro1976@yahoo.es>" 
  8  __license__ = "GPL" 
  9   
 10  import types, sys, logging, datetime as pyDT 
 11   
 12   
 13  if __name__ == '__main__': 
 14          sys.path.insert(0, '../../') 
 15  from Gnumed.pycommon import gmPG2, gmI18N, gmBusinessDBObject, gmDateTime 
 16   
 17   
 18  _log = logging.getLogger('gm.domain') 
 19  _log.info(__version__) 
 20  #============================================================ 
 21  # allergy state related code 
 22  #============================================================ 
 23  allergy_states = [ 
 24          None,           # unknown 
 25          0,                      # no allergies 
 26          1                       # some allergies 
 27  ] 
 28  #------------------------------------------------------------ 
29 -def ensure_has_allergy_state(encounter=None):
30 31 args = {'enc': encounter} 32 33 cmd_create = u""" 34 insert into clin.allergy_state (fk_encounter, has_allergy) 35 36 select %(enc)s, NULL 37 where not exists ( 38 select 1 from clin.v_pat_allergy_state 39 where pk_patient = ( 40 select fk_patient from clin.encounter where pk = %(enc)s 41 ) 42 )""" 43 44 cmd_search = u""" 45 select pk_allergy_state from clin.v_pat_allergy_state 46 where pk_patient = ( 47 select fk_patient from clin.encounter where pk = %(enc)s 48 )""" 49 50 rows, idx = gmPG2.run_rw_queries ( 51 queries = [ 52 {'cmd': cmd_create, 'args': args}, 53 {'cmd': cmd_search, 'args': args} 54 ], 55 return_data = True 56 ) 57 58 return cAllergyState(aPK_obj = rows[0][0])
59 #------------------------------------------------------------
60 -class cAllergyState(gmBusinessDBObject.cBusinessDBObject):
61 """Represents the allergy state of one patient.""" 62 63 _cmd_fetch_payload = u"select * from clin.v_pat_allergy_state where pk_allergy_state = %s" 64 _cmds_store_payload = [ 65 u"""update clin.allergy_state set 66 last_confirmed = %(last_confirmed)s, 67 has_allergy = %(has_allergy)s, 68 comment = %(comment)s 69 where 70 pk = %(pk_allergy_state)s and 71 xmin = %(xmin_allergy_state)s""", 72 u"""select xmin_allergy_state from clin.v_pat_allergy_state where pk_allergy_state = %(pk_allergy_state)s""" 73 ] 74 _updatable_fields = [ 75 'last_confirmed', # special value u'now' will set to datetime.datetime.now() in the local time zone 76 'has_allergy', # verified against allergy_states (see above) 77 'comment' # u'' maps to None / NULL 78 ] 79 #-------------------------------------------------------- 80 # properties 81 #--------------------------------------------------------
82 - def _get_as_string(self):
83 if self._payload[self._idx['has_allergy']] is None: 84 return _('unknown allergy state') 85 if self._payload[self._idx['has_allergy']] == 0: 86 return _('no known allergies') 87 if self._payload[self._idx['has_allergy']] == 1: 88 return _('*does* have allergies') 89 _log.error('unknown allergy state [%s]', self._payload[self._idx['has_allergy']]) 90 return _('ERROR: unknown allergy state [%s]') % self._payload[self._idx['has_allergy']]
91
92 - def _set_string(self, value):
93 raise AttributeError('invalid to set allergy state string')
94 95 state_string = property(_get_as_string, _set_string) 96 #--------------------------------------------------------
97 - def _get_as_symbol(self):
98 if self._payload[self._idx['has_allergy']] is None: 99 if self._payload[self._idx['comment']] is None: 100 return u'?' 101 else: 102 return u'?!' 103 if self._payload[self._idx['has_allergy']] == 0: 104 if self._payload[self._idx['comment']] is None: 105 return u'\u2300' 106 else: 107 return u'\u2300!' 108 if self._payload[self._idx['has_allergy']] == 1: 109 return '!' 110 _log.error('unknown allergy state [%s]', self._payload[self._idx['has_allergy']]) 111 return _('ERROR: unknown allergy state [%s]') % self._payload[self._idx['has_allergy']]
112
113 - def _set_symbol(self, value):
114 raise AttributeError('invalid to set allergy state symbol')
115 116 state_symbol = property(_get_as_symbol, _set_symbol) 117 #--------------------------------------------------------
118 - def __setitem__(self, attribute, value):
119 if attribute == u'comment': 120 if value is not None: 121 if value.strip() == u'': 122 value = None 123 124 elif attribute == u'last_confirmed': 125 if value == u'now': 126 value = pyDT.datetime.now(tz = gmDateTime.gmCurrentLocalTimezone) 127 128 elif attribute == u'has_allergy': 129 if value not in allergy_states: 130 raise ValueError('invalid allergy state [%s]' % value) 131 132 gmBusinessDBObject.cBusinessDBObject.__setitem__(self, attribute, value)
133 #============================================================
134 -class cAllergy(gmBusinessDBObject.cBusinessDBObject):
135 """Represents one allergy item. 136 137 Actually, those things are really things to *avoid*. 138 Allergy is just one of several reasons for that. 139 See Adrian's post on gm-dev. 140 141 Another word might be Therapeutic Precautions. 142 """ 143 _cmd_fetch_payload = u"select * from clin.v_pat_allergies where pk_allergy=%s" 144 _cmds_store_payload = [ 145 u"""update clin.allergy set 146 clin_when=%(date)s, 147 substance=%(substance)s, 148 substance_code=%(substance_code)s, 149 generics=%(generics)s, 150 allergene=%(allergene)s, 151 atc_code=%(atc_code)s, 152 fk_type=%(pk_type)s, 153 generic_specific=%(generic_specific)s::boolean, 154 definite=%(definite)s::boolean, 155 narrative=%(reaction)s 156 where 157 pk=%(pk_allergy)s and 158 xmin=%(xmin_allergy)s""", 159 u"""select xmin_allergy from clin.v_pat_allergies where pk_allergy=%(pk_allergy)s""" 160 ] 161 _updatable_fields = [ 162 'date', 163 'substance', 164 'substance_code', 165 'generics', 166 'allergene', 167 'atc_code', 168 'pk_type', 169 'generic_specific', 170 'definite', 171 'reaction' 172 ] 173 #--------------------------------------------------------
174 - def __setitem__(self, attribute, value):
175 if attribute == 'pk_type': 176 if value in ['allergy', 'sensitivity']: 177 cmd = u'select pk from clin._enum_allergy_type where value=%s' 178 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [value]}]) 179 value = rows[0][0] 180 181 gmBusinessDBObject.cBusinessDBObject.__setitem__(self, attribute, value)
182 #============================================================ 183 # convenience functions 184 #------------------------------------------------------------
185 -def create_allergy(substance=None, allg_type=None, episode_id=None, encounter_id=None):
186 """Creates a new allergy clinical item. 187 188 substance - allergic substance 189 allg_type - allergy or sensitivity, pk or string 190 encounter_id - encounter's primary key 191 episode_id - episode's primary key 192 """ 193 # sanity checks: 194 # 1) any of the args being None should fail the SQL code 195 # 2) do episode/encounter belong to the same patient ? 196 cmd = u""" 197 select pk_patient from clin.v_pat_episodes where pk_episode=%s 198 union 199 select fk_patient from clin.encounter where pk=%s""" 200 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [episode_id, encounter_id]}]) 201 202 if len(rows) == 0: 203 raise ValueError('error checking episode [%s] <-> encounter [%s] consistency' % (episode_id, encounter_id)) 204 205 if len(rows) > 1: 206 raise ValueError('episode [%s] and encounter [%s] belong to different patients !?!' % (episode_id, encounter_id)) 207 208 pat_id = rows[0][0] 209 210 cmd = u'select pk_allergy from clin.v_pat_allergies where pk_patient=%(pat)s and substance=%(substance)s' 211 args = {'pat': pat_id, 'substance': substance} 212 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 213 if len(rows) > 0: 214 # don't implicitely change existing data 215 return cAllergy(aPK_obj = rows[0][0]) 216 217 # insert new allergy 218 queries = [] 219 220 if type(allg_type) == types.IntType: 221 cmd = u""" 222 insert into clin.allergy (fk_type, fk_encounter, fk_episode, substance) 223 values (%s, %s, %s, %s)""" 224 else: 225 cmd = u""" 226 insert into clin.allergy (fk_type, fk_encounter, fk_episode, substance) 227 values ((select pk from clin._enum_allergy_type where value = %s), %s, %s, %s)""" 228 queries.append({'cmd': cmd, 'args': [allg_type, encounter_id, episode_id, substance]}) 229 230 cmd = u"select currval('clin.allergy_id_seq')" 231 queries.append({'cmd': cmd}) 232 233 rows, idx = gmPG2.run_rw_queries(queries=queries, return_data=True) 234 allergy = cAllergy(aPK_obj = rows[0][0]) 235 236 return allergy
237 #============================================================ 238 # main - unit testing 239 #------------------------------------------------------------ 240 if __name__ == '__main__': 241 242 allg = cAllergy(aPK_obj=1) 243 print allg 244 fields = allg.get_fields() 245 for field in fields: 246 print field, ':', allg[field] 247 print "updatable:", allg.get_updatable_fields() 248 enc_id = allg['pk_encounter'] 249 epi_id = allg['pk_episode'] 250 status, allg = create_allergy ( 251 substance = 'test substance', 252 allg_type=1, 253 episode_id = epi_id, 254 encounter_id = enc_id 255 ) 256 print allg 257 allg['reaction'] = 'hehehe' 258 status, data = allg.save_payload() 259 print 'status:', status 260 print 'data:', data 261 print allg 262 #============================================================ 263 # $Log: gmAllergy.py,v $ 264 # Revision 1.34 2009/06/29 14:49:42 ncq 265 # - improved wording of allergy state 266 # 267 # Revision 1.33 2009/02/20 15:41:24 ncq 268 # - fix ensure_has_allergy_state 269 # 270 # Revision 1.32 2008/10/22 12:03:46 ncq 271 # - better documentation 272 # - better allergy state symbols 273 # - improved __setitem__ on allergy state 274 # 275 # Revision 1.31 2008/10/12 15:10:05 ncq 276 # - allergic -> allergy 277 # 278 # Revision 1.30 2008/10/12 15:02:43 ncq 279 # - no more allergy state -1 280 # - ensure_has_allergic_state() 281 # - cAllergyState 282 # 283 # Revision 1.29 2008/01/30 13:34:49 ncq 284 # - switch to std lib logging 285 # 286 # Revision 1.28 2007/10/25 12:17:28 ncq 287 # - robustify stringification of allergic state 288 # 289 # Revision 1.27 2007/08/20 14:17:59 ncq 290 # - note on what an "allergy" really is to capture Adrian Midgleys input 291 # 292 # Revision 1.26 2007/03/26 16:48:34 ncq 293 # - various id -> pk/fk type fixes 294 # 295 # Revision 1.25 2007/03/21 08:09:07 ncq 296 # - add allergic_states 297 # - add allergic_state2str() 298 # 299 # Revision 1.24 2007/03/18 12:54:39 ncq 300 # - allow string and integer for setting pk_type on allergy 301 # 302 # Revision 1.24 2007/03/12 12:23:23 ncq 303 # - error handling now more exception centric 304 # 305 # Revision 1.23 2006/10/28 15:02:24 ncq 306 # - remove superfluous xmin_allergy 307 # 308 # Revision 1.22 2006/10/08 14:27:52 ncq 309 # - convert to cBusinessDBObject 310 # - convert to gmPG2 311 # 312 # Revision 1.21 2006/07/19 20:25:00 ncq 313 # - gmPyCompat.py is history 314 # 315 # Revision 1.20 2005/11/27 12:44:57 ncq 316 # - clinical tables are in schema "clin" now 317 # 318 # Revision 1.19 2005/04/30 13:30:02 sjtan 319 # 320 # id_patient is now pk_patient. 321 # 322 # Revision 1.18 2005/01/02 19:55:30 ncq 323 # - don't need _xmins_refetch_col_pos anymore 324 # 325 # Revision 1.17 2004/12/20 16:45:49 ncq 326 # - gmBusinessDBObject now requires refetching of XMIN after save_payload 327 # 328 # Revision 1.16 2004/12/15 21:52:05 ncq 329 # - improve unit test 330 # 331 # Revision 1.15 2004/11/03 22:32:34 ncq 332 # - support _cmds_lock_rows_for_update in business object base class 333 # 334 # Revision 1.14 2004/10/11 19:42:32 ncq 335 # - add license 336 # - adapt field names 337 # - some cleanup 338 # 339 # Revision 1.13 2004/06/28 12:18:41 ncq 340 # - more id_* -> fk_* 341 # 342 # Revision 1.12 2004/06/26 07:33:54 ncq 343 # - id_episode -> fk/pk_episode 344 # 345 # Revision 1.11 2004/06/14 08:22:10 ncq 346 # - cast to boolean in save payload 347 # 348 # Revision 1.10 2004/06/09 14:32:24 ncq 349 # - remove extraneous ()'s 350 # 351 # Revision 1.9 2004/06/08 00:41:38 ncq 352 # - fix imports, cleanup, improved self-test 353 # 354 # Revision 1.8 2004/06/02 21:47:27 ncq 355 # - improved sanity check in create_allergy() contributed by Carlos 356 # 357 # Revision 1.7 2004/05/30 18:33:28 ncq 358 # - cleanup, create_allergy, done mostly by Carlos 359 # 360 # Revision 1.6 2004/05/12 14:28:52 ncq 361 # - allow dict style pk definition in __init__ for multicolum primary keys (think views) 362 # - self.pk -> self.pk_obj 363 # - __init__(aPKey) -> __init__(aPK_obj) 364 # 365 # Revision 1.5 2004/04/20 13:32:33 ncq 366 # - improved __str__ output 367 # 368 # Revision 1.4 2004/04/20 00:17:55 ncq 369 # - allergies API revamped, kudos to Carlos 370 # 371 # Revision 1.3 2004/04/16 16:17:33 ncq 372 # - test save_payload 373 # 374 # Revision 1.2 2004/04/16 00:00:59 ncq 375 # - Carlos fixes 376 # - save_payload should now work 377 # 378 # Revision 1.1 2004/04/12 22:58:55 ncq 379 # - Carlos sent me this 380 # 381