Gnumed.wxpython.gmProviderInboxWidgets

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                  msg = _('There is a message about patient [%s].\n\n'
    811                          'However, I cannot find that\n'
    812                          'patient in the GNUmed database.'
    813                  ) % pk_patient
    814                  pat = None
    815                  try:
    816                          pat = gmPerson.cPerson(aPK_obj = pk_patient)
    817                  except gmExceptions.ConstructorError:
    818                          _log.exception('patient [%s] not found', pk_patient)
    819                  finally:
    820                          wx.EndBusyCursor()
    821                  if pat is None:
    822                          gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
    823                          return False
    824
    825                  success = set_active_patient(patient = pat)
    826                  if not success:
    827                          gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
    828                          return False
    829
    830                  return True
    831          #--------------------------------------------------------
    832 -        def _goto_doc_review(self, pk_context=None, pk_patient=None):
    833
    834                  msg = _('Supposedly there are unreviewed documents\n'
    835                          'for patient [%s]. However, I cannot find\n'
    836                          'that patient in the GNUmed database.'
    837                  ) % pk_patient
    838
    839                  wx.BeginBusyCursor()
    840
    841                  try:
    842                          pat = gmPerson.cPerson(aPK_obj = pk_patient)
    843                  except gmExceptions.ConstructorError:
    844                          wx.EndBusyCursor()
    845                          _log.exception('patient [%s] not found', pk_patient)
    846                          gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
    847                          return False
    848
    849                  success = set_active_patient(patient = pat)
    850
    851                  wx.EndBusyCursor()
    852
    853                  if not success:
    854                          gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
    855                          return False
    856
    857                  gmDispatcher.send(signal = 'display_widget', name = 'gmShowMedDocs', sort_mode = 'review')
    858                  return True
    859          #--------------------------------------------------------
    860 -        def _goto_measurements_review(self, pk_context=None, pk_patient=None):
    861
    862                  msg = _('Supposedly there are unreviewed results\n'
    863                          'for patient [%s]. However, I cannot find\n'
    864                          'that patient in the GNUmed database.'
    865                  ) % pk_patient
    866
    867                  wx.BeginBusyCursor()
    868
    869                  try:
    870                          pat = gmPerson.cPerson(aPK_obj = pk_patient)
    871                  except gmExceptions.ConstructorError:
    872                          wx.EndBusyCursor()
    873                          _log.exception('patient [%s] not found', pk_patient)
    874                          gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
    875                          return False
    876
    877                  success = set_active_patient(patient = pat)
    878
    879                  wx.EndBusyCursor()
    880
    881                  if not success:
    882                          gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
    883                          return False
    884
    885                  gmDispatcher.send(signal = 'display_widget', name = 'gmMeasurementsGridPlugin')
    886                  return True
    887          #--------------------------------------------------------
    888 -        def _goto_vaccination_review(self, pk_context=None, pk_patient=None):
    889
    890                  msg = _('Supposedly there are conflicting vaccinations\n'
    891                          'for patient [%s]. However, I cannot find\n'
    892                          'that patient in the GNUmed database.'
    893                  ) % pk_patient
    894
    895                  wx.BeginBusyCursor()
    896
    897                  try:
    898                          pat = gmPerson.cPerson(aPK_obj = pk_patient)
    899                  except gmExceptions.ConstructorError:
    900                          wx.EndBusyCursor()
    901                          _log.exception('patient [%s] not found', pk_patient)
    902                          gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
    903                          return False
    904
    905                  success = set_active_patient(patient = pat)
    906
    907                  wx.EndBusyCursor()
    908
    909                  if not success:
    910                          gmGuiHelpers.gm_show_error(msg, _('handling provider inbox item'))
    911                          return False
    912
    913                  wx.CallAfter(manage_vaccinations)
    914
    915                  return True
    916
    917  #============================================================
    918  if __name__ == '__main__':
    919
    920          if len(sys.argv) < 2:
    921                  sys.exit()
    922
    923          if sys.argv[1] != 'test':
    924                  sys.exit()
    925
    926          gmI18N.activate_locale()
    927          gmI18N.install_domain(domain = 'gnumed')
    928
    929 -        def test_message_inbox():
    930                  app = wx.PyWidgetTester(size = (800, 600))
    931                  app.SetWidget(cProviderInboxPnl, -1)
    932                  app.MainLoop()
    933
    934 -        def test_msg_ea():
    935                  app = wx.PyWidgetTester(size = (800, 600))
    936                  app.SetWidget(cInboxMessageEAPnl, -1)
    937                  app.MainLoop()
    938
    939
    940          #test_message_inbox()
    941          test_msg_ea()
    942
    943  #============================================================
    944