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