# Module `Gnumed.business.gmAutoHints`

GNUmed auto hints middleware.

This should eventually end up in a class cPractice.

Expand source code

    # -*- coding: utf-8 -*-
    """GNUmed auto hints middleware.

    This should eventually end up in a class cPractice.
    """
    #============================================================
    __license__ = "GPL"
    __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>"

    import sys
    import logging

    if __name__ == '__main__':
            sys.path.insert(0, '../../')
            _ = lambda x:x
    from Gnumed.pycommon import gmPG2
    from Gnumed.pycommon import gmBusinessDBObject
    from Gnumed.pycommon import gmTools
    from Gnumed.pycommon import gmDateTime

    from Gnumed.business import gmStaff

    _log = logging.getLogger('gm.hints')

    #============================================================
    # dynamic hints API
    #------------------------------------------------------------
    _SQL_get_dynamic_hints = "SELECT * FROM ref.v_auto_hints WHERE %s"

    class cDynamicHint(gmBusinessDBObject.cBusinessDBObject):
            """Represents a dynamic hint to be run against the database."""

            _cmd_fetch_payload = _SQL_get_dynamic_hints % "pk_auto_hint = %s"
            _cmds_store_payload = [
                    """UPDATE ref.auto_hint SET
                                    query = gm.nullify_empty_string(%(query)s),
                                    recommendation_query = gm.nullify_empty_string(%(recommendation_query)s),
                                    title = gm.nullify_empty_string(%(title)s),
                                    hint = gm.nullify_empty_string(%(hint)s),
                                    url = gm.nullify_empty_string(%(url)s),
                                    source = gm.nullify_empty_string(%(source)s),
                                    is_active = %(is_active)s,
                                    popup_type = %(popup_type)s,
                                    highlight_as_priority = %(highlight_as_priority)s
                            WHERE
                                    pk = %(pk_auto_hint)s
                                            AND
                                    xmin = %(xmin_auto_hint)s
                            RETURNING
                                    xmin AS xmin_auto_hint
                    """
            ]
            _updatable_fields = [
                    'query',
                    'recommendation_query',
                    'title',
                    'hint',
                    'url',
                    'source',
                    'is_active',
                    'popup_type',
                    'highlight_as_priority'
            ]
            #--------------------------------------------------------
            def format_maximum_information(self, patient):
                    return self.format(include_sql = True).split('\n')

            #--------------------------------------------------------
            def format(self, include_sql=False):
                    txt = '%s               [#%s]\n' % (
                            gmTools.bool2subst(self._payload[self._idx['is_active']], _('Active clinical hint'), _('Inactive clinical hint')),
                            self._payload[self._idx['pk_auto_hint']]
                    )
                    txt += '\n'
                    txt += self._payload[self._idx['title']]
                    txt += '\n'
                    txt += '\n'
                    txt += _('Source: %s\n') % self._payload[self._idx['source']]
                    txt += _('Language: %s\n') % self._payload[self._idx['lang']]
                    txt += '\n'
                    txt += gmTools.wrap(self._payload[self._idx['hint']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                    txt += '\n'
                    txt += '\n'
                    if self._payload[self._idx['recommendation']] is not None:
                            txt += gmTools.wrap(self._payload[self._idx['recommendation']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                            txt += '\n'
                            txt += '\n'
                    txt += gmTools.wrap (
                            gmTools.coalesce(self._payload[self._idx['url']], ''),
                            width = 50,
                            initial_indent = ' ',
                            subsequent_indent = ' '
                    )
                    txt += '\n'
                    if include_sql:
                            txt += '\n'
                            txt += gmTools.wrap(self._payload[self._idx['query']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                            txt += '\n'
                            if self._payload[self._idx['recommendation_query']] is not None:
                                    txt += '\n'
                                    txt += gmTools.wrap(self._payload[self._idx['recommendation_query']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                                    txt += '\n'
                    if self._payload[self._idx['rationale4suppression']] is not None:
                            txt += '\n'
                            txt += _('Rationale for suppression:')
                            txt += '\n'
                            txt += gmTools.wrap(self._payload[self._idx['rationale4suppression']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                            txt += '\n'
                    return txt

            #--------------------------------------------------------
            def suppress(self, rationale=None, pk_encounter=None):
                    return suppress_dynamic_hint (
                            pk_hint = self._payload[self._idx['pk_auto_hint']],
                            pk_encounter = pk_encounter,
                            rationale = rationale
                    )
            #--------------------------------------------------------
            def invalidate_suppression(self, pk_encounter=None):
                    return invalidate_hint_suppression (
                            pk_hint = self._payload[self._idx['pk_auto_hint']],
                            pk_encounter = pk_encounter
                    )

    #------------------------------------------------------------
    def get_dynamic_hints(order_by=None, link_obj=None, return_pks=False):
            if order_by is None:
                    order_by = 'TRUE'
            else:
                    order_by = 'TRUE ORDER BY %s' % order_by
            cmd = _SQL_get_dynamic_hints % order_by
            rows, idx = gmPG2.run_ro_queries(link_obj = link_obj, queries = [{'cmd': cmd}], get_col_idx = True)
            if return_pks:
                    return [ r['pk_auto_hint'] for r in rows ]
            return [ cDynamicHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk_auto_hint'}) for r in rows ]

    #------------------------------------------------------------
    def create_dynamic_hint(link_obj=None, query=None, title=None, hint=None, source=None):
            args = {
                    'query': query,
                    'title': title,
                    'hint': hint,
                    'source': source,
                    'usr': gmStaff.gmCurrentProvider()['db_user']
            }
            cmd = """
                    INSERT INTO ref.auto_hint (
                            query,
                            title,
                            hint,
                            source,
                            lang
                    ) VALUES (
                            gm.nullify_empty_string(%(query)s),
                            gm.nullify_empty_string(%(title)s),
                            gm.nullify_empty_string(%(hint)s),
                            gm.nullify_empty_string(%(source)s),
                            i18n.get_curr_lang(%(usr)s)
                    )
                    RETURNING pk
            """
            rows, idx = gmPG2.run_rw_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = True)
            return cDynamicHint(aPK_obj = rows[0]['pk'], link_obj = link_obj)

    #------------------------------------------------------------
    def delete_dynamic_hint(link_obj=None, pk_hint=None):
            args = {'pk': pk_hint}
            cmd = "DELETE FROM ref.auto_hint WHERE pk = %(pk)s"
            gmPG2.run_rw_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}])
            return True

    #------------------------------------------------------------
    def get_hints_for_patient(pk_identity=None, pk_encounter=None):
            conn = gmPG2.get_connection()
            curs = conn.cursor()
            curs.callproc('clin.get_hints_for_patient', [pk_identity])
            rows = curs.fetchall()
            idx = gmPG2.get_col_indices(curs)
            curs.close()
            conn.rollback()

            applying_rows = []
            for row in rows:
                    if row['rationale4suppression'] is None:
                            applying_rows.append(row)
                            continue
                    if row['rationale4suppression'].startswith('magic_tag::'):
                            _log.debug('hint with magic tag: %s', row['rationale4suppression'])
                            if 'suppression_needs_invalidation' in row['rationale4suppression']:
                                    _log.debug('database asks for invalidation of suppression of hint [%s]', row)
                                    if pk_encounter is not None:
                                            invalidate_hint_suppression(pk_hint = row['pk_auto_hint'], pk_encounter = pk_encounter)
                            if 'does_not_apply' in row['rationale4suppression']:
                                    continue
                            # we would need to reload the relevant hint at this time,
                            # however currently, only hints which do not apply ask
                            # for invalidation of suppression
                    applying_rows.append(row)

            return [ cDynamicHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk_auto_hint'}) for r in applying_rows ]

    #------------------------------------------------------------
    def suppress_dynamic_hint(pk_hint=None, rationale=None, pk_encounter=None):
            args = {
                    'hint': pk_hint,
                    'rationale': rationale,
                    'enc': pk_encounter
            }
            cmd = """
                    DELETE FROM clin.suppressed_hint
                    WHERE
                            fk_hint = %(hint)s
                                    AND
                            fk_encounter IN (
                                    SELECT pk FROM clin.encounter WHERE fk_patient = (
                                            SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
                                    )
                            )
            """
            queries = [{'cmd': cmd, 'args': args}]
            cmd = """
                    INSERT INTO clin.suppressed_hint (
                            fk_encounter,
                            fk_hint,
                            rationale,
                            md5_sum
                    ) VALUES (
                            %(enc)s,
                            %(hint)s,
                            %(rationale)s,
                            (SELECT r_vah.md5_sum FROM ref.v_auto_hints r_vah WHERE r_vah.pk_auto_hint = %(hint)s)
                    )
            """
            queries.append({'cmd': cmd, 'args': args})
            gmPG2.run_rw_queries(queries = queries)
            return True

    #------------------------------------------------------------
    # suppressed dynamic hints
    #------------------------------------------------------------
    _SQL_get_suppressed_hints = "SELECT * FROM clin.v_suppressed_hints WHERE %s"

    class cSuppressedHint(gmBusinessDBObject.cBusinessDBObject):
            """Represents suppressed dynamic hints per patient."""

            _cmd_fetch_payload = _SQL_get_suppressed_hints % "pk_suppressed_hint = %s"
            _cmds_store_payload = []
            _updatable_fields = []
            #--------------------------------------------------------
            def format(self):
                    txt = '%s               [#%s]\n' % (
                            gmTools.bool2subst(self._payload[self._idx['is_active']], _('Suppressed active dynamic hint'), _('Suppressed inactive dynamic hint')),
                            self._payload[self._idx['pk_suppressed_hint']]
                    )
                    txt += '\n'
                    txt += '%s\n\n' % self._payload[self._idx['title']]
                    txt += _('Suppressed by: %s\n') % self._payload[self._idx['suppressed_by']]
                    txt += _('Suppressed at: %s\n') % gmDateTime.pydt_strftime(self._payload[self._idx['suppressed_when']], '%Y %b %d')
                    txt += _('Hint #: %s\n') % self._payload[self._idx['pk_hint']]
                    txt += _('Patient #: %s\n') % self._payload[self._idx['pk_identity']]
                    txt += _('MD5 (currently): %s\n') % self._payload[self._idx['md5_hint']]
                    txt += _('MD5 (at suppression): %s\n') % self._payload[self._idx['md5_suppressed']]
                    txt += _('Source: %s\n') % self._payload[self._idx['source']]
                    txt += _('Language: %s\n') % self._payload[self._idx['lang']]
                    txt += '\n'
                    txt += '%s\n' % gmTools.wrap(self._payload[self._idx['hint']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                    txt += '\n'
                    if self._payload[self._idx['recommendation']] is not None:
                            txt += '\n'
                            txt += '%s\n' % gmTools.wrap(self._payload[self._idx['recommendation']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                            txt += '\n'
                    txt += '%s\n' % gmTools.wrap (
                            gmTools.coalesce(self._payload[self._idx['url']], ''),
                            width = 50,
                            initial_indent = ' ',
                            subsequent_indent = ' '
                    )
                    txt += '\n'
                    txt += '%s\n' % gmTools.wrap(self._payload[self._idx['query']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                    return txt

    #------------------------------------------------------------
    def get_suppressed_hints(pk_identity=None, order_by=None, return_pks=False):
            args = {'pat': pk_identity}
            if pk_identity is None:
                    where = 'true'
            else:
                    where = "pk_identity = %(pat)s"
            if order_by is None:
                    order_by = ''
            else:
                    order_by = ' ORDER BY %s' % order_by
            cmd = (_SQL_get_suppressed_hints % where) + order_by
            rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
            if return_pks:
                    return [ r['pk_suppressed_hint'] for r in rows ]
            return [ cSuppressedHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk_suppressed_hint'}) for r in rows ]

    #------------------------------------------------------------
    def delete_suppressed_hint(pk_suppressed_hint=None):
            args = {'pk': pk_suppressed_hint}
            cmd = "DELETE FROM clin.suppressed_hint WHERE pk = %(pk)s"
            gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
            return True

    #------------------------------------------------------------
    def invalidate_hint_suppression(pk_hint=None, pk_encounter=None):
            _log.debug('invalidating suppression of hint #%s', pk_hint)
            args = {
                    'pk_hint': pk_hint,
                    'enc': pk_encounter,
                    'fake_md5': '***INVALIDATED***'                 # only needs to NOT match ANY md5 sum
            }
            cmd = """
                    UPDATE clin.suppressed_hint SET
                            fk_encounter = %(enc)s,
                            md5_sum = %(fake_md5)s
                    WHERE
                            pk = (
                                    SELECT pk_suppressed_hint
                                    FROM clin.v_suppressed_hints
                                    WHERE
                                            pk_hint = %(pk_hint)s
                                                    AND
                                            pk_identity = (
                                                    SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
                                            )
                            )
            """
            gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
            return True

    #============================================================
    if __name__ == '__main__':

            if len(sys.argv) < 2:
                    sys.exit()

            if sys.argv[1] != 'test':
                    sys.exit()

            from Gnumed.pycommon import gmI18N

            gmI18N.activate_locale()
            gmI18N.install_domain()

            #---------------------------------------
            def test_auto_hints():
    #               for row in get_dynamic_hints():
    #                       print row
                    for row in get_hints_for_patient(pk_identity = 12):
                            print(row)
            #---------------------------------------
            test_auto_hints()

## Functions

`def create_dynamic_hint(link_obj=None, query=None, title=None, hint=None, source=None)`
  Expand source code

      def create_dynamic_hint(link_obj=None, query=None, title=None, hint=None, source=None):
              args = {
                      'query': query,
                      'title': title,
                      'hint': hint,
                      'source': source,
                      'usr': gmStaff.gmCurrentProvider()['db_user']
              }
              cmd = """
                      INSERT INTO ref.auto_hint (
                              query,
                              title,
                              hint,
                              source,
                              lang
                      ) VALUES (
                              gm.nullify_empty_string(%(query)s),
                              gm.nullify_empty_string(%(title)s),
                              gm.nullify_empty_string(%(hint)s),
                              gm.nullify_empty_string(%(source)s),
                              i18n.get_curr_lang(%(usr)s)
                      )
                      RETURNING pk
              """
              rows, idx = gmPG2.run_rw_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = True)
              return cDynamicHint(aPK_obj = rows[0]['pk'], link_obj = link_obj)

`def delete_dynamic_hint(link_obj=None, pk_hint=None)`
  Expand source code

      def delete_dynamic_hint(link_obj=None, pk_hint=None):
              args = {'pk': pk_hint}
              cmd = "DELETE FROM ref.auto_hint WHERE pk = %(pk)s"
              gmPG2.run_rw_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}])
              return True

`def delete_suppressed_hint(pk_suppressed_hint=None)`
  Expand source code

      def delete_suppressed_hint(pk_suppressed_hint=None):
              args = {'pk': pk_suppressed_hint}
              cmd = "DELETE FROM clin.suppressed_hint WHERE pk = %(pk)s"
              gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
              return True

`def get_dynamic_hints(order_by=None, link_obj=None, return_pks=False)`
  Expand source code

      def get_dynamic_hints(order_by=None, link_obj=None, return_pks=False):
              if order_by is None:
                      order_by = 'TRUE'
              else:
                      order_by = 'TRUE ORDER BY %s' % order_by
              cmd = _SQL_get_dynamic_hints % order_by
              rows, idx = gmPG2.run_ro_queries(link_obj = link_obj, queries = [{'cmd': cmd}], get_col_idx = True)
              if return_pks:
                      return [ r['pk_auto_hint'] for r in rows ]
              return [ cDynamicHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk_auto_hint'}) for r in rows ]

`def get_hints_for_patient(pk_identity=None, pk_encounter=None)`
  Expand source code

      def get_hints_for_patient(pk_identity=None, pk_encounter=None):
              conn = gmPG2.get_connection()
              curs = conn.cursor()
              curs.callproc('clin.get_hints_for_patient', [pk_identity])
              rows = curs.fetchall()
              idx = gmPG2.get_col_indices(curs)
              curs.close()
              conn.rollback()

              applying_rows = []
              for row in rows:
                      if row['rationale4suppression'] is None:
                              applying_rows.append(row)
                              continue
                      if row['rationale4suppression'].startswith('magic_tag::'):
                              _log.debug('hint with magic tag: %s', row['rationale4suppression'])
                              if 'suppression_needs_invalidation' in row['rationale4suppression']:
                                      _log.debug('database asks for invalidation of suppression of hint [%s]', row)
                                      if pk_encounter is not None:
                                              invalidate_hint_suppression(pk_hint = row['pk_auto_hint'], pk_encounter = pk_encounter)
                              if 'does_not_apply' in row['rationale4suppression']:
                                      continue
                              # we would need to reload the relevant hint at this time,
                              # however currently, only hints which do not apply ask
                              # for invalidation of suppression
                      applying_rows.append(row)

              return [ cDynamicHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk_auto_hint'}) for r in applying_rows ]

`def get_suppressed_hints(pk_identity=None, order_by=None, return_pks=False)`
  Expand source code

      def get_suppressed_hints(pk_identity=None, order_by=None, return_pks=False):
              args = {'pat': pk_identity}
              if pk_identity is None:
                      where = 'true'
              else:
                      where = "pk_identity = %(pat)s"
              if order_by is None:
                      order_by = ''
              else:
                      order_by = ' ORDER BY %s' % order_by
              cmd = (_SQL_get_suppressed_hints % where) + order_by
              rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
              if return_pks:
                      return [ r['pk_suppressed_hint'] for r in rows ]
              return [ cSuppressedHint(row = {'data': r, 'idx': idx, 'pk_field': 'pk_suppressed_hint'}) for r in rows ]

`def invalidate_hint_suppression(pk_hint=None, pk_encounter=None)`
  Expand source code

      def invalidate_hint_suppression(pk_hint=None, pk_encounter=None):
              _log.debug('invalidating suppression of hint #%s', pk_hint)
              args = {
                      'pk_hint': pk_hint,
                      'enc': pk_encounter,
                      'fake_md5': '***INVALIDATED***'                 # only needs to NOT match ANY md5 sum
              }
              cmd = """
                      UPDATE clin.suppressed_hint SET
                              fk_encounter = %(enc)s,
                              md5_sum = %(fake_md5)s
                      WHERE
                              pk = (
                                      SELECT pk_suppressed_hint
                                      FROM clin.v_suppressed_hints
                                      WHERE
                                              pk_hint = %(pk_hint)s
                                                      AND
                                              pk_identity = (
                                                      SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
                                              )
                              )
              """
              gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
              return True

`def suppress_dynamic_hint(pk_hint=None, rationale=None, pk_encounter=None)`
  Expand source code

      def suppress_dynamic_hint(pk_hint=None, rationale=None, pk_encounter=None):
              args = {
                      'hint': pk_hint,
                      'rationale': rationale,
                      'enc': pk_encounter
              }
              cmd = """
                      DELETE FROM clin.suppressed_hint
                      WHERE
                              fk_hint = %(hint)s
                                      AND
                              fk_encounter IN (
                                      SELECT pk FROM clin.encounter WHERE fk_patient = (
                                              SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
                                      )
                              )
              """
              queries = [{'cmd': cmd, 'args': args}]
              cmd = """
                      INSERT INTO clin.suppressed_hint (
                              fk_encounter,
                              fk_hint,
                              rationale,
                              md5_sum
                      ) VALUES (
                              %(enc)s,
                              %(hint)s,
                              %(rationale)s,
                              (SELECT r_vah.md5_sum FROM ref.v_auto_hints r_vah WHERE r_vah.pk_auto_hint = %(hint)s)
                      )
              """
              queries.append({'cmd': cmd, 'args': args})
              gmPG2.run_rw_queries(queries = queries)
              return True

## Classes

`class cDynamicHint (aPK_obj=None, row: dict = None, link_obj=None)`

  Represents a dynamic hint to be run against the database.

  Init business object.

  Call from child classes like so:

          super().__init__(aPK_obj = aPK_obj, row = row, link_obj = link_obj)

  ## Args

  `aPK_obj`
    retrieve data from backend * a simple value the primary key WHERE condition must be a simple column * a dictionary of values the primary key WHERE condition must be a subselect consuming the dict and producing the single-value primary key
  `row`
    must hold the fields * idx: a dict mapping field names to position * data: the field values in a list (as returned by cursor.fetchone() in the DB-API) * pk_field: the name of the primary key field OR * pk_obj: a dictionary suitable for passed to cursor.execute and holding the primary key values, used for composite PKs

  ## Examples

  row = { 'data': rows[0], 'idx': idx, 'pk_field': 'pk_XXX (the PK column name)', 'pk_obj': {'pk_col1': pk_col1_val, 'pk_col2': pk_col2_val} } rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) objects = [ cChildClass(row = {'data': r, 'idx': idx, 'pk_field': 'the PK column name'}) for r in rows ]

  Expand source code

      class cDynamicHint(gmBusinessDBObject.cBusinessDBObject):
              """Represents a dynamic hint to be run against the database."""

              _cmd_fetch_payload = _SQL_get_dynamic_hints % "pk_auto_hint = %s"
              _cmds_store_payload = [
                      """UPDATE ref.auto_hint SET
                                      query = gm.nullify_empty_string(%(query)s),
                                      recommendation_query = gm.nullify_empty_string(%(recommendation_query)s),
                                      title = gm.nullify_empty_string(%(title)s),
                                      hint = gm.nullify_empty_string(%(hint)s),
                                      url = gm.nullify_empty_string(%(url)s),
                                      source = gm.nullify_empty_string(%(source)s),
                                      is_active = %(is_active)s,
                                      popup_type = %(popup_type)s,
                                      highlight_as_priority = %(highlight_as_priority)s
                              WHERE
                                      pk = %(pk_auto_hint)s
                                              AND
                                      xmin = %(xmin_auto_hint)s
                              RETURNING
                                      xmin AS xmin_auto_hint
                      """
              ]
              _updatable_fields = [
                      'query',
                      'recommendation_query',
                      'title',
                      'hint',
                      'url',
                      'source',
                      'is_active',
                      'popup_type',
                      'highlight_as_priority'
              ]
              #--------------------------------------------------------
              def format_maximum_information(self, patient):
                      return self.format(include_sql = True).split('\n')

              #--------------------------------------------------------
              def format(self, include_sql=False):
                      txt = '%s               [#%s]\n' % (
                              gmTools.bool2subst(self._payload[self._idx['is_active']], _('Active clinical hint'), _('Inactive clinical hint')),
                              self._payload[self._idx['pk_auto_hint']]
                      )
                      txt += '\n'
                      txt += self._payload[self._idx['title']]
                      txt += '\n'
                      txt += '\n'
                      txt += _('Source: %s\n') % self._payload[self._idx['source']]
                      txt += _('Language: %s\n') % self._payload[self._idx['lang']]
                      txt += '\n'
                      txt += gmTools.wrap(self._payload[self._idx['hint']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                      txt += '\n'
                      txt += '\n'
                      if self._payload[self._idx['recommendation']] is not None:
                              txt += gmTools.wrap(self._payload[self._idx['recommendation']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                              txt += '\n'
                              txt += '\n'
                      txt += gmTools.wrap (
                              gmTools.coalesce(self._payload[self._idx['url']], ''),
                              width = 50,
                              initial_indent = ' ',
                              subsequent_indent = ' '
                      )
                      txt += '\n'
                      if include_sql:
                              txt += '\n'
                              txt += gmTools.wrap(self._payload[self._idx['query']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                              txt += '\n'
                              if self._payload[self._idx['recommendation_query']] is not None:
                                      txt += '\n'
                                      txt += gmTools.wrap(self._payload[self._idx['recommendation_query']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                                      txt += '\n'
                      if self._payload[self._idx['rationale4suppression']] is not None:
                              txt += '\n'
                              txt += _('Rationale for suppression:')
                              txt += '\n'
                              txt += gmTools.wrap(self._payload[self._idx['rationale4suppression']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                              txt += '\n'
                      return txt

              #--------------------------------------------------------
              def suppress(self, rationale=None, pk_encounter=None):
                      return suppress_dynamic_hint (
                              pk_hint = self._payload[self._idx['pk_auto_hint']],
                              pk_encounter = pk_encounter,
                              rationale = rationale
                      )
              #--------------------------------------------------------
              def invalidate_suppression(self, pk_encounter=None):
                      return invalidate_hint_suppression (
                              pk_hint = self._payload[self._idx['pk_auto_hint']],
                              pk_encounter = pk_encounter
                      )

  ### Ancestors

  - cBusinessDBObject

  ### Methods

  `def format_maximum_information(self, patient)`
    Expand source code

        def format_maximum_information(self, patient):
                return self.format(include_sql = True).split('\n')

  `def invalidate_suppression(self, pk_encounter=None)`
    Expand source code

        def invalidate_suppression(self, pk_encounter=None):
                return invalidate_hint_suppression (
                        pk_hint = self._payload[self._idx['pk_auto_hint']],
                        pk_encounter = pk_encounter
                )

  `def suppress(self, rationale=None, pk_encounter=None)`
    Expand source code

        def suppress(self, rationale=None, pk_encounter=None):
                return suppress_dynamic_hint (
                        pk_hint = self._payload[self._idx['pk_auto_hint']],
                        pk_encounter = pk_encounter,
                        rationale = rationale
                )

  ### Inherited members

  - `cBusinessDBObject`:
    - `fields_as_dict`
    - `format`
    - `get_fields`
    - `get_patient`
    - `get_updatable_fields`
    - `is_modified`
    - `patient_pk`
    - `refetch_payload`
    - `same_payload`
    - `save`
    - `save_payload`
    - `staff_id`
`class cSuppressedHint (aPK_obj=None, row: dict = None, link_obj=None)`

  Represents suppressed dynamic hints per patient.

  Init business object.

  Call from child classes like so:

          super().__init__(aPK_obj = aPK_obj, row = row, link_obj = link_obj)

  ## Args

  `aPK_obj`
    retrieve data from backend * a simple value the primary key WHERE condition must be a simple column * a dictionary of values the primary key WHERE condition must be a subselect consuming the dict and producing the single-value primary key
  `row`
    must hold the fields * idx: a dict mapping field names to position * data: the field values in a list (as returned by cursor.fetchone() in the DB-API) * pk_field: the name of the primary key field OR * pk_obj: a dictionary suitable for passed to cursor.execute and holding the primary key values, used for composite PKs

  ## Examples

  row = { 'data': rows[0], 'idx': idx, 'pk_field': 'pk_XXX (the PK column name)', 'pk_obj': {'pk_col1': pk_col1_val, 'pk_col2': pk_col2_val} } rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) objects = [ cChildClass(row = {'data': r, 'idx': idx, 'pk_field': 'the PK column name'}) for r in rows ]

  Expand source code

      class cSuppressedHint(gmBusinessDBObject.cBusinessDBObject):
              """Represents suppressed dynamic hints per patient."""

              _cmd_fetch_payload = _SQL_get_suppressed_hints % "pk_suppressed_hint = %s"
              _cmds_store_payload = []
              _updatable_fields = []
              #--------------------------------------------------------
              def format(self):
                      txt = '%s               [#%s]\n' % (
                              gmTools.bool2subst(self._payload[self._idx['is_active']], _('Suppressed active dynamic hint'), _('Suppressed inactive dynamic hint')),
                              self._payload[self._idx['pk_suppressed_hint']]
                      )
                      txt += '\n'
                      txt += '%s\n\n' % self._payload[self._idx['title']]
                      txt += _('Suppressed by: %s\n') % self._payload[self._idx['suppressed_by']]
                      txt += _('Suppressed at: %s\n') % gmDateTime.pydt_strftime(self._payload[self._idx['suppressed_when']], '%Y %b %d')
                      txt += _('Hint #: %s\n') % self._payload[self._idx['pk_hint']]
                      txt += _('Patient #: %s\n') % self._payload[self._idx['pk_identity']]
                      txt += _('MD5 (currently): %s\n') % self._payload[self._idx['md5_hint']]
                      txt += _('MD5 (at suppression): %s\n') % self._payload[self._idx['md5_suppressed']]
                      txt += _('Source: %s\n') % self._payload[self._idx['source']]
                      txt += _('Language: %s\n') % self._payload[self._idx['lang']]
                      txt += '\n'
                      txt += '%s\n' % gmTools.wrap(self._payload[self._idx['hint']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                      txt += '\n'
                      if self._payload[self._idx['recommendation']] is not None:
                              txt += '\n'
                              txt += '%s\n' % gmTools.wrap(self._payload[self._idx['recommendation']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                              txt += '\n'
                      txt += '%s\n' % gmTools.wrap (
                              gmTools.coalesce(self._payload[self._idx['url']], ''),
                              width = 50,
                              initial_indent = ' ',
                              subsequent_indent = ' '
                      )
                      txt += '\n'
                      txt += '%s\n' % gmTools.wrap(self._payload[self._idx['query']], width = 50, initial_indent = ' ', subsequent_indent = ' ')
                      return txt

  ### Ancestors

  - cBusinessDBObject

  ### Inherited members

  - `cBusinessDBObject`:
    - `fields_as_dict`
    - `format`
    - `get_fields`
    - `get_patient`
    - `get_updatable_fields`
    - `is_modified`
    - `patient_pk`
    - `refetch_payload`
    - `same_payload`
    - `save`
    - `save_payload`
    - `staff_id`