Gnumed.business.gmAutoHints

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

# Source Code for Module Gnumed.business.gmAutoHints

      1  # -*- coding: utf-8 -*-
      2  """GNUmed auto hints 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  import logging
     13
     14
     15  if __name__ == '__main__':
     16          sys.path.insert(0, '../../')
     17  from Gnumed.pycommon import gmPG2
     18  from Gnumed.pycommon import gmBusinessDBObject
     19  from Gnumed.pycommon import gmTools
     20  from Gnumed.pycommon import gmDateTime
     21
     22  from Gnumed.business import gmStaff
     23
     24  _log = logging.getLogger('gm.hints')
     25
     26  #============================================================
     27  # dynamic hints API
     28  #------------------------------------------------------------
     29  _SQL_get_dynamic_hints = "SELECT * FROM ref.v_auto_hints WHERE %s"
     30
     31 -class cDynamicHint(gmBusinessDBObject.cBusinessDBObject):
     32          """Represents dynamic hints to be run against the database."""
     33
     34          _cmd_fetch_payload = _SQL_get_dynamic_hints % "pk_auto_hint = %s"
     35          _cmds_store_payload = [
     36                  """UPDATE ref.auto_hint SET
     37                                  query = gm.nullify_empty_string(%(query)s),
     38                                  recommendation_query = gm.nullify_empty_string(%(recommendation_query)s),
     39                                  title = gm.nullify_empty_string(%(title)s),
     40                                  hint = gm.nullify_empty_string(%(hint)s),
     41                                  url = gm.nullify_empty_string(%(url)s),
     42                                  source = gm.nullify_empty_string(%(source)s),
     43                                  is_active = %(is_active)s,
     44                                  popup_type = %(popup_type)s,
     45                                  highlight_as_priority = %(highlight_as_priority)s
     46                          WHERE
     47                                  pk = %(pk_auto_hint)s
     48                                          AND
     49                                  xmin = %(xmin_auto_hint)s
     50                          RETURNING
     51                                  xmin AS xmin_auto_hint
     52                  """
     53          ]
     54          _updatable_fields = [
     55                  'query',
     56                  'recommendation_query',
     57                  'title',
     58                  'hint',
     59                  'url',
     60                  'source',
     61                  'is_active',
     62                  'popup_type',
     63                  'highlight_as_priority'
     64          ]
     65          #--------------------------------------------------------
     66 -        def format_maximum_information(self, patient):
     67                  return self.format(include_sql = True).split('\n')
     68
     69          #--------------------------------------------------------
     70 -        def format(self, include_sql=False):
     71                  txt = '%s               [#%s]\n' % (
     72                          gmTools.bool2subst(self._payload[self._idx['is_active']], _('Active clinical hint'), _('Inactive clinical hint')),
     73                          self._payload[self._idx['pk_auto_hint']]
     74                  )
     75                  txt += '\n'
     76                  txt += self._payload[self._idx['title']]
     77                  txt += '\n'
     78                  txt += '\n'
     79                  txt += _('Source: %s\n') % self._payload[self._idx['source']]
     80                  txt += _('Language: %s\n') % self._payload[self._idx['lang']]
     81                  txt += '\n'
     82                  txt += gmTools.wrap(self._payload[self._idx['hint']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
     83                  txt += '\n'
     84                  txt += '\n'
     85                  if self._payload[self._idx['recommendation']] is not None:
     86                          txt += gmTools.wrap(self._payload[self._idx['recommendation']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
     87                          txt += '\n'
     88                          txt += '\n'
     89                  txt += gmTools.wrap (
     90                          gmTools.coalesce(self._payload[self._idx['url']], ''),
     91                          width = 50,
     92                          initial_indent = ' ',
     93                          subsequent_indent = ' '
     94                  )
     95                  txt += '\n'
     96                  if include_sql:
     97                          txt += '\n'
     98                          txt += gmTools.wrap(self._payload[self._idx['query']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
     99                          txt += '\n'
    100                          if self._payload[self._idx['recommendation_query']] is not None:
    101                                  txt += '\n'
    102                                  txt += gmTools.wrap(self._payload[self._idx['recommendation_query']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
    103                                  txt += '\n'
    104                  if self._payload[self._idx['rationale4suppression']] is not None:
    105                          txt += '\n'
    106                          txt += _('Rationale for suppression:')
    107                          txt += '\n'
    108                          txt += gmTools.wrap(self._payload[self._idx['rationale4suppression']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
    109                          txt += '\n'
    110                  return txt
    111
    112          #--------------------------------------------------------
    113 -        def suppress(self, rationale=None, pk_encounter=None):
    114                  return suppress_dynamic_hint (
    115                          pk_hint = self._payload[self._idx['pk_auto_hint']],
    116                          pk_encounter = pk_encounter,
    117                          rationale = rationale
    118                  )
    119          #--------------------------------------------------------
    120 -        def invalidate_suppression(self, pk_encounter=None):
    121                  return invalidate_hint_suppression (
    122                          pk_hint = self._payload[self._idx['pk_auto_hint']],
    123                          pk_encounter = pk_encounter
    124                  )
    125
    126  #------------------------------------------------------------
    127 -def get_dynamic_hints(order_by=None, link_obj=None):
    128          if order_by is None:
    129                  order_by = 'TRUE'
    130          else:
    131                  order_by = 'TRUE ORDER BY %s' % order_by
    132          cmd = _SQL_get_dynamic_hints % order_by
    133          rows, idx = gmPG2.run_ro_queries(link_obj = link_obj, queries = [{'cmd': cmd}], get_col_idx = True)
    134          return [ cDynamicHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk_auto_hint'}) for r in rows ]
    135
    136  #------------------------------------------------------------
    137 -def create_dynamic_hint(link_obj=None, query=None, title=None, hint=None, source=None):
    138          args = {
    139                  'query': query,
    140                  'title': title,
    141                  'hint': hint,
    142                  'source': source,
    143                  'usr': gmStaff.gmCurrentProvider()['db_user']
    144          }
    145          cmd = """
    146                  INSERT INTO ref.auto_hint (
    147                          query,
    148                          title,
    149                          hint,
    150                          source,
    151                          lang
    152                  ) VALUES (
    153                          gm.nullify_empty_string(%(query)s),
    154                          gm.nullify_empty_string(%(title)s),
    155                          gm.nullify_empty_string(%(hint)s),
    156                          gm.nullify_empty_string(%(source)s),
    157                          i18n.get_curr_lang(%(usr)s)
    158                  )
    159                  RETURNING pk
    160          """
    161          rows, idx = gmPG2.run_rw_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = True)
    162          return cDynamicHint(aPK_obj = rows[0]['pk'], link_obj = link_obj)
    163
    164  #------------------------------------------------------------
    165 -def delete_dynamic_hint(link_obj=None, pk_hint=None):
    166          args = {'pk': pk_hint}
    167          cmd = "DELETE FROM ref.auto_hint WHERE pk = %(pk)s"
    168          gmPG2.run_rw_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}])
    169          return True
    170
    171  #------------------------------------------------------------
    172 -def get_hints_for_patient(pk_identity=None, pk_encounter=None):
    173          conn = gmPG2.get_connection()
    174          curs = conn.cursor()
    175          curs.callproc('clin.get_hints_for_patient', [pk_identity])
    176          rows = curs.fetchall()
    177          idx = gmPG2.get_col_indices(curs)
    178          curs.close()
    179          conn.rollback()
    180
    181          applying_rows = []
    182          for row in rows:
    183                  if row['rationale4suppression'] is None:
    184                          applying_rows.append(row)
    185                          continue
    186                  if row['rationale4suppression'].startswith('magic_tag::'):
    187                          _log.debug('hint with magic tag: %s', row['rationale4suppression'])
    188                          if 'suppression_needs_invalidation' in row['rationale4suppression']:
    189                                  _log.debug('database asks for invalidation of suppression of hint [%s]', row)
    190                                  if pk_encounter is not None:
    191                                          invalidate_hint_suppression(pk_hint = row['pk_auto_hint'], pk_encounter = pk_encounter)
    192                          if 'does_not_apply' in row['rationale4suppression']:
    193                                  continue
    194                          # we would need to reload the relevant hint at this time,
    195                          # however currently, only hints which do not apply ask
    196                          # for invalidation of suppression
    197                  applying_rows.append(row)
    198
    199          return [ cDynamicHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk_auto_hint'}) for r in applying_rows ]
    200
    201  #------------------------------------------------------------
    202 -def suppress_dynamic_hint(pk_hint=None, rationale=None, pk_encounter=None):
    203          args = {
    204                  'hint': pk_hint,
    205                  'rationale': rationale,
    206                  'enc': pk_encounter
    207          }
    208          cmd = """
    209                  DELETE FROM clin.suppressed_hint
    210                  WHERE
    211                          fk_hint = %(hint)s
    212                                  AND
    213                          fk_encounter IN (
    214                                  SELECT pk FROM clin.encounter WHERE fk_patient = (
    215                                          SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
    216                                  )
    217                          )
    218          """
    219          queries = [{'cmd': cmd, 'args': args}]
    220          cmd = """
    221                  INSERT INTO clin.suppressed_hint (
    222                          fk_encounter,
    223                          fk_hint,
    224                          rationale,
    225                          md5_sum
    226                  ) VALUES (
    227                          %(enc)s,
    228                          %(hint)s,
    229                          %(rationale)s,
    230                          (SELECT r_vah.md5_sum FROM ref.v_auto_hints r_vah WHERE r_vah.pk_auto_hint = %(hint)s)
    231                  )
    232          """
    233          queries.append({'cmd': cmd, 'args': args})
    234          gmPG2.run_rw_queries(queries = queries)
    235          return True
    236
    237  #------------------------------------------------------------
    238  # suppressed dynamic hints
    239  #------------------------------------------------------------
    240  _SQL_get_suppressed_hints = "SELECT * FROM clin.v_suppressed_hints WHERE %s"
    241
    242 -class cSuppressedHint(gmBusinessDBObject.cBusinessDBObject):
    243          """Represents suppressed dynamic hints per patient."""
    244
    245          _cmd_fetch_payload = _SQL_get_suppressed_hints % "pk_suppressed_hint = %s"
    246          _cmds_store_payload = []
    247          _updatable_fields = []
    248          #--------------------------------------------------------
    249 -        def format(self):
    250                  txt = '%s               [#%s]\n' % (
    251                          gmTools.bool2subst(self._payload[self._idx['is_active']], _('Suppressed active dynamic hint'), _('Suppressed inactive dynamic hint')),
    252                          self._payload[self._idx['pk_suppressed_hint']]
    253                  )
    254                  txt += '\n'
    255                  txt += '%s\n\n' % self._payload[self._idx['title']]
    256                  txt += _('Suppressed by: %s\n') % self._payload[self._idx['suppressed_by']]
    257                  txt += _('Suppressed at: %s\n') % gmDateTime.pydt_strftime(self._payload[self._idx['suppressed_when']], '%Y %b %d')
    258                  txt += _('Hint #: %s\n') % self._payload[self._idx['pk_hint']]
    259                  txt += _('Patient #: %s\n') % self._payload[self._idx['pk_identity']]
    260                  txt += _('MD5 (currently): %s\n') % self._payload[self._idx['md5_hint']]
    261                  txt += _('MD5 (at suppression): %s\n') % self._payload[self._idx['md5_suppressed']]
    262                  txt += _('Source: %s\n') % self._payload[self._idx['source']]
    263                  txt += _('Language: %s\n') % self._payload[self._idx['lang']]
    264                  txt += '\n'
    265                  txt += '%s\n' % gmTools.wrap(self._payload[self._idx['hint']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
    266                  txt += '\n'
    267                  if self._payload[self._idx['recommendation']] is not None:
    268                          txt += '\n'
    269                          txt += '%s\n' % gmTools.wrap(self._payload[self._idx['recommendation']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
    270                          txt += '\n'
    271                  txt += '%s\n' % gmTools.wrap (
    272                          gmTools.coalesce(self._payload[self._idx['url']], ''),
    273                          width = 50,
    274                          initial_indent = ' ',
    275                          subsequent_indent = ' '
    276                  )
    277                  txt += '\n'
    278                  txt += '%s\n' % gmTools.wrap(self._payload[self._idx['query']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
    279                  return txt
    280
    281  #------------------------------------------------------------
    282 -def get_suppressed_hints(pk_identity=None, order_by=None):
    283          args = {'pat': pk_identity}
    284          if pk_identity is None:
    285                  where = 'true'
    286          else:
    287                  where = "pk_identity = %(pat)s"
    288          if order_by is None:
    289                  order_by = ''
    290          else:
    291                  order_by = ' ORDER BY %s' % order_by
    292          cmd = (_SQL_get_suppressed_hints % where) + order_by
    293          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
    294          return [ cSuppressedHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk_suppressed_hint'}) for r in rows ]
    295
    296  #------------------------------------------------------------
    297 -def delete_suppressed_hint(pk_suppressed_hint=None):
    298          args = {'pk': pk_suppressed_hint}
    299          cmd = "DELETE FROM clin.suppressed_hint WHERE pk = %(pk)s"
    300          gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
    301          return True
    302
    303  #------------------------------------------------------------
    304 -def invalidate_hint_suppression(pk_hint=None, pk_encounter=None):
    305          _log.debug('invalidating suppression of hint #%s', pk_hint)
    306          args = {
    307                  'pk_hint': pk_hint,
    308                  'enc': pk_encounter,
    309                  'fake_md5': '***INVALIDATED***'                 # only needs to NOT match ANY md5 sum
    310          }
    311          cmd = """
    312                  UPDATE clin.suppressed_hint SET
    313                          fk_encounter = %(enc)s,
    314                          md5_sum = %(fake_md5)s
    315                  WHERE
    316                          pk = (
    317                                  SELECT pk_suppressed_hint
    318                                  FROM clin.v_suppressed_hints
    319                                  WHERE
    320                                          pk_hint = %(pk_hint)s
    321                                                  AND
    322                                          pk_identity = (
    323                                                  SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
    324                                          )
    325                          )
    326          """
    327          gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
    328          return True
    329
    330  #============================================================
    331  if __name__ == '__main__':
    332
    333          if len(sys.argv) < 2:
    334                  sys.exit()
    335
    336          if sys.argv[1] != 'test':
    337                  sys.exit()
    338
    339          from Gnumed.pycommon import gmI18N
    340
    341          gmI18N.activate_locale()
    342          gmI18N.install_domain()
    343
    344          #---------------------------------------
    345 -        def test_auto_hints():
    346  #               for row in get_dynamic_hints():
    347  #                       print row
    348                  for row in get_hints_for_patient(pk_identity = 12):
    349                          print(row)
    350          #---------------------------------------
    351          test_auto_hints()
    352