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

# Source Code for Module Gnumed.wxpython.gmHospitalStayWidgets

      1  """GNUmed hospital stay widgets"""
      2  #================================================================
      3  __author__ = "cfmoro1976@yahoo.es, karsten.hilbert@gmx.net"
      4  __license__ = "GPL v2 or later"
      5
      6  # stdlib
      7  import sys
      8  import logging
      9  import datetime as pydt
     10
     11
     12  # 3rd party
     13  import wx
     14
     15
     16  # GNUmed
     17  if __name__ == '__main__':
     18          sys.path.insert(0, '../../')
     19  from Gnumed.pycommon import gmI18N
     20  from Gnumed.pycommon import gmDateTime
     21  if __name__ == '__main__':
     22          gmI18N.activate_locale()
     23          gmI18N.install_domain()
     24          gmDateTime.init()
     25
     26  from Gnumed.pycommon import gmTools
     27  from Gnumed.pycommon import gmDispatcher
     28  from Gnumed.pycommon import gmMatchProvider
     29
     30  from Gnumed.business import gmEMRStructItems
     31  from Gnumed.business import gmPerson
     32
     33  from Gnumed.wxpython import gmPhraseWheel
     34  from Gnumed.wxpython import gmListWidgets
     35  from Gnumed.wxpython import gmEditArea
     36
     37
     38  _log = logging.getLogger('gm.ui')
     39
     40  #================================================================
     41  # hospitalizations related widgets/functions
     42  #----------------------------------------------------------------
     43 -def manage_hospital_stays(parent=None):
     44
     45          pat = gmPerson.gmCurrentPatient()
     46          emr = pat.emr
     47
     48          if parent is None:
     49                  parent = wx.GetApp().GetTopWindow()
     50
     51          #-----------------------------------------
     52          def get_tooltip(stay=None):
     53                  if stay is None:
     54                          return None
     55                  return stay.format (
     56                          include_procedures = True,
     57                          include_docs = True
     58                  )
     59
     60          #-----------------------------------------
     61          def edit(stay=None):
     62                  return edit_hospital_stay(parent = parent, hospital_stay = stay)
     63
     64          #-----------------------------------------
     65          def delete(stay=None):
     66                  if gmEMRStructItems.delete_hospital_stay(stay = stay['pk_hospital_stay']):
     67                          return True
     68                  gmDispatcher.send (
     69                          signal = 'statustext',
     70                          msg = _('Cannot delete hospitalization.'),
     71                          beep = True
     72                  )
     73                  return False
     74
     75          #-----------------------------------------
     76          def refresh(lctrl):
     77                  stays = emr.get_hospital_stays()
     78                  items = [
     79                          [
     80                                  s['admission'].strftime('%Y-%m-%d'),
     81                                  gmTools.coalesce(s['discharge'], '', function4value = ('strftime', '%Y-%m-%d')),
     82                                  s['episode'],
     83                                  '%s @ %s' % (s['ward'], s['hospital'])
     84                          ] for s in stays
     85                  ]
     86                  lctrl.set_string_items(items = items)
     87                  lctrl.set_data(data = stays)
     88          #-----------------------------------------
     89          gmListWidgets.get_choices_from_list (
     90                  parent = parent,
     91                  msg = _("The patient's hospitalizations:\n"),
     92                  caption = _('Editing hospitalizations ...'),
     93                  columns = [_('Admission'), _('Discharge'), _('Reason'), _('Hospital')],
     94                  single_selection = True,
     95                  edit_callback = edit,
     96                  new_callback = edit,
     97                  delete_callback = delete,
     98                  refresh_callback = refresh,
     99                  list_tooltip_callback = get_tooltip
    100          )
    101
    102  #----------------------------------------------------------------
    103 -def edit_hospital_stay(parent=None, hospital_stay=None, single_entry=True):
    104          ea = cHospitalStayEditAreaPnl(parent, -1)
    105          ea.data = hospital_stay
    106          ea.mode = gmTools.coalesce(hospital_stay, 'new', 'edit')
    107          dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea, single_entry = single_entry)
    108          dlg.SetTitle(gmTools.coalesce(hospital_stay, _('Adding a hospitalization'), _('Editing a hospitalization')))
    109          if dlg.ShowModal() == wx.ID_OK:
    110                  dlg.DestroyLater()
    111                  return True
    112          dlg.DestroyLater()
    113          return False
    114
    115  #----------------------------------------------------------------
    116 -class cHospitalWardPhraseWheel(gmPhraseWheel.cPhraseWheel):
    117          """Phrasewheel to allow selection of a hospitalization."""
    118 -        def __init__(self, *args, **kwargs):
    119
    120                  gmPhraseWheel.cPhraseWheel.__init__ (self, *args, **kwargs)
    121
    122                  query = """
    123                  SELECT data, list_label, field_label FROM (
    124                          SELECT DISTINCT ON (data) * FROM ((
    125
    126                                  -- already-used org_units
    127                                  SELECT
    128                                          pk_org_unit
    129                                                  AS data,
    130                                          ward || ' @ ' || hospital
    131                                                  AS list_label,
    132                                          ward || ' @ ' || hospital
    133                                                  AS field_label,
    134                                          1
    135                                                  AS rank
    136                                  FROM
    137                                          clin.v_hospital_stays
    138                                  WHERE
    139                                          ward %(fragment_condition)s
    140                                                  OR
    141                                          hospital %(fragment_condition)s
    142
    143                                  ) UNION ALL (
    144                                  -- wards
    145                                  SELECT
    146                                          pk_org_unit
    147                                                  AS data,
    148                                          unit || ' (' || l10n_unit_category || ') @ ' || organization
    149                                                  AS list_label,
    150                                          unit || ' @ ' || organization
    151                                                  AS field_label,
    152                                          2
    153                                                  AS rank
    154                                  FROM
    155                                          dem.v_org_units
    156                                  WHERE
    157                                          unit_category = 'Ward'
    158                                                  AND
    159                                          unit %(fragment_condition)s
    160                                                  AND
    161                                          NOT EXISTS (
    162                                                  SELECT 1 FROM clin.v_hospital_stays WHERE clin.v_hospital_stays.pk_org_unit = dem.v_org_units.pk_org_unit
    163                                          )
    164
    165                                  ) UNION ALL (
    166                                  -- hospital units
    167                                  SELECT
    168                                          pk_org_unit
    169                                                  AS data,
    170                                          unit || coalesce(' (' || l10n_unit_category || ')', '') || ' @ ' || organization || ' (' || l10n_organization_category || ')'
    171                                                  AS list_label,
    172                                          unit || ' @ ' || organization
    173                                                  AS field_label,
    174                                          3
    175                                                  AS rank
    176                                  FROM
    177                                          dem.v_org_units
    178                                  WHERE
    179                                          unit_category <> 'Ward'
    180                                                  AND
    181                                          organization_category = 'Hospital'
    182                                                  AND
    183                                          unit %(fragment_condition)s
    184                                                  AND
    185                                          NOT EXISTS (
    186                                                  SELECT 1 FROM clin.v_hospital_stays WHERE clin.v_hospital_stays.pk_org_unit = dem.v_org_units.pk_org_unit
    187                                          )
    188
    189                                  ) UNION ALL (
    190                                  -- any other units
    191                                  SELECT
    192                                          pk_org_unit
    193                                                  AS data,
    194                                          unit || coalesce(' (' || l10n_unit_category || ')', '') || ' @ ' || organization || ' (' || l10n_organization_category || ')'
    195                                                  AS list_label,
    196                                          unit || ' @ ' || organization
    197                                                  AS field_label,
    198                                          3
    199                                                  AS rank
    200                                  FROM
    201                                          dem.v_org_units
    202                                  WHERE
    203                                          unit_category <> 'Ward'
    204                                                  AND
    205                                          organization_category <> 'Hospital'
    206                                                  AND
    207                                          unit %(fragment_condition)s
    208                                                  AND
    209                                          NOT EXISTS (
    210                                                  SELECT 1 FROM clin.v_hospital_stays WHERE clin.v_hospital_stays.pk_org_unit = dem.v_org_units.pk_org_unit
    211                                          )
    212                          )) AS all_matches
    213                          ORDER BY data, rank
    214                  ) AS distinct_matches
    215                  ORDER BY rank, list_label
    216                  LIMIT 50
    217                  """
    218
    219                  mp = gmMatchProvider.cMatchProvider_SQL2(queries = [query])
    220                  mp.setThresholds(2, 4, 6)
    221                  self.matcher = mp
    222                  self.selection_only = True
    223
    224  #----------------------------------------------------------------
    225 -class cHospitalStayPhraseWheel(gmPhraseWheel.cPhraseWheel):
    226          """Phrasewheel to allow selection of a hospital-type org_unit."""
    227 -        def __init__(self, *args, **kwargs):
    228
    229                  gmPhraseWheel.cPhraseWheel.__init__ (self, *args, **kwargs)
    230
    231                  ctxt = {'ctxt_pat': {'where_part': '(pk_patient = %(pat)s) AND', 'placeholder': 'pat'}}
    232
    233                  mp = gmMatchProvider.cMatchProvider_SQL2 (
    234                          queries = [
    235  """
    236  SELECT
    237          pk_hospital_stay,
    238          descr
    239  FROM (
    240          SELECT DISTINCT ON (pk_hospital_stay)
    241                  pk_hospital_stay,
    242                  descr
    243          FROM
    244                  (SELECT
    245                          pk_hospital_stay,
    246                          (
    247                                  to_char(admission, 'YYYY-Mon-DD')
    248                                  || ' (' || ward || ' @ ' || hospital || '):'
    249                                  || episode
    250                                  || coalesce((' (' || health_issue || ')'), '')
    251                          ) AS descr
    252                   FROM
    253                          clin.v_hospital_stays
    254                   WHERE
    255                          %(ctxt_pat)s (
    256                                  hospital %(fragment_condition)s
    257                                          OR
    258                                  ward %(fragment_condition)s
    259                                          OR
    260                                  episode %(fragment_condition)s
    261                                          OR
    262                                  health_issue %(fragment_condition)s
    263                          )
    264                  ) AS the_stays
    265  ) AS distinct_stays
    266  ORDER BY descr
    267  LIMIT 25
    268  """                     ],
    269                          context = ctxt
    270                  )
    271                  mp.setThresholds(3, 4, 6)
    272                  mp.set_context('pat', gmPerson.gmCurrentPatient().ID)
    273
    274                  self.matcher = mp
    275                  self.selection_only = True
    276
    277  #----------------------------------------------------------------
    278  from Gnumed.wxGladeWidgets import wxgHospitalStayEditAreaPnl
    279
    280 -class cHospitalStayEditAreaPnl(wxgHospitalStayEditAreaPnl.wxgHospitalStayEditAreaPnl, gmEditArea.cGenericEditAreaMixin):
    281
    282 -        def __init__(self, *args, **kwargs):
    283                  wxgHospitalStayEditAreaPnl.wxgHospitalStayEditAreaPnl.__init__(self, *args, **kwargs)
    284                  gmEditArea.cGenericEditAreaMixin.__init__(self)
    285
    286          #----------------------------------------------------------------
    287          # generic Edit Area mixin API
    288          #----------------------------------------------------------------
    289 -        def _valid_for_save(self):
    290
    291                  valid = True
    292
    293                  if self._PRW_episode.GetValue().strip() == '':
    294                          valid = False
    295                          self._PRW_episode.display_as_valid(False)
    296                          self.StatusText = _('Must select an episode or enter a name for a new one. Cannot save hospitalization.')
    297                          self._PRW_episode.SetFocus()
    298
    299                  if not self._PRW_admission.is_valid_timestamp(empty_is_valid = False):
    300                          valid = False
    301                          self.StatusText = _('Missing admission data. Cannot save hospitalization.')
    302                          self._PRW_admission.SetFocus()
    303
    304                  if self._PRW_discharge.is_valid_timestamp(empty_is_valid = True):
    305                          if self._PRW_discharge.date is not None:
    306                                  adm = self._PRW_admission.date
    307                                  discharge = self._PRW_discharge.date
    308                                  # normalize for comparison
    309                                  discharge = discharge.replace (
    310                                          hour = adm.hour,
    311                                          minute = adm.minute,
    312                                          second = adm.second,
    313                                          microsecond = adm.microsecond
    314                                  )
    315                                  if adm is not None:
    316                                          if discharge == adm:
    317                                                  self._PRW_discharge.SetData(discharge + pydt.timedelta(seconds = 1))
    318                                          elif not self._PRW_discharge.date > self._PRW_admission.date:
    319                                                  valid = False
    320                                                  self._PRW_discharge.display_as_valid(False)
    321                                                  self.StatusText = _('Discharge date must be empty or later than admission. Cannot save hospitalization.')
    322                                                  self._PRW_discharge.SetFocus()
    323
    324                  if self._PRW_hospital.GetData() is None:
    325                          valid = False
    326                          self._PRW_hospital.display_as_valid(False)
    327                          self.StatusText = _('Must select a hospital. Cannot save hospitalization.')
    328                          self._PRW_hospital.SetFocus()
    329                  else:
    330                          self._PRW_hospital.display_as_valid(True)
    331
    332                  return (valid is True)
    333          #----------------------------------------------------------------
    334 -        def _save_as_new(self):
    335
    336                  pat = gmPerson.gmCurrentPatient()
    337                  emr = pat.emr
    338                  stay = emr.add_hospital_stay(episode = self._PRW_episode.GetData(can_create = True), fk_org_unit = self._PRW_hospital.GetData())
    339                  stay['comment'] = self._TCTRL_comment.GetValue().strip()
    340                  stay['admission'] = self._PRW_admission.GetData()
    341                  stay['discharge'] = self._PRW_discharge.GetData()
    342                  stay['comment'] = self._TCTRL_comment.GetValue()
    343                  stay.save_payload()
    344
    345                  self.data = stay
    346                  return True
    347          #----------------------------------------------------------------
    348 -        def _save_as_update(self):
    349
    350                  self.data['pk_episode'] = self._PRW_episode.GetData(can_create = True)
    351                  self.data['pk_org_unit'] = self._PRW_hospital.GetData()
    352                  self.data['admission'] = self._PRW_admission.GetData()
    353                  self.data['discharge'] = self._PRW_discharge.GetData()
    354                  self.data['comment'] = self._TCTRL_comment.GetValue()
    355                  self.data.save_payload()
    356
    357                  return True
    358          #----------------------------------------------------------------
    359 -        def _refresh_as_new(self):
    360                  self._PRW_hospital.SetText(value = '', data = None)
    361                  self._PRW_episode.SetText(value = '')
    362                  self._PRW_admission.SetText(data = gmDateTime.pydt_now_here())
    363                  self._PRW_discharge.SetText()
    364                  self._TCTRL_comment.SetValue('')
    365                  self._PRW_hospital.SetFocus()
    366          #----------------------------------------------------------------
    367 -        def _refresh_from_existing(self):
    368                  self._PRW_hospital.SetText(value = '%s @ %s' % (self.data['ward'], self.data['hospital']), data = self.data['pk_org_unit'])
    369
    370                  if self.data['pk_episode'] is not None:
    371                          self._PRW_episode.SetText(value = self.data['episode'], data = self.data['pk_episode'])
    372
    373                  self._PRW_admission.SetText(data = self.data['admission'])
    374                  self._PRW_discharge.SetText(data = self.data['discharge'])
    375                  self._TCTRL_comment.SetValue(gmTools.coalesce(self.data['comment'], ''))
    376
    377                  self._PRW_hospital.SetFocus()
    378          #----------------------------------------------------------------
    379 -        def _refresh_as_new_from_existing(self):
    380                  print("this was not expected to be used in this edit area")
    381
    382  #================================================================
    383  # main
    384  #----------------------------------------------------------------
    385  if __name__ == '__main__':
    386
    387          if len(sys.argv) < 2:
    388                  sys.exit()
    389
    390          if sys.argv[1] != 'test':
    391                  sys.exit()
    392
    393          from Gnumed.business import gmPersonSearch
    394          from Gnumed.wxpython import gmPatSearchWidgets
    395
    396          #================================================================
    397          # obtain patient
    398          pat = gmPersonSearch.ask_for_patient()
    399          if pat is None:
    400                  print("No patient. Exiting gracefully...")
    401                  sys.exit(0)
    402          gmPatSearchWidgets.set_active_patient(patient=pat)
    403
    404  #       try:
    405                  # lauch emr dialogs test application
    406  #               app = testapp(0)
    407  #               app.MainLoop()
    408  #       except Exception:
    409  #               _log.exception("unhandled exception caught !")
    410                  # but re-raise them
    411  #               raise
    412
    413          #----------------------------------------------------------------
    414 -        def test_hospital_stay_prw():
    415                  app = wx.PyWidgetTester(size = (400, 40))
    416                  app.SetWidget(cHospitalStayPhraseWheel, id=-1, size=(180,20), pos=(10,20))
    417                  app.MainLoop()
    418
    419          test_hospital_stay_prw()
    420