Package Gnumed :: Package business :: Module gmProviderInbox |
[frames] | no frames]

# Source Code for Module Gnumed.business.gmProviderInbox

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