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

Source Code for Module Gnumed.business.gmProviderInbox

  1  # -*- coding: latin-1 -*- 
  2  """GNUmed provider inbox middleware. 
  3   
  4  This should eventually end up in a class cPractice. 
  5  """ 
  6  #============================================================ 
  7  __license__ = "GPL" 
  8  __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>" 
  9   
 10   
 11  import sys 
 12   
 13   
 14  if __name__ == '__main__': 
 15          sys.path.insert(0, '../../') 
 16  from Gnumed.pycommon import gmPG2 
 17  from Gnumed.pycommon import gmBusinessDBObject 
 18  from Gnumed.pycommon import gmTools 
 19  from Gnumed.pycommon import gmDateTime 
 20   
 21  from Gnumed.business import gmStaff 
 22   
 23  #============================================================ 
 24  # provider message inbox 
 25  #------------------------------------------------------------ 
 26  _SQL_get_inbox_messages = u"SELECT * FROM dem.v_message_inbox WHERE %s" 
 27   
28 -class cInboxMessage(gmBusinessDBObject.cBusinessDBObject):
29 30 _cmd_fetch_payload = _SQL_get_inbox_messages % u"pk_inbox_message = %s" 31 _cmds_store_payload = [ 32 u""" 33 UPDATE dem.message_inbox SET 34 fk_staff = %(pk_staff)s, 35 fk_inbox_item_type = %(pk_type)s, 36 comment = gm.nullify_empty_string(%(comment)s), 37 data = gm.nullify_empty_string(%(data)s), 38 importance = %(importance)s, 39 fk_patient = %(pk_patient)s, 40 ufk_context = NULLIF(%(pk_context)s::integer[], ARRAY[NULL::integer]), 41 due_date = %(due_date)s, 42 expiry_date = %(expiry_date)s 43 WHERE 44 pk = %(pk_inbox_message)s 45 AND 46 xmin = %(xmin_message_inbox)s 47 RETURNING 48 pk as pk_inbox_message, 49 xmin as xmin_message_inbox 50 """ 51 ] 52 _updatable_fields = [ 53 u'pk_staff', 54 u'pk_type', 55 u'comment', 56 u'data', 57 u'importance', 58 u'pk_patient', 59 u'pk_context', 60 u'due_date', 61 u'expiry_date' 62 ] 63 #------------------------------------------------------------
64 - def format(self, with_patient=True):
65 tt = u'%s: %s%s\n' % ( 66 gmDateTime.pydt_strftime ( 67 self._payload[self._idx['received_when']], 68 format = '%A, %Y %b %d, %H:%M', 69 accuracy = gmDateTime.acc_minutes 70 ), 71 gmTools.bool2subst(self._payload[self._idx['is_virtual']], _('virtual message'), _('message')), 72 gmTools.coalesce(self._payload[self._idx['pk_inbox_message']], u'', u' #%s ') 73 ) 74 75 tt += u'%s: %s\n' % ( 76 self._payload[self._idx['l10n_category']], 77 self._payload[self._idx['l10n_type']] 78 ) 79 80 tt += u'%s %s %s\n' % ( 81 self._payload[self._idx['modified_by']], 82 gmTools.u_right_arrow, 83 gmTools.coalesce(self._payload[self._idx['provider']], _('everyone')) 84 ) 85 86 tt += u'\n%s%s%s\n\n' % ( 87 gmTools.u_left_double_angle_quote, 88 self._payload[self._idx['comment']], 89 gmTools.u_right_double_angle_quote 90 ) 91 92 if with_patient: 93 tt += gmTools.coalesce ( 94 self._payload[self._idx['pk_patient']], 95 u'', 96 u'%s\n\n' % _('Patient #%s') 97 ) 98 99 if self._payload[self._idx['due_date']] is not None: 100 if self._payload[self._idx['is_overdue']]: 101 template = _('Due: %s (%s ago)\n') 102 else: 103 template = _('Due: %s (in %s)\n') 104 tt += template % ( 105 gmDateTime.pydt_strftime(self._payload[self._idx['due_date']], '%Y %b %d'), 106 gmDateTime.format_interval_medically(self._payload[self._idx['interval_due']]) 107 ) 108 109 if self._payload[self._idx['expiry_date']] is not None: 110 if self._payload[self._idx['is_expired']]: 111 template = _('Expired: %s\n') 112 else: 113 template = _('Expires: %s\n') 114 tt += template % gmDateTime.pydt_strftime(self._payload[self._idx['expiry_date']], '%Y %b %d') 115 116 if self._payload[self._idx['data']] is not None: 117 tt += self._payload[self._idx['data']][:150] 118 if len(self._payload[self._idx['data']]) > 150: 119 tt += gmTools.u_ellipsis 120 121 return tt
122 #------------------------------------------------------------
123 -def get_reminders(pk_patient=None, order_by=None):
124 125 if order_by is None: 126 order_by = u'%s ORDER BY due_date, importance DESC, received_when DESC' 127 else: 128 order_by = u'%%s ORDER BY %s' % order_by 129 130 args = {'pat': pk_patient} 131 where_parts = [ 132 u'pk_patient = %(pat)s', 133 u'due_date IS NOT NULL' 134 ] 135 136 cmd = u"SELECT * FROM dem.v_message_inbox WHERE %s" % ( 137 order_by % u' AND '.join(where_parts) 138 ) 139 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) 140 141 return [ cInboxMessage(row = {'data': r, 'idx': idx, 'pk_field': 'pk_inbox_message'}) for r in rows ]
142 143 #------------------------------------------------------------
144 -def get_overdue_messages(pk_patient=None, order_by=None):
145 146 if order_by is None: 147 order_by = u'%s ORDER BY due_date, importance DESC, received_when DESC' 148 else: 149 order_by = u'%%s ORDER BY %s' % order_by 150 151 args = {'pat': pk_patient} 152 where_parts = [ 153 u'pk_patient = %(pat)s', 154 u'is_overdue IS TRUE' 155 ] 156 157 cmd = u"SELECT * FROM dem.v_message_inbox WHERE %s" % ( 158 order_by % u' AND '.join(where_parts) 159 ) 160 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) 161 162 return [ cInboxMessage(row = {'data': r, 'idx': idx, 'pk_field': 'pk_inbox_message'}) for r in rows ]
163 164 #------------------------------------------------------------
165 -def get_inbox_messages(pk_staff=None, pk_patient=None, include_without_provider=False, exclude_expired=False, expired_only=False, overdue_only=False, unscheduled_only=False, exclude_unscheduled=False, order_by=None):
166 167 if order_by is None: 168 order_by = u'%s ORDER BY importance desc, received_when desc' 169 else: 170 order_by = u'%%s ORDER BY %s' % order_by 171 172 args = {} 173 where_parts = [] 174 175 if pk_staff is not None: 176 if include_without_provider: 177 where_parts.append(u'((pk_staff IN (%(staff)s, NULL)) OR (modified_by = (SELECT short_alias FROM dem.staff WHERE pk = %(staff)s)))') 178 else: 179 where_parts.append(u'((pk_staff = %(staff)s) OR (modified_by = (SELECT short_alias FROM dem.staff WHERE pk = %(staff)s)))') 180 args['staff'] = pk_staff 181 182 if pk_patient is not None: 183 where_parts.append(u'pk_patient = %(pat)s') 184 args['pat'] = pk_patient 185 186 if exclude_expired: 187 where_parts.append(u'is_expired IS FALSE') 188 189 if expired_only: 190 where_parts.append(u'is_expired IS TRUE') 191 192 if overdue_only: 193 where_parts.append(u'is_overdue IS TRUE') 194 195 if unscheduled_only: 196 where_parts.append(u'due_date IS NULL') 197 198 if exclude_unscheduled: 199 where_parts.append(u'due_date IS NOT NULL') 200 201 cmd = _SQL_get_inbox_messages % ( 202 order_by % u' AND '.join(where_parts) 203 ) 204 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) 205 206 return [ cInboxMessage(row = {'data': r, 'idx': idx, 'pk_field': 'pk_inbox_message'}) for r in rows ]
207 #------------------------------------------------------------
208 -def create_inbox_message(message_type=None, subject=None, patient=None, staff=None, message_category=u'clinical'):
209 210 success, pk_type = gmTools.input2int(initial = message_type) 211 if not success: 212 pk_type = create_inbox_item_type(message_type = message_type, category = message_category) 213 214 cmd = u""" 215 INSERT INTO dem.message_inbox ( 216 fk_staff, 217 fk_patient, 218 fk_inbox_item_type, 219 comment 220 ) VALUES ( 221 %(staff)s, 222 %(pat)s, 223 %(type)s, 224 gm.nullify_empty_string(%(subject)s) 225 ) 226 RETURNING pk 227 """ 228 args = { 229 u'staff': staff, 230 u'pat': patient, 231 u'type': pk_type, 232 u'subject': subject 233 } 234 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False) 235 236 return cInboxMessage(aPK_obj = rows[0]['pk'])
237 #------------------------------------------------------------
238 -def delete_inbox_message(inbox_message=None):
239 args = {'pk': inbox_message} 240 cmd = u"DELETE FROM dem.message_inbox WHERE pk = %(pk)s" 241 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 242 return True
243 #------------------------------------------------------------
244 -def create_inbox_item_type(message_type=None, category=u'clinical'):
245 246 # determine category PK 247 success, pk_cat = gmTools.input2int(initial = category) 248 if not success: 249 args = {u'cat': category} 250 cmd = u"""SELECT COALESCE ( 251 (SELECT pk FROM dem.inbox_item_category WHERE _(description) = %(cat)s), 252 (SELECT pk FROM dem.inbox_item_category WHERE description = %(cat)s) 253 ) AS pk""" 254 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 255 if rows[0]['pk'] is None: 256 cmd = u"INSERT INTO dem.inbox_item_category (description) VALUES (%(cat)s) RETURNING pk" 257 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True) 258 pk_cat = rows[0]['pk'] 259 else: 260 pk_cat = rows[0]['pk'] 261 262 # find type PK or create type 263 args = {u'cat': pk_cat, u'type': message_type} 264 cmd = u"""SELECT COALESCE ( 265 (SELECT pk FROM dem.inbox_item_type where fk_inbox_item_category = %(cat)s and _(description) = %(type)s), 266 (SELECT pk FROM dem.inbox_item_type where fk_inbox_item_category = %(cat)s and description = %(type)s) 267 ) AS pk""" 268 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 269 if rows[0]['pk'] is None: 270 cmd = u""" 271 INSERT INTO dem.inbox_item_type ( 272 fk_inbox_item_category, 273 description, 274 is_user 275 ) VALUES ( 276 %(cat)s, 277 %(type)s, 278 TRUE 279 ) RETURNING pk""" 280 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True) 281 282 return rows[0]['pk']
283 284 #============================================================
285 -class cProviderInbox:
286 - def __init__(self, provider_id=None):
287 if provider_id is None: 288 self.__provider_id = gmStaff.gmCurrentProvider()['pk_staff'] 289 else: 290 self.__provider_id = provider_id
291 #--------------------------------------------------------
292 - def delete_message(self, pk=None):
293 return delete_inbox_message(inbox_message = pk)
294 #--------------------------------------------------------
295 - def add_message(message_type=None, subject=None, patient=None):
296 return create_inbox_message ( 297 message_type = message_type, 298 subject = subject, 299 patient = patient, 300 staff = self.__provider_id 301 )
302 #-------------------------------------------------------- 303 # properties 304 #--------------------------------------------------------
305 - def get_messages(self, pk_patient=None, include_without_provider=False, exclude_expired=False, expired_only=False, overdue_only=False, unscheduled_only=False, exclude_unscheduled=False, order_by=None):
306 return get_inbox_messages ( 307 pk_staff = self.__provider_id, 308 pk_patient = pk_patient, 309 include_without_provider = include_without_provider, 310 exclude_expired = exclude_expired, 311 expired_only = expired_only, 312 overdue_only = overdue_only, 313 unscheduled_only = unscheduled_only, 314 exclude_unscheduled = exclude_unscheduled, 315 order_by = order_by 316 )
317
318 - def _set_messages(self, messages):
319 return
320 321 messages = property(get_messages, _set_messages)
322 323 #============================================================ 324 # dynamic hints API 325 #------------------------------------------------------------ 326 _SQL_get_dynamic_hints = u"SELECT *, xmin AS xmin_auto_hint FROM ref.auto_hint WHERE %s" 327
328 -class cDynamicHint(gmBusinessDBObject.cBusinessDBObject):
329 """Represents dynamic hints to be run against the database.""" 330 331 _cmd_fetch_payload = _SQL_get_dynamic_hints % u"pk = %s" 332 _cmds_store_payload = [ 333 u"""UPDATE ref.auto_hint SET 334 is_active = %(is_active)s 335 WHERE 336 pk = %(pk)s 337 AND 338 xmin = %(xmin_auto_hint)s 339 RETURNING 340 pk, 341 xmin AS xmin_auto_hint 342 """ 343 ] 344 _updatable_fields = [ 345 u'is_active' 346 ] 347 #--------------------------------------------------------
348 - def format(self):
349 txt = u'%s [#%s]\n' % ( 350 gmTools.bool2subst(self._payload[self._idx['is_active']], _('Active clinical hint'), _('Inactive clinical hint')), 351 self._payload[self._idx['pk']] 352 ) 353 txt += u'\n' 354 txt += u'%s\n\n' % self._payload[self._idx['title']] 355 txt += _('Source: %s\n') % self._payload[self._idx['source']] 356 txt += _('Language: %s\n') % self._payload[self._idx['lang']] 357 txt += u'\n' 358 txt += u'%s\n' % gmTools.wrap(self._payload[self._idx['hint']], width = 50, initial_indent = u' ', subsequent_indent = u' ') 359 txt += u'\n' 360 txt += u'%s\n' % gmTools.wrap ( 361 gmTools.coalesce(self._payload[self._idx['url']], u''), 362 width = 50, 363 initial_indent = u' ', 364 subsequent_indent = u' ' 365 ) 366 txt += u'\n' 367 txt += u'%s\n' % gmTools.wrap(self._payload[self._idx['query']], width = 50, initial_indent = u' ', subsequent_indent = u' ') 368 return txt
369 370 #------------------------------------------------------------
371 -def get_dynamic_hints(order_by=None):
372 if order_by is None: 373 order_by = u'true' 374 else: 375 order_by = u'true ORDER BY %s' % order_by 376 377 cmd = _SQL_get_dynamic_hints % order_by 378 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True) 379 return [ cDynamicHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk'}) for r in rows ]
380 #------------------------------------------------------------ 381 #def create_xxx(xxx=None, xxx=None): 382 # 383 # args = { 384 # u'xxx': xxx, 385 # u'xxx': xxx 386 # } 387 # cmd = u""" 388 # INSERT INTO xxx.xxx ( 389 # xxx, 390 # xxx, 391 # xxx 392 # ) VALUES ( 393 # %(xxx)s, 394 # %(xxx)s, 395 # gm.nullify_empty_string(%(xxx)s) 396 # ) 397 # RETURNING pk 398 # """ 399 # rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False) 400 # 401 # return cDynamicHint(aPK_obj = rows[0]['pk']) 402 #------------------------------------------------------------ 403 #def delete_xxx(xxx=None): 404 # args = {'pk': xxx} 405 # cmd = u"DELETE FROM xxx.xxx WHERE pk = %(pk)s" 406 # gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 407 # return True 408 #------------------------------------------------------------ 409 410 #------------------------------------------------------------
411 -def get_hints_for_patient(pk_identity=None):
412 conn = gmPG2.get_connection() 413 curs = conn.cursor() 414 curs.callproc('clin.get_hints_for_patient', [pk_identity]) 415 rows = curs.fetchall() 416 idx = gmPG2.get_col_indices(curs) 417 return [ cDynamicHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk'}) for r in rows ]
418 419 #============================================================ 420 if __name__ == '__main__': 421 422 if len(sys.argv) < 2: 423 sys.exit() 424 425 if sys.argv[1] != 'test': 426 sys.exit() 427 428 from Gnumed.pycommon import gmI18N 429 430 gmI18N.activate_locale() 431 gmI18N.install_domain() 432 433 #---------------------------------------
434 - def test_inbox():
435 gmStaff.gmCurrentProvider(provider = gmStaff.cStaff()) 436 inbox = cProviderInbox() 437 for msg in inbox.messages: 438 print msg
439 #---------------------------------------
440 - def test_msg():
441 msg = cInboxMessage(aPK_obj = 1) 442 print msg
443 #---------------------------------------
444 - def test_create_type():
445 print create_inbox_item_type(message_type = 'test')
446 #---------------------------------------
447 - def test_due():
448 for msg in get_overdue_messages(pk_patient = 12): 449 print msg.format()
450 #---------------------------------------
451 - def test_auto_hints():
452 for row in get_dynamic_hints(pk_identity = 13): 453 print row
454 #--------------------------------------- 455 #test_inbox() 456 #test_msg() 457 #test_create_type() 458 #test_due() 459 test_auto_hints() 460 461 #============================================================ 462