Package Gnumed :: Package wxpython :: Module gmProviderInboxWidgets
[frames] | no frames]

Source Code for Module Gnumed.wxpython.gmProviderInboxWidgets

   1  """GNUmed provider inbox handling widgets. 
   2  """ 
   3  #================================================================ 
   4  __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>" 
   5   
   6  import sys 
   7  import logging 
   8   
   9   
  10  import wx 
  11   
  12   
  13  if __name__ == '__main__': 
  14          sys.path.insert(0, '../../') 
  15  from Gnumed.pycommon import gmI18N 
  16  from Gnumed.pycommon import gmExceptions 
  17  from Gnumed.pycommon import gmPG2 
  18  from Gnumed.pycommon import gmTools 
  19  from Gnumed.pycommon import gmDispatcher 
  20  from Gnumed.pycommon import gmMatchProvider 
  21  from Gnumed.pycommon import gmDateTime 
  22  from Gnumed.pycommon import gmNetworkTools 
  23   
  24  from Gnumed.business import gmPerson 
  25  from Gnumed.business import gmStaff 
  26  from Gnumed.business import gmProviderInbox 
  27  from Gnumed.business import gmClinicalRecord 
  28   
  29  from Gnumed.wxpython import gmGuiHelpers 
  30  from Gnumed.wxpython import gmListWidgets 
  31  from Gnumed.wxpython import gmPlugin 
  32  from Gnumed.wxpython import gmRegetMixin 
  33  from Gnumed.wxpython import gmPhraseWheel 
  34  from Gnumed.wxpython import gmEditArea 
  35  from Gnumed.wxpython import gmAuthWidgets 
  36  from Gnumed.wxpython import gmDataPackWidgets 
  37  from Gnumed.wxpython.gmPatSearchWidgets import set_active_patient 
  38  from Gnumed.wxpython.gmVaccWidgets import manage_vaccinations 
  39   
  40   
  41  _log = logging.getLogger('gm.ui') 
  42   
  43  _indicator = { 
  44          -1: '', 
  45          0: '', 
  46          1: '*!!*' 
  47  } 
  48   
  49  #==================================================================== 
50 -class cMessageTypePhraseWheel(gmPhraseWheel.cPhraseWheel):
51
52 - def __init__(self, *args, **kwargs):
53 54 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 55 56 query = u""" 57 SELECT DISTINCT ON (label) 58 pk_type, 59 (l10n_type || ' (' || l10n_category || ')') 60 AS label 61 FROM 62 dem.v_inbox_item_type 63 WHERE 64 l10n_type %(fragment_condition)s 65 OR 66 type %(fragment_condition)s 67 OR 68 l10n_category %(fragment_condition)s 69 OR 70 category %(fragment_condition)s 71 ORDER BY label 72 LIMIT 50""" 73 74 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query) 75 mp.setThresholds(1, 2, 4) 76 self.matcher = mp 77 self.SetToolTipString(_('Select a message type.'))
78 #----------------------------------------------------------------
79 - def _create_data(self):
80 if self.GetData() is not None: 81 return 82 83 val = self.GetValue().strip() 84 if val == u'': 85 return 86 87 self.SetText ( 88 value = val, 89 data = gmProviderInbox.create_inbox_item_type(message_type = val) 90 )
91 #====================================================================
92 -def _display_clinical_reminders():
93 wx.CallAfter(__display_clinical_reminders)
94 95 gmDispatcher.connect(signal = u'post_patient_selection', receiver = _display_clinical_reminders) 96
97 -def __display_clinical_reminders():
98 pat = gmPerson.gmCurrentPatient() 99 if not pat.connected: 100 return 101 for msg in pat.overdue_messages: 102 if msg['expiry_date'] is None: 103 exp = u'' 104 else: 105 exp = _(' - expires %s') % gmDateTime.pydt_strftime ( 106 msg['expiry_date'], 107 '%Y %b %d', 108 accuracy = gmDateTime.acc_days 109 ) 110 txt = _( 111 'Due for %s (since %s%s):\n' 112 '%s' 113 '%s' 114 '\n' 115 'Patient: %s\n' 116 'Reminder by: %s' 117 ) % ( 118 gmDateTime.format_interval_medically(msg['interval_due']), 119 gmDateTime.pydt_strftime(msg['due_date'], '%Y %b %d', accuracy = gmDateTime.acc_days), 120 exp, 121 gmTools.coalesce(msg['comment'], u'', u'\n%s\n'), 122 gmTools.coalesce(msg['data'], u'', u'\n%s\n'), 123 pat['description_gender'], 124 msg['modified_by'] 125 ) 126 gmGuiHelpers.gm_show_warning ( 127 aTitle = _('Clinical reminder'), 128 aMessage = txt 129 ) 130 for hint in pat.dynamic_hints: 131 txt = u'%s\n\n%s\n\n %s' % ( 132 hint['title'], 133 gmTools.wrap(hint['hint'], width = 50, initial_indent = u' ', subsequent_indent = u' '), 134 hint['source'] 135 ) 136 dlg = gmGuiHelpers.c2ButtonQuestionDlg ( 137 None, 138 -1, 139 caption = _('Clinical hint'), 140 question = txt, 141 button_defs = [ 142 {'label': _('OK'), 'tooltip': _('OK'), 'default': True}, 143 {'label': _('More info'), 'tooltip': _('Go to [%s]') % hint['url']} 144 ] 145 ) 146 button = dlg.ShowModal() 147 dlg.Destroy() 148 if button == wx.ID_NO: 149 gmNetworkTools.open_url_in_browser(hint['url'], autoraise = False) 150 151 return
152 #==================================================================== 153 from Gnumed.wxGladeWidgets import wxgInboxMessageEAPnl 154
155 -class cInboxMessageEAPnl(wxgInboxMessageEAPnl.wxgInboxMessageEAPnl, gmEditArea.cGenericEditAreaMixin):
156
157 - def __init__(self, *args, **kwargs):
158 159 try: 160 data = kwargs['message'] 161 del kwargs['message'] 162 except KeyError: 163 data = None 164 165 wxgInboxMessageEAPnl.wxgInboxMessageEAPnl.__init__(self, *args, **kwargs) 166 gmEditArea.cGenericEditAreaMixin.__init__(self) 167 168 # Code using this mixin should set mode and data 169 # after instantiating the class: 170 self.mode = 'new' 171 self.data = data 172 if data is not None: 173 self.mode = 'edit' 174 175 self.__init_ui()
176 #----------------------------------------------------------------
177 - def __init_ui(self):
178 if not gmPerson.gmCurrentPatient().connected: 179 self._CHBOX_active_patient.SetValue(False) 180 self._CHBOX_active_patient.Enable(False) 181 self._PRW_patient.Enable(True)
182 #---------------------------------------------------------------- 183 # generic Edit Area mixin API 184 #----------------------------------------------------------------
185 - def _valid_for_save(self):
186 validity = True 187 188 if self._TCTRL_subject.GetValue().strip() == u'': 189 validity = False 190 self.display_ctrl_as_valid(ctrl = self._TCTRL_subject, valid = False) 191 else: 192 self.display_ctrl_as_valid(ctrl = self._TCTRL_subject, valid = True) 193 194 if self._PRW_type.GetValue().strip() == u'': 195 validity = False 196 self._PRW_type.display_as_valid(False) 197 else: 198 self._PRW_type.display_as_valid(True) 199 200 missing_receiver = ( 201 (self._CHBOX_send_to_me.IsChecked() is False) 202 and 203 (self._PRW_receiver.GetData() is None) 204 ) 205 206 missing_patient = ( 207 (self._CHBOX_active_patient.IsChecked() is False) 208 and 209 (self._PRW_patient.person is None) 210 ) 211 212 if missing_receiver and missing_patient: 213 validity = False 214 self.display_ctrl_as_valid(ctrl = self._CHBOX_send_to_me, valid = False) 215 self._PRW_receiver.display_as_valid(False) 216 self.display_ctrl_as_valid(ctrl = self._CHBOX_active_patient, valid = False) 217 self.display_ctrl_as_valid(ctrl = self._PRW_patient, valid = False) 218 else: 219 self.display_ctrl_as_valid(ctrl = self._CHBOX_send_to_me, valid = True) 220 self._PRW_receiver.display_as_valid(True) 221 self.display_ctrl_as_valid(ctrl = self._CHBOX_active_patient, valid = True) 222 self.display_ctrl_as_valid(ctrl = self._PRW_patient, valid = True) 223 224 if self._PRW_due.is_valid_timestamp(allow_empty = True): 225 self._PRW_due.display_as_valid(True) 226 else: 227 # non-empty but also not valid 228 validity = False 229 self._PRW_due.display_as_valid(False) 230 231 if self._PRW_expiry.is_valid_timestamp(allow_empty = True): 232 self._PRW_expiry.display_as_valid(True) 233 else: 234 # non-empty but also not valid 235 validity = False 236 self._PRW_expiry.display_as_valid(False) 237 238 # if .due is not empty AND valid 239 if self._PRW_due.is_valid_timestamp(allow_empty = False): 240 # and if .expiry is ALSO not empty AND valid 241 if self._PRW_expiry.is_valid_timestamp(allow_empty = False): 242 # only then compare .due and .expiry 243 if not self._PRW_expiry.date > self._PRW_due.date: 244 validity = False 245 self._PRW_expiry.display_as_valid(False) 246 gmDispatcher.send(signal = 'statustext', msg = _('Message cannot expire before being due.')) 247 248 return validity
249 #----------------------------------------------------------------
250 - def _save_as_new(self):
251 252 pat_id = None 253 if self._CHBOX_active_patient.GetValue() is True: 254 pat_id = gmPerson.gmCurrentPatient().ID 255 else: 256 if self._PRW_patient.person is not None: 257 pat_id = self._PRW_patient.person.ID 258 259 receiver = None 260 if self._CHBOX_send_to_me.IsChecked(): 261 receiver = gmStaff.gmCurrentProvider()['pk_staff'] 262 else: 263 if self._PRW_receiver.GetData() is not None: 264 receiver = self._PRW_receiver.GetData() 265 266 msg = gmProviderInbox.create_inbox_message ( 267 patient = pat_id, 268 staff = receiver, 269 message_type = self._PRW_type.GetData(can_create = True), 270 subject = self._TCTRL_subject.GetValue().strip() 271 ) 272 273 msg['data'] = self._TCTRL_message.GetValue().strip() 274 275 if self._PRW_due.is_valid_timestamp(): 276 msg['due_date'] = self._PRW_due.date 277 278 if self._PRW_expiry.is_valid_timestamp(): 279 msg['expiry_date'] = self._PRW_expiry.date 280 281 if self._RBTN_normal.GetValue() is True: 282 msg['importance'] = 0 283 elif self._RBTN_high.GetValue() is True: 284 msg['importance'] = 1 285 else: 286 msg['importance'] = -1 287 288 msg.save() 289 self.data = msg 290 return True
291 #----------------------------------------------------------------
292 - def _save_as_update(self):
293 294 self.data['comment'] = self._TCTRL_subject.GetValue().strip() 295 self.data['pk_type'] = self._PRW_type.GetData(can_create = True) 296 297 if self._CHBOX_send_to_me.IsChecked(): 298 self.data['pk_staff'] = gmStaff.gmCurrentProvider()['pk_staff'] 299 else: 300 self.data['pk_staff'] = self._PRW_receiver.GetData() 301 302 self.data['data'] = self._TCTRL_message.GetValue().strip() 303 304 if self._CHBOX_active_patient.GetValue() is True: 305 self.data['pk_patient'] = gmPerson.gmCurrentPatient().ID 306 else: 307 if self._PRW_patient.person is None: 308 self.data['pk_patient'] = None 309 else: 310 self.data['pk_patient'] = self._PRW_patient.person.ID 311 312 if self._PRW_due.is_valid_timestamp(): 313 self.data['due_date'] = self._PRW_due.date 314 315 if self._PRW_expiry.is_valid_timestamp(): 316 self.data['expiry_date'] = self._PRW_expiry.date 317 318 if self._RBTN_normal.GetValue() is True: 319 self.data['importance'] = 0 320 elif self._RBTN_high.GetValue() is True: 321 self.data['importance'] = 1 322 else: 323 self.data['importance'] = -1 324 325 self.data.save() 326 return True
327 #----------------------------------------------------------------
328 - def _refresh_as_new(self):
329 self._TCTRL_subject.SetValue(u'') 330 self._PRW_type.SetText(value = u'', data = None) 331 self._CHBOX_send_to_me.SetValue(True) 332 self._PRW_receiver.Enable(False) 333 self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff']) 334 self._TCTRL_message.SetValue(u'') 335 self._PRW_due.SetText(data = None) 336 self._PRW_expiry.SetText(data = None) 337 self._RBTN_normal.SetValue(True) 338 self._RBTN_high.SetValue(False) 339 self._RBTN_low.SetValue(False) 340 341 self._PRW_patient.person = None 342 343 if gmPerson.gmCurrentPatient().connected: 344 self._CHBOX_active_patient.Enable(True) 345 self._CHBOX_active_patient.SetValue(True) 346 self._PRW_patient.Enable(False) 347 else: 348 self._CHBOX_active_patient.Enable(False) 349 self._CHBOX_active_patient.SetValue(False) 350 self._PRW_patient.Enable(True) 351 352 self._TCTRL_subject.SetFocus()
353 #----------------------------------------------------------------
355 self._refresh_as_new()
356 #----------------------------------------------------------------
357 - def _refresh_from_existing(self):
358 359 self._TCTRL_subject.SetValue(gmTools.coalesce(self.data['comment'], u'')) 360 self._PRW_type.SetData(data = self.data['pk_type']) 361 362 curr_prov = gmStaff.gmCurrentProvider() 363 curr_pat = gmPerson.gmCurrentPatient() 364 365 if curr_prov['pk_staff'] == self.data['pk_staff']: 366 self._CHBOX_send_to_me.SetValue(True) 367 self._PRW_receiver.Enable(False) 368 self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff']) 369 else: 370 self._CHBOX_send_to_me.SetValue(False) 371 self._PRW_receiver.Enable(True) 372 self._PRW_receiver.SetData(data = self.data['pk_staff']) 373 374 self._TCTRL_message.SetValue(gmTools.coalesce(self.data['data'], u'')) 375 376 if curr_pat.connected: 377 self._CHBOX_active_patient.Enable(True) 378 if curr_pat.ID == self.data['pk_patient']: 379 self._CHBOX_active_patient.SetValue(True) 380 self._PRW_patient.Enable(False) 381 self._PRW_patient.person = None 382 else: 383 self._CHBOX_active_patient.SetValue(False) 384 self._PRW_patient.Enable(True) 385 if self.data['pk_patient'] is None: 386 self._PRW_patient.person = None 387 else: 388 self._PRW_patient.person = gmPerson.cIdentity(aPK_obj = self.data['pk_patient']) 389 else: 390 self._CHBOX_active_patient.Enable(False) 391 self._CHBOX_active_patient.SetValue(False) 392 self._PRW_patient.Enable(True) 393 if self.data['pk_patient'] is None: 394 self._PRW_patient.person = None 395 else: 396 self._PRW_patient.person = gmPerson.cIdentity(aPK_obj = self.data['pk_patient']) 397 398 self._PRW_due.SetText(data = self.data['due_date']) 399 self._PRW_expiry.SetText(data = self.data['expiry_date']) 400 401 self._RBTN_normal.SetValue(False) 402 self._RBTN_high.SetValue(False) 403 self._RBTN_low.SetValue(False) 404 { -1: self._RBTN_low, 405 0: self._RBTN_normal, 406 1: self._RBTN_high 407 }[self.data['importance']].SetValue(True) 408 409 self._TCTRL_subject.SetFocus()
410 #---------------------------------------------------------------- 411 # event handlers 412 #----------------------------------------------------------------
413 - def _on_active_patient_checked(self, event):
414 if self._CHBOX_active_patient.IsChecked(): 415 self._PRW_patient.Enable(False) 416 self._PRW_patient.person = None 417 else: 418 self._PRW_patient.Enable(True)
419 #----------------------------------------------------------------
420 - def _on_send_to_me_checked(self, event):
421 if self._CHBOX_send_to_me.IsChecked(): 422 self._PRW_receiver.Enable(False) 423 self._PRW_receiver.SetData(data = gmStaff.gmCurrentProvider()['pk_staff']) 424 else: 425 self._PRW_receiver.Enable(True) 426 self._PRW_receiver.SetText(value = u'', data = None)
427 #============================================================
428 -def edit_inbox_message(parent=None, message=None, single_entry=True):
429 430 if parent is None: 431 parent = wx.GetApp().GetTopWindow() 432 433 ea = cInboxMessageEAPnl(parent = parent, id = -1) 434 ea.data = message 435 ea.mode = gmTools.coalesce(message, 'new', 'edit') 436 dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = single_entry) 437 dlg.SetTitle(gmTools.coalesce(message, _('Adding new inbox message'), _('Editing inbox message'))) 438 if dlg.ShowModal() == wx.ID_OK: 439 dlg.Destroy() 440 return True 441 dlg.Destroy() 442 return False
443 444 #============================================================
445 -def manage_reminders(parent=None, patient=None):
446 447 if parent is None: 448 parent = wx.GetApp().GetTopWindow() 449 #------------------------------------------------------------ 450 def refresh(lctrl): 451 reminders = gmProviderInbox.get_reminders(pk_patient = patient) 452 items = [ [ 453 gmTools.bool2subst ( 454 r['is_overdue'], 455 _('overdue for %s'), 456 _('due in %s') 457 ) % gmDateTime.format_interval_medically(r['interval_due']), 458 r['comment'], 459 r['pk_inbox_message'] 460 ] for r in reminders ] 461 lctrl.set_string_items(items) 462 lctrl.set_data(reminders)
463 #------------------------------------------------------------ 464 return gmListWidgets.get_choices_from_list ( 465 parent = parent, 466 msg = None, 467 caption = _('Reminders for the current patient'), 468 columns = [ _('Status'), _('Subject'), '#' ], 469 single_selection = False, 470 can_return_empty = True, 471 ignore_OK_button = False, 472 refresh_callback = refresh 473 # edit_callback=None, 474 # new_callback=None, 475 # delete_callback=None, 476 # left_extra_button=None, 477 # middle_extra_button=None, 478 # right_extra_button=None 479 ) 480 481 #============================================================ 482 from Gnumed.wxGladeWidgets import wxgProviderInboxPnl 483
484 -class cProviderInboxPnl(wxgProviderInboxPnl.wxgProviderInboxPnl, gmRegetMixin.cRegetOnPaintMixin):
485 486 _item_handlers = {} 487 488 #--------------------------------------------------------
489 - def __init__(self, *args, **kwds):
490 491 wxgProviderInboxPnl.wxgProviderInboxPnl.__init__(self, *args, **kwds) 492 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 493 494 self.provider = gmStaff.gmCurrentProvider() 495 self.__init_ui() 496 497 cProviderInboxPnl._item_handlers['clinical.review docs'] = self._goto_doc_review 498 cProviderInboxPnl._item_handlers['clinical.review results'] = self._goto_measurements_review 499 cProviderInboxPnl._item_handlers['clinical.review lab'] = self._goto_measurements_review 500 cProviderInboxPnl._item_handlers['clinical.review vaccs'] = self._goto_vaccination_review 501 502 self.__register_interests()
503 #-------------------------------------------------------- 504 # reget-on-paint API 505 #--------------------------------------------------------
506 - def _schedule_data_reget(self):
507 _log.debug('called by reget-on-paint mixin API') 508 gmRegetMixin.cRegetOnPaintMixin._schedule_data_reget(self)
509 #--------------------------------------------------------
510 - def _populate_with_data(self):
511 _log.debug('_populate_with_data() (after _schedule_data_reget ?)') 512 self.__populate_inbox() 513 return True
514 #-------------------------------------------------------- 515 # notebook plugin API 516 #--------------------------------------------------------
517 - def repopulate_ui(self):
518 _log.debug('called by notebook plugin API, skipping inbox loading') 519 #gmRegetMixin.cRegetOnPaintMixin.repopulate_ui(self) 520 return True
521 #-------------------------------------------------------- 522 # internal helpers 523 #--------------------------------------------------------
524 - def __register_interests(self):
525 gmDispatcher.connect(signal = u'message_inbox_generic_mod_db', receiver = self._on_message_inbox_generic_mod_db) 526 gmDispatcher.connect(signal = u'message_inbox_mod_db', receiver = self._on_message_inbox_mod_db) 527 # FIXME: listen for results insertion/deletion 528 gmDispatcher.connect(signal = u'reviewed_test_results_mod_db', receiver = self._on_results_mod_db) 529 gmDispatcher.connect(signal = u'identity_mod_db', receiver = self._on_identity_mod_db) 530 gmDispatcher.connect(signal = u'doc_mod_db', receiver = self._on_doc_mod_db) 531 gmDispatcher.connect(signal = u'doc_obj_review_mod_db', receiver = self._on_doc_obj_review_mod_db) 532 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection)
533 #--------------------------------------------------------
534 - def __init_ui(self):
535 self._LCTRL_provider_inbox.debug = 'provider inbox list' 536 537 self._LCTRL_provider_inbox.set_columns([u'', _('Sent'), _('Status'), _('Category - Type'), _('Message')]) 538 self._LCTRL_provider_inbox.searchable_columns = [2, 3, 4] 539 self._LCTRL_provider_inbox.item_tooltip_callback = self._get_msg_tooltip 540 541 self.__update_greeting() 542 543 if gmPerson.gmCurrentPatient().connected: 544 self._CHBOX_active_patient.Enable()
545 #--------------------------------------------------------
546 - def __update_greeting(self, no_of_messages=None):
547 msg = _(' Inbox of %s %s%s') % ( 548 gmTools.coalesce ( 549 self.provider['title'], 550 gmPerson.map_gender2salutation(self.provider['gender']) 551 ), 552 self.provider['lastnames'], 553 gmTools.coalesce(no_of_messages, u'.', _(': %s message(s)')) 554 ) 555 self._msg_welcome.SetLabel(msg)
556 #--------------------------------------------------------
557 - def __populate_inbox(self):
558 _log.debug('populating provider inbox') 559 560 # calculate constraints 561 pk_patient = None 562 if self._CHBOX_active_patient.IsChecked(): 563 _log.debug('restricting to active patient') 564 curr_pat = gmPerson.gmCurrentPatient() 565 if curr_pat.connected: 566 pk_patient = curr_pat.ID 567 568 include_without_provider = True 569 if self._CHBOX_active_provider.IsChecked(): 570 _log.debug('restricting to active provider directly') 571 include_without_provider = False 572 573 # get which messages to show 574 if self._RBTN_all_messages.GetValue(): 575 _log.debug('loading all but expired messages') 576 self.__msgs = self.provider.inbox.get_messages ( 577 pk_patient = pk_patient, 578 include_without_provider = include_without_provider, 579 exclude_expired = True, 580 expired_only = False, 581 overdue_only = False, 582 unscheduled_only = False, 583 exclude_unscheduled = False 584 ) 585 elif self._RBTN_overdue_messages.GetValue(): 586 _log.debug('loading overdue messages only') 587 self.__msgs = self.provider.inbox.get_messages ( 588 pk_patient = pk_patient, 589 include_without_provider = include_without_provider, 590 exclude_expired = True, 591 expired_only = False, 592 overdue_only = True, 593 unscheduled_only = False, 594 exclude_unscheduled = True, 595 order_by = u'due_date, importance DESC, received_when DESC' 596 ) 597 elif self._RBTN_scheduled_messages.GetValue(): 598 _log.debug('loading overdue messages only') 599 self.__msgs = self.provider.inbox.get_messages ( 600 pk_patient = pk_patient, 601 include_without_provider = include_without_provider, 602 exclude_expired = True, 603 expired_only = False, 604 overdue_only = False, 605 unscheduled_only = False, 606 exclude_unscheduled = True, 607 order_by = u'due_date, importance DESC, received_when DESC' 608 ) 609 elif self._RBTN_unscheduled_messages.GetValue(): 610 _log.debug('loading unscheduled messages only') 611 self.__msgs = self.provider.inbox.get_messages ( 612 pk_patient = pk_patient, 613 include_without_provider = include_without_provider, 614 exclude_expired = True, 615 expired_only = False, 616 overdue_only = False, 617 unscheduled_only = True, 618 exclude_unscheduled = False 619 ) 620 elif self._RBTN_expired_messages.GetValue(): 621 _log.debug('loading expired messages only') 622 self.__msgs = self.provider.inbox.get_messages ( 623 pk_patient = pk_patient, 624 include_without_provider = include_without_provider, 625 exclude_expired = False, 626 expired_only = True, 627 overdue_only = False, 628 unscheduled_only = False, 629 exclude_unscheduled = True, 630 order_by = u'expiry_date DESC, importance DESC, received_when DESC' 631 ) 632 633 _log.debug('total # of inbox msgs: %s', len(self.__msgs)) 634 635 items = [] 636 for m in self.__msgs: 637 item = [_indicator[m['importance']], gmDateTime.pydt_strftime(m['received_when'], '%Y-%m-%d')] 638 if m['due_date'] is None: 639 item.append(u'') 640 else: 641 if m['is_expired'] is True: 642 item.append(_('expired')) 643 else: 644 if m['is_overdue'] is True: 645 item.append(_('%s overdue') % gmDateTime.format_interval_medically(m['interval_due'])) 646 else: 647 item.append(_('due in %s') % gmDateTime.format_interval_medically(m['interval_due'])) 648 item.append(u'%s - %s' % (m['l10n_category'], m['l10n_type'])) 649 item.append(m['comment']) 650 items.append(item) 651 652 _log.debug('# of list items created from msgs: %s', len(items)) 653 self._LCTRL_provider_inbox.set_string_items(items = items) 654 self._LCTRL_provider_inbox.set_data(data = self.__msgs) 655 self._LCTRL_provider_inbox.set_column_widths() 656 self._TXT_inbox_item_comment.SetValue(u'') 657 self.__update_greeting(len(items))
658 #-------------------------------------------------------- 659 # event handlers 660 #--------------------------------------------------------
661 - def _on_results_mod_db(self):
662 _log.debug('reviewed_test_results_mod_db') 663 wx.CallAfter(self.__on_message_inbox_mod_db)
664 #--------------------------------------------------------
665 - def _on_identity_mod_db(self):
666 _log.debug('identity_mod_db') 667 wx.CallAfter(self.__on_message_inbox_mod_db)
668 #--------------------------------------------------------
669 - def _on_doc_obj_review_mod_db(self):
670 _log.debug('doc_obj_review_mod_db') 671 wx.CallAfter(self.__on_message_inbox_mod_db)
672 #--------------------------------------------------------
673 - def _on_doc_mod_db(self):
674 _log.debug('doc_mod_db') 675 wx.CallAfter(self.__on_message_inbox_mod_db)
676 #--------------------------------------------------------
677 - def _on_message_inbox_generic_mod_db(self, *args, **kwargs):
678 _log.debug('message_inbox_generic_mod_db') 679 wx.CallAfter(self.__on_message_inbox_mod_db)
680 #--------------------------------------------------------
681 - def _on_message_inbox_mod_db(self, *args, **kwargs):
682 _log.debug('message_inbox_mod_db') 683 wx.CallAfter(self.__on_message_inbox_mod_db)
684
685 - def __on_message_inbox_mod_db(self):
686 self._schedule_data_reget() 687 gmDispatcher.send(signal = u'request_user_attention', msg = _('Please check your GNUmed Inbox !'))
688 #--------------------------------------------------------
689 - def _on_post_patient_selection(self):
690 _log.debug('post_patient_selection') 691 wx.CallAfter(self.__on_post_patient_selection)
692
693 - def __on_post_patient_selection(self):
694 self._CHBOX_active_patient.Enable() 695 self._schedule_data_reget()
696 #--------------------------------------------------------
697 - def _lst_item_activated(self, evt):
698 699 try: 700 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True) 701 except IndexError: 702 _log.exception('problem with provider inbox item data access') 703 gmGuiHelpers.gm_show_error ( 704 aTitle = _('handling provider inbox item'), 705 aMessage = _('There was a problem accessing the message data.') 706 ) 707 _log.debug('effecting inbox reload') 708 wx.CallAfter(self.__populate_inbox) 709 return False 710 711 if msg is None: 712 return 713 714 handler_key = '%s.%s' % (msg['category'], msg['type']) 715 try: 716 handle_item = cProviderInboxPnl._item_handlers[handler_key] 717 except KeyError: 718 if msg['pk_patient'] is None: 719 gmGuiHelpers.gm_show_warning ( 720 _('No double-click action pre-programmed into\n' 721 'GNUmed for message category and type:\n' 722 '\n' 723 ' [%s]\n' 724 ) % handler_key, 725 _('handling provider inbox item') 726 ) 727 return False 728 handle_item = self._goto_patient 729 730 if not handle_item(pk_context = msg['pk_context'], pk_patient = msg['pk_patient']): 731 _log.error('item handler returned <False>') 732 _log.error('handler key: [%s]', handler_key) 733 _log.error('message: %s', str(msg)) 734 return False 735 736 return True
737 #--------------------------------------------------------
738 - def _lst_item_focused(self, evt):
739 pass
740 #--------------------------------------------------------
741 - def _lst_item_selected(self, evt):
742 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True) 743 if msg is None: 744 return 745 746 if msg['data'] is None: 747 tmp = _('Message: %s') % msg['comment'] 748 else: 749 tmp = _('Message: %s\nData: %s') % (msg['comment'], msg['data']) 750 751 self._TXT_inbox_item_comment.SetValue(tmp)
752 #--------------------------------------------------------
753 - def _lst_item_right_clicked(self, evt):
754 tmp = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True) 755 if tmp is None: 756 return 757 self.__focussed_msg = tmp 758 759 # build menu 760 menu = wx.Menu(title = _('Inbox Message Actions:')) 761 762 if self.__focussed_msg['pk_patient'] is not None: 763 ID = wx.NewId() 764 menu.AppendItem(wx.MenuItem(menu, ID, _('Activate patient'))) 765 wx.EVT_MENU(menu, ID, self._on_goto_patient) 766 767 if not self.__focussed_msg['is_virtual']: 768 # - delete message 769 ID = wx.NewId() 770 menu.AppendItem(wx.MenuItem(menu, ID, _('Delete'))) 771 wx.EVT_MENU(menu, ID, self._on_delete_focussed_msg) 772 # - edit message 773 ID = wx.NewId() 774 menu.AppendItem(wx.MenuItem(menu, ID, _('Edit'))) 775 wx.EVT_MENU(menu, ID, self._on_edit_focussed_msg) 776 777 # if self.__focussed_msg['pk_staff'] is not None: 778 # # - distribute to other providers 779 # ID = wx.NewId() 780 # menu.AppendItem(wx.MenuItem(menu, ID, _('Distribute'))) 781 # wx.EVT_MENU(menu, ID, self._on_distribute_focussed_msg) 782 783 # show menu 784 self.PopupMenu(menu, wx.DefaultPosition) 785 menu.Destroy()
786 #--------------------------------------------------------
788 self._TXT_inbox_item_comment.SetValue(u'') 789 _log.debug('_on_message_range_radiobutton_selected') 790 self.__populate_inbox()
791 #--------------------------------------------------------
792 - def _on_active_patient_checkbox_ticked(self, event):
793 self._TXT_inbox_item_comment.SetValue(u'') 794 _log.debug('_on_active_patient_checkbox_ticked') 795 self.__populate_inbox()
796 #--------------------------------------------------------
797 - def _on_active_provider_checkbox_ticked(self, event):
798 self._TXT_inbox_item_comment.SetValue(u'') 799 _log.debug('_on_active_provider_checkbox_ticked') 800 self.__populate_inbox()
801 #--------------------------------------------------------
802 - def _on_add_button_pressed(self, event):
803 edit_inbox_message(parent = self, message = None, single_entry = False)
804 #--------------------------------------------------------
805 - def _get_msg_tooltip(self, msg):
806 return msg.format()
807 #-------------------------------------------------------- 808 # item handlers 809 #--------------------------------------------------------
810 - def _on_goto_patient(self, evt):
811 return self._goto_patient(pk_patient = self.__focussed_msg['pk_patient'])
812 #--------------------------------------------------------
813 - def _on_delete_focussed_msg(self, evt):
814 if self.__focussed_msg['is_virtual']: 815 gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True) 816 return False 817 818 pk_patient = self.__focussed_msg['pk_patient'] 819 if pk_patient is not None: 820 emr = gmClinicalRecord.cClinicalRecord(aPKey = pk_patient, allow_user_interaction = False) 821 epi = emr.add_episode(episode_name = 'administration', is_open = False) 822 soap_cat = gmTools.bool2subst ( 823 (self.__focussed_msg['category'] == u'clinical'), 824 u'U', 825 None 826 ) 827 narr = _('Deleted inbox message:\n%s') % self.__focussed_msg.format(with_patient = False) 828 emr.add_clin_narrative(note = narr, soap_cat = soap_cat, episode = epi) 829 gmDispatcher.send(signal = 'statustext', msg = _('Recorded deletion of inbox message in EMR.'), beep = False) 830 831 if not self.provider.inbox.delete_message(self.__focussed_msg['pk_inbox_message']): 832 gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.')) 833 return False 834 return True
835 #--------------------------------------------------------
836 - def _on_edit_focussed_msg(self, evt):
837 if self.__focussed_msg['is_virtual']: 838 gmDispatcher.send(signal = 'statustext', msg = _('This message cannot be edited because it is virtual.')) 839 return False 840 edit_inbox_message(parent = self, message = self.__focussed_msg, single_entry = True) 841 return True
842 #--------------------------------------------------------
843 - def _on_distribute_focussed_msg(self, evt):
844 if self.__focussed_msg['pk_staff'] is None: 845 gmDispatcher.send(signal = 'statustext', msg = _('This message is already visible to all providers.')) 846 return False 847 print "now distributing" 848 return True
849 #--------------------------------------------------------
850 - def _goto_patient(self, pk_context=None, pk_patient=None):
851 852 wx.BeginBusyCursor() 853 854 msg = _('There is a message about patient [%s].\n\n' 855 'However, I cannot find that\n' 856 'patient in the GNUmed database.' 857 ) % pk_patient 858 859 try: 860 pat = gmPerson.cIdentity(aPK_obj = pk_patient) 861 except gmExceptions.ConstructorError: 862 wx.EndBusyCursor() 863 _log.exception('patient [%s] not found', pk_patient) 864 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 865 return False 866 except: 867 wx.EndBusyCursor() 868 raise 869 870 success = set_active_patient(patient = pat) 871 872 wx.EndBusyCursor() 873 874 if not success: 875 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 876 return False 877 878 return True
879 #--------------------------------------------------------
880 - def _goto_doc_review(self, pk_context=None, pk_patient=None):
881 882 msg = _('Supposedly there are unreviewed documents\n' 883 'for patient [%s]. However, I cannot find\n' 884 'that patient in the GNUmed database.' 885 ) % pk_patient 886 887 wx.BeginBusyCursor() 888 889 try: 890 pat = gmPerson.cIdentity(aPK_obj = pk_patient) 891 except gmExceptions.ConstructorError: 892 wx.EndBusyCursor() 893 _log.exception('patient [%s] not found', pk_patient) 894 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 895 return False 896 897 success = set_active_patient(patient = pat) 898 899 wx.EndBusyCursor() 900 901 if not success: 902 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 903 return False 904 905 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs', sort_mode = 'review') 906 return True
907 #--------------------------------------------------------
908 - def _goto_measurements_review(self, pk_context=None, pk_patient=None):
909 910 msg = _('Supposedly there are unreviewed results\n' 911 'for patient [%s]. However, I cannot find\n' 912 'that patient in the GNUmed database.' 913 ) % pk_patient 914 915 wx.BeginBusyCursor() 916 917 try: 918 pat = gmPerson.cIdentity(aPK_obj = pk_patient) 919 except gmExceptions.ConstructorError: 920 wx.EndBusyCursor() 921 _log.exception('patient [%s] not found', pk_patient) 922 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 923 return False 924 925 success = set_active_patient(patient = pat) 926 927 wx.EndBusyCursor() 928 929 if not success: 930 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 931 return False 932 933 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmMeasurementsGridPlugin') 934 return True
935 #--------------------------------------------------------
936 - def _goto_vaccination_review(self, pk_context=None, pk_patient=None):
937 938 msg = _('Supposedly there are conflicting vaccinations\n' 939 'for patient [%s]. However, I cannot find\n' 940 'that patient in the GNUmed database.' 941 ) % pk_patient 942 943 wx.BeginBusyCursor() 944 945 try: 946 pat = gmPerson.cIdentity(aPK_obj = pk_patient) 947 except gmExceptions.ConstructorError: 948 wx.EndBusyCursor() 949 _log.exception('patient [%s] not found', pk_patient) 950 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 951 return False 952 953 success = set_active_patient(patient = pat) 954 955 wx.EndBusyCursor() 956 957 if not success: 958 gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item')) 959 return False 960 961 wx.CallAfter(gmVaccWidgets.manage_vaccinations) 962 963 return True
964 #============================================================
965 -def browse_dynamic_hints(parent=None):
966 967 if parent is None: 968 parent = wx.GetApp().GetTopWindow() 969 #------------------------------------------------------------ 970 def get_tooltip(item): 971 if item is None: 972 return None 973 return item.format()
974 #------------------------------------------------------------ 975 def switch_activation(item): 976 conn = gmAuthWidgets.get_dbowner_connection(procedure = _('Switching clinical hint activation')) 977 if conn is None: 978 return False 979 item['is_active'] = not item['is_active'] 980 return item.save(conn = conn) 981 #------------------------------------------------------------ 982 def manage_data_packs(item): 983 gmDataPackWidgets.manage_data_packs(parent = parent) 984 return True 985 #------------------------------------------------------------ 986 def refresh(lctrl): 987 hints = gmProviderInbox.get_dynamic_hints(order_by = u'is_active DESC, source, hint') 988 items = [ [ 989 gmTools.bool2subst(h['is_active'], gmTools.u_checkmark_thin, u''), 990 h['title'], 991 h['source'][:30], 992 h['hint'][:60], 993 gmTools.coalesce(h['url'], u'')[:60], 994 h['lang'], 995 h['pk'] 996 ] for h in hints ] 997 lctrl.set_string_items(items) 998 lctrl.set_data(hints) 999 #------------------------------------------------------------ 1000 gmListWidgets.get_choices_from_list ( 1001 parent = parent, 1002 msg = _('\nDynamic hints registered with GNUmed.\n'), 1003 caption = _('Showing dynamic hints.'), 1004 columns = [ _('Active'), _('Title'), _('Source'), _('Hint'), u'URL', _('Language'), u'#' ], 1005 single_selection = True, 1006 refresh_callback = refresh, 1007 left_extra_button = ( 1008 _('(De)-Activate'), 1009 _('Switch activation of the selected hint'), 1010 switch_activation 1011 ), 1012 right_extra_button = ( 1013 _('Data packs'), 1014 _('Browse and install clinical hints data packs'), 1015 manage_data_packs 1016 ), 1017 list_tooltip_callback = get_tooltip 1018 ) 1019 1020 #============================================================ 1021 if __name__ == '__main__': 1022 1023 if len(sys.argv) < 2: 1024 sys.exit() 1025 1026 if sys.argv[1] != 'test': 1027 sys.exit() 1028 1029 gmI18N.activate_locale() 1030 gmI18N.install_domain(domain = 'gnumed') 1031
1032 - def test_message_inbox():
1033 app = wx.PyWidgetTester(size = (800, 600)) 1034 app.SetWidget(cProviderInboxPnl, -1) 1035 app.MainLoop()
1036
1037 - def test_msg_ea():
1038 app = wx.PyWidgetTester(size = (800, 600)) 1039 app.SetWidget(cInboxMessageEAPnl, -1) 1040 app.MainLoop()
1041 1042 1043 #test_message_inbox() 1044 test_msg_ea() 1045 1046 #============================================================ 1047