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