Gnumed.business.gmAllergy API documentation
Description: GNUmed allergy related business object.

# Module `Gnumed.business.gmAllergy`

GNUmed allergy related business object.

Expand source code

    # -*- coding: utf-8 -*-
    """GNUmed allergy related business object."""
    #============================================================
    __author__ = "Carlos Moro <cfmoro1976@yahoo.es>"
    __license__ = "GPL v2 or later"

    import sys
    import logging
    import datetime as pyDT

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

    _log = logging.getLogger('gm.domain')
    #============================================================
    # allergy state related code
    #============================================================
    allergy_states = [
            None,           # unknown
            0,                      # no allergies
            1                       # some allergies
    ]

    #------------------------------------------------------------
    class cAllergyState(gmBusinessDBObject.cBusinessDBObject):
            """Represents the allergy state of one patient."""

            _cmd_fetch_payload = "select * from clin.v_pat_allergy_state where pk_allergy_state = %s"
            _cmds_store_payload = [
                    """update clin.allergy_state set
                                    last_confirmed = %(last_confirmed)s,
                                    has_allergy = %(has_allergy)s,
                                    comment = gm.nullify_empty_string(%(comment)s)
                            where
                                    pk = %(pk_allergy_state)s and
                                    xmin = %(xmin_allergy_state)s""",
                    """select xmin_allergy_state from clin.v_pat_allergy_state where pk_allergy_state = %(pk_allergy_state)s"""
            ]
            _updatable_fields = [
                    'last_confirmed',               # special value u'now' will set to datetime.datetime.now() in the local time zone
                    'has_allergy',                  # verified against allergy_states (see above)
                    'comment'                               # u'' maps to None / NULL
            ]

            #--------------------------------------------------------
            def format_maximum_information(self, patient=None):
                    lines = []
                    lines.append('%s (%s)' % (
                            self.state_string,
                            gmDateTime.pydt_strftime(self['last_confirmed'], '%Y %b %d', none_str = '?')
                    ))
                    if self._payload['comment']:
                            lines.append(' %s' % self._payload['comment'])
                    return lines

            #--------------------------------------------------------
            # properties
            #--------------------------------------------------------
            def _get_as_string(self):
                    if self._payload['has_allergy'] is None:
                            return _('unknown allergy state')
                    if self._payload['has_allergy'] == 0:
                            return _('no known allergies')
                    if self._payload['has_allergy'] == 1:
                            return _('*does* have allergies')
                    _log.error('unknown allergy state [%s]', self._payload['has_allergy'])
                    return _('ERROR: unknown allergy state [%s]') % self._payload['has_allergy']

            state_string = property(_get_as_string)

            #--------------------------------------------------------
            def _get_as_symbol(self):
                    if self._payload['has_allergy'] is None:
                            if self._payload['comment'] is None:
                                    return '?'
                            else:
                                    return '?!'

                    if self._payload['has_allergy'] == 0:
                            if self._payload['comment'] is None:
                                    return '\u2300'
                            else:
                                    return '\u2300!'

                    if self._payload['has_allergy'] == 1:
                            return '!'

                    _log.error('unknown allergy state [%s]', self._payload['has_allergy'])
                    return _('ERROR: unknown allergy state [%s]') % self._payload['has_allergy']

            state_symbol = property(_get_as_symbol)

            #--------------------------------------------------------
            def _get_as_amts_latex(self, strict=True):
                    table_rows = []
                    # Trennzeile als leere Zeile für bessere Lesbarkeit
                    table_rows.append('\\multicolumn{11}{l}{}\\tabularnewline')
                    # Zwischenüberschrift: 31 Zeichen, $..., 14pt, no frame, \textwidth
                    state = '%s (%s)' % (
                            self.state_string,
                            gmDateTime.pydt_strftime(self['last_confirmed'], '%b %Y', none_str = '?')
                    )
                    if strict:
                            state = state[:31]
                    table_rows.append('\\multicolumn{11}{>{\\RaggedRight}p{27.9cm}}{\\rule{0pt}{4.5mm} \\fontsize{14pt}{16pt}\selectfont %s\label{AnchorAllergieDetails}}\\tabularnewline' % gmTools.tex_escape_string(state))
                    # Freitextzeile: 200 Zeichen, @..., \textwidth
                    if self['comment'] is not None:
                            if strict:
                                    cmt = self['comment'].strip()[:200]
                            else:
                                    cmt = self['comment'].strip()
                            table_rows.append('\\multicolumn{11}{>{\\RaggedRight}p{27.9cm}}{%s}\\tabularnewline') % gmTools.tex_escape_string(cmt)
                    return table_rows

            as_amts_latex = property(_get_as_amts_latex)

            #--------------------------------------------------------
            def _get_as_amts_data_v_2_0(self, strict=True):
                    lines = []
                    # Trennzeile für bessere Lesbarkeit als leere Zwischenüberschrift
                    lines.append('$ ')
                    # Zwischenüberschrift: 31 Zeichen, $..., \textwidth
                    txt = '$%s (%s)' % (
                            self.state_string,
                            gmDateTime.pydt_strftime(self['last_confirmed'], '%b %Y', none_str = '?')
                    )
                    if strict:
                            lines.append(txt[:32])
                    else:
                            lines.append(txt)
                    # Freitextzeile: 200 Zeichen, @..., \textwidth
                    if self['comment']:
                            if strict:
                                    lines.append('@%s' % self['comment'][:200])
                            else:
                                    lines.append('@%s' % self['comment'])
                    return lines

            #--------------------------------------------------------
            def _get_as_amts_data(self, strict=True):
                    # Zwischenüberschrift
                    state = '%s (%s)' % (self.state_string, gmDateTime.pydt_strftime(self['last_confirmed'], '%b %Y', none_str = '?'))
                    if strict:
                            state = state[:32]
                    # Freitextzeile
                    if self['comment'] is None:
                            comment = ''
                    else:
                            comment = '<X t="%s"/>' % self['comment']
                            if strict:
                                    comment = '<X t="%s"/>' % self['comment'][:200]
                    return '<S t="%s">%s%%s</S>' % (state, comment)

            as_amts_data = property(_get_as_amts_data)

            #--------------------------------------------------------
            def __setitem__(self, attribute, value):
                    if attribute == 'comment':
                            if value is not None:
                                    if value.strip() == '':
                                            value = None

                    elif attribute == 'last_confirmed':
                            if value == 'now':
                                    value = pyDT.datetime.now(tz = gmDateTime.gmCurrentLocalTimezone)

                    elif attribute == 'has_allergy':
                            if value not in allergy_states:
                                    raise ValueError('invalid allergy state [%s]' % value)

                    gmBusinessDBObject.cBusinessDBObject.__setitem__(self, attribute, value)

    #------------------------------------------------------------
    def ensure_has_allergy_state(encounter=None) -> cAllergyState:
            _log.debug('checking allergy state for identity of encounter [%s]', encounter)
            args = {'enc': encounter}
            SQL_create = """
                    INSERT INTO clin.allergy_state (
                            fk_encounter,
                            has_allergy
                    )       SELECT
                                    %(enc)s,
                                    NULL
                            WHERE NOT EXISTS (
                                    SELECT 1 FROM clin.v_pat_allergy_state
                                    WHERE pk_patient = (
                                            SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
                                    )
                            )
            """
            SQL_search = """
                    SELECT pk_allergy_state FROM clin.v_pat_allergy_state
                    WHERE pk_patient = (
                            SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
                    )
            """
            rows, idx = gmPG2.run_rw_queries (
                    queries = [
                            {'cmd': SQL_create, 'args': args},
                            {'cmd': SQL_search, 'args': args}
                    ],
                    return_data = True
            )
            return cAllergyState(aPK_obj = rows[0][0])

    #============================================================
    class cAllergy(gmBusinessDBObject.cBusinessDBObject):
            """Represents one allergy item.

            Actually, those things are really things to "avoid".
            Allergy is just one of several reasons for that.
            See Adrian's post on gm-dev.

            Another word might be Therapeutic Precautions.
            """
            _cmd_fetch_payload = "SELECT * FROM clin.v_pat_allergies WHERE pk_allergy = %s"
            _cmds_store_payload = [
                    """UPDATE clin.allergy SET
                                    clin_when = %(date)s,
                                    substance = %(substance)s,
                                    substance_code = %(substance_code)s,
                                    generics = %(generics)s,
                                    allergene = %(allergene)s,
                                    atc_code = %(atc_code)s,
                                    fk_type = %(pk_type)s,
                                    generic_specific = %(generic_specific)s::boolean,
                                    definite = %(definite)s::boolean,
                                    narrative = %(reaction)s
                            WHERE
                                    pk = %(pk_allergy)s AND
                                    xmin = %(xmin_allergy)s""",
                    """SELECT xmin_allergy FROM clin.v_pat_allergies WHERE pk_allergy=%(pk_allergy)s"""
            ]
            _updatable_fields = [
                    'date',
                    'substance',
                    'substance_code',
                    'generics',
                    'allergene',
                    'atc_code',
                    'pk_type',
                    'generic_specific',
                    'definite',
                    'reaction'
            ]
            #--------------------------------------------------------
            def format_maximum_information(self, patient=None):
                    lines = []
                    lines.append('%s%s: %s     [#%s]' % (
                            self._payload['l10n_type'],
                            gmTools.bool2subst (
                                    self._payload['definite'],
                                    ' (%s)' % _('definite'),
                                    ' (%s)' % _('indefinite'),
                                    ''
                            ),
                            self._payload['descriptor'],
                            self._payload['pk_allergy']
                    ))
                    if self._payload['reaction'] is not None:
                            lines.append(' ' + _('Reaction:') + ' ' + self._payload['reaction'])
                    if self._payload['date'] is not None:
                            lines.append(' ' + _('Noted:') + ' ' + gmDateTime.pydt_strftime(self._payload['date'], '%Y %b %d'))
                    if self._payload['allergene'] is not None:
                            lines.append(' ' + _('Allergene:') + ' ' + self._payload['allergene'])
                    if self._payload['substance'] is not None:
                            lines.append(' ' + _('Substance:') + ' ' + self._payload['substance'])
                    if self._payload['substance_code'] is not None:
                            lines.append(' ' + _('Code:') + ' ' + self._payload['substance_code'])
                    if self._payload['atc_code'] is not None:
                            lines.append(' ' + _('ATC:') + ' ' + self._payload['atc_code'])
                    lines.append(' ' + _('Specific to:') + ' ' + gmTools.bool2subst (
                            self._payload['generic_specific'],
                            _('this substance only'),
                            _('drug class'),
                            _('unknown')
                    ))
                    if self._payload['generics']:
                            lines.append(' ' + _('Generics:') + ' ' + self._payload['generics'])
                    return lines

            #--------------------------------------------------------
            def __setitem__(self, attribute, value):
                    if attribute == 'pk_type':
                            if value in ['allergy', 'sensitivity']:
                                    cmd = 'select pk from clin._enum_allergy_type where value=%s'
                                    rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [value]}])
                                    value = rows[0][0]
                    gmBusinessDBObject.cBusinessDBObject.__setitem__(self, attribute, value)

            #--------------------------------------------------------
            def _get_as_amts_latex(self, strict=True):
                    # Freitextzeile: 200 Zeichen, @...
                    cells = ['\\multicolumn{1}{>{\\RaggedRight}p{4cm}}{%s}' % gmTools.tex_escape_string(self['descriptor'])]
                    txt = '%s%s' % (
                            self['l10n_type'],
                            gmTools.coalesce(self['reaction'], '', ': %s')
                    )
                    if strict:
                            txt = txt[:(200-len(self['descriptor']))]
                    cells.append('\\multicolumn{10}{>{\\RaggedRight}p{23.9cm}}{%s}' % gmTools.tex_escape_string(txt))
                    table_row = ' & '.join(cells)
                    table_row += '\\tabularnewline'
                    return table_row

            as_amts_latex = property(_get_as_amts_latex)

            #--------------------------------------------------------
            def _get_as_amts_data_v_2_0(self, strict=True):
                    # Freitextzeile: 200 Zeichen, @..., \textwidth
                    txt = '@%s %s%s' % (
                            self['descriptor'],
                            self['l10n_type'],
                            gmTools.coalesce(self['reaction'], '', ': %s')
                    )
                    if strict:
                            return txt[:200]
                    return txt

            #--------------------------------------------------------
            def _get_as_amts_data(self, strict=True):
                    txt = '%s %s%s' % (
                            self['descriptor'],
                            self['l10n_type'],
                            gmTools.coalesce(self['reaction'], '', ': %s')
                    )
                    if strict:
                            txt = txt[:200]
                    # Freitextzeile: 200 Zeichen
                    return '<X t="%s"/>' % txt

            as_amts_data = property(_get_as_amts_data)

    #============================================================
    # convenience functions
    #------------------------------------------------------------
    def create_allergy(allergene:str=None, allg_type=None, episode_id:int=None, encounter_id:int=None) -> cAllergy:
            """Creates a new allergy clinical item.

            Args:
                    allergene: allergic substance
                    allg_type: allergy or sensitivity, pk or string
                    encounter_id - encounter
                    episode_id - episode

            Returns:
                    The newly created allergy.
            """
            SQL = """
                    SELECT pk_allergy
                    FROM clin.v_pat_allergies
                    WHERE
                            pk_patient = (SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s)
                                    AND
                            allergene = %(allergene)s
            """
            #args = {'enc': encounter_id, 'substance': substance}
            args = {'enc': encounter_id, 'allergene': allergene}
            rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': SQL, 'args': args}])
            if rows:
                    # don't implicitely change existing data, return existing allergy
                    return cAllergy(aPK_obj = rows[0][0])

            # insert new allergy
            queries = []
            if isinstance(allg_type, int):
                    SQL = """
                            insert into clin.allergy (fk_type, fk_encounter, fk_episode, allergene, substance)
                            values (%s, %s, %s, %s, %s)"""
            else:
                    SQL = """
                            insert into clin.allergy (fk_type, fk_encounter, fk_episode,  allergene, substance)
                            values ((select pk from clin._enum_allergy_type where value = %s), %s, %s, %s, %s)"""
            queries.append({'cmd': SQL, 'args': [allg_type, encounter_id, episode_id, allergene, allergene]})
            SQL = "select currval('clin.allergy_id_seq')"
            queries.append({'cmd': SQL})
            rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True)
            allergy = cAllergy(aPK_obj = rows[0][0])
            return allergy

    #============================================================
    # main - unit testing
    #------------------------------------------------------------
    if __name__ == '__main__':

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

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

            allg = cAllergy(aPK_obj=1)
            print(allg)
            fields = allg.get_fields()
            for field in fields:
                    print(field, ':', allg[field])
            print("updatable:", allg.get_updatable_fields())
            enc_id = allg['pk_encounter']
            epi_id = allg['pk_episode']
            allg = create_allergy (
                    allergene = 'test substance',
                    allg_type = 1,
                    episode_id = epi_id,
                    encounter_id = enc_id
            )
            print(allg)
            allg['reaction'] = 'hehehe'
            status, data = allg.save_payload()
            print('status:', status)
            print('data:', data)
            print(allg)

## Functions

`def create_allergy(allergene: str = None, allg_type=None, episode_id: int = None, encounter_id: int = None) ‑> cAllergy`

  Creates a new allergy clinical item.

  ## Args

  `allergene`
    allergic substance
  `allg_type`
    allergy or sensitivity, pk or string

  encounter_id - encounter episode_id - episode

  ## Returns

  The newly created allergy.

  Expand source code

      def create_allergy(allergene:str=None, allg_type=None, episode_id:int=None, encounter_id:int=None) -> cAllergy:
              """Creates a new allergy clinical item.

              Args:
                      allergene: allergic substance
                      allg_type: allergy or sensitivity, pk or string
                      encounter_id - encounter
                      episode_id - episode

              Returns:
                      The newly created allergy.
              """
              SQL = """
                      SELECT pk_allergy
                      FROM clin.v_pat_allergies
                      WHERE
                              pk_patient = (SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s)
                                      AND
                              allergene = %(allergene)s
              """
              #args = {'enc': encounter_id, 'substance': substance}
              args = {'enc': encounter_id, 'allergene': allergene}
              rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': SQL, 'args': args}])
              if rows:
                      # don't implicitely change existing data, return existing allergy
                      return cAllergy(aPK_obj = rows[0][0])

              # insert new allergy
              queries = []
              if isinstance(allg_type, int):
                      SQL = """
                              insert into clin.allergy (fk_type, fk_encounter, fk_episode, allergene, substance)
                              values (%s, %s, %s, %s, %s)"""
              else:
                      SQL = """
                              insert into clin.allergy (fk_type, fk_encounter, fk_episode,  allergene, substance)
                              values ((select pk from clin._enum_allergy_type where value = %s), %s, %s, %s, %s)"""
              queries.append({'cmd': SQL, 'args': [allg_type, encounter_id, episode_id, allergene, allergene]})
              SQL = "select currval('clin.allergy_id_seq')"
              queries.append({'cmd': SQL})
              rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True)
              allergy = cAllergy(aPK_obj = rows[0][0])
              return allergy

`def ensure_has_allergy_state(encounter=None) ‑> cAllergyState`
  Expand source code

      def ensure_has_allergy_state(encounter=None) -> cAllergyState:
              _log.debug('checking allergy state for identity of encounter [%s]', encounter)
              args = {'enc': encounter}
              SQL_create = """
                      INSERT INTO clin.allergy_state (
                              fk_encounter,
                              has_allergy
                      )       SELECT
                                      %(enc)s,
                                      NULL
                              WHERE NOT EXISTS (
                                      SELECT 1 FROM clin.v_pat_allergy_state
                                      WHERE pk_patient = (
                                              SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
                                      )
                              )
              """
              SQL_search = """
                      SELECT pk_allergy_state FROM clin.v_pat_allergy_state
                      WHERE pk_patient = (
                              SELECT fk_patient FROM clin.encounter WHERE pk = %(enc)s
                      )
              """
              rows, idx = gmPG2.run_rw_queries (
                      queries = [
                              {'cmd': SQL_create, 'args': args},
                              {'cmd': SQL_search, 'args': args}
                      ],
                      return_data = True
              )
              return cAllergyState(aPK_obj = rows[0][0])

## Classes

`class cAllergy (aPK_obj: Union[int, dict] = None, row: psycopg2.extras.DictRow = None, link_obj=None)`

  Represents one allergy item.

  Actually, those things are really things to "avoid". Allergy is just one of several reasons for that. See Adrian's post on gm-dev.

  Another word might be Therapeutic Precautions.

  Call init 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
  - for example:

        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 cAllergy(gmBusinessDBObject.cBusinessDBObject):
              """Represents one allergy item.

              Actually, those things are really things to "avoid".
              Allergy is just one of several reasons for that.
              See Adrian's post on gm-dev.

              Another word might be Therapeutic Precautions.
              """
              _cmd_fetch_payload = "SELECT * FROM clin.v_pat_allergies WHERE pk_allergy = %s"
              _cmds_store_payload = [
                      """UPDATE clin.allergy SET
                                      clin_when = %(date)s,
                                      substance = %(substance)s,
                                      substance_code = %(substance_code)s,
                                      generics = %(generics)s,
                                      allergene = %(allergene)s,
                                      atc_code = %(atc_code)s,
                                      fk_type = %(pk_type)s,
                                      generic_specific = %(generic_specific)s::boolean,
                                      definite = %(definite)s::boolean,
                                      narrative = %(reaction)s
                              WHERE
                                      pk = %(pk_allergy)s AND
                                      xmin = %(xmin_allergy)s""",
                      """SELECT xmin_allergy FROM clin.v_pat_allergies WHERE pk_allergy=%(pk_allergy)s"""
              ]
              _updatable_fields = [
                      'date',
                      'substance',
                      'substance_code',
                      'generics',
                      'allergene',
                      'atc_code',
                      'pk_type',
                      'generic_specific',
                      'definite',
                      'reaction'
              ]
              #--------------------------------------------------------
              def format_maximum_information(self, patient=None):
                      lines = []
                      lines.append('%s%s: %s     [#%s]' % (
                              self._payload['l10n_type'],
                              gmTools.bool2subst (
                                      self._payload['definite'],
                                      ' (%s)' % _('definite'),
                                      ' (%s)' % _('indefinite'),
                                      ''
                              ),
                              self._payload['descriptor'],
                              self._payload['pk_allergy']
                      ))
                      if self._payload['reaction'] is not None:
                              lines.append(' ' + _('Reaction:') + ' ' + self._payload['reaction'])
                      if self._payload['date'] is not None:
                              lines.append(' ' + _('Noted:') + ' ' + gmDateTime.pydt_strftime(self._payload['date'], '%Y %b %d'))
                      if self._payload['allergene'] is not None:
                              lines.append(' ' + _('Allergene:') + ' ' + self._payload['allergene'])
                      if self._payload['substance'] is not None:
                              lines.append(' ' + _('Substance:') + ' ' + self._payload['substance'])
                      if self._payload['substance_code'] is not None:
                              lines.append(' ' + _('Code:') + ' ' + self._payload['substance_code'])
                      if self._payload['atc_code'] is not None:
                              lines.append(' ' + _('ATC:') + ' ' + self._payload['atc_code'])
                      lines.append(' ' + _('Specific to:') + ' ' + gmTools.bool2subst (
                              self._payload['generic_specific'],
                              _('this substance only'),
                              _('drug class'),
                              _('unknown')
                      ))
                      if self._payload['generics']:
                              lines.append(' ' + _('Generics:') + ' ' + self._payload['generics'])
                      return lines

              #--------------------------------------------------------
              def __setitem__(self, attribute, value):
                      if attribute == 'pk_type':
                              if value in ['allergy', 'sensitivity']:
                                      cmd = 'select pk from clin._enum_allergy_type where value=%s'
                                      rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [value]}])
                                      value = rows[0][0]
                      gmBusinessDBObject.cBusinessDBObject.__setitem__(self, attribute, value)

              #--------------------------------------------------------
              def _get_as_amts_latex(self, strict=True):
                      # Freitextzeile: 200 Zeichen, @...
                      cells = ['\\multicolumn{1}{>{\\RaggedRight}p{4cm}}{%s}' % gmTools.tex_escape_string(self['descriptor'])]
                      txt = '%s%s' % (
                              self['l10n_type'],
                              gmTools.coalesce(self['reaction'], '', ': %s')
                      )
                      if strict:
                              txt = txt[:(200-len(self['descriptor']))]
                      cells.append('\\multicolumn{10}{>{\\RaggedRight}p{23.9cm}}{%s}' % gmTools.tex_escape_string(txt))
                      table_row = ' & '.join(cells)
                      table_row += '\\tabularnewline'
                      return table_row

              as_amts_latex = property(_get_as_amts_latex)

              #--------------------------------------------------------
              def _get_as_amts_data_v_2_0(self, strict=True):
                      # Freitextzeile: 200 Zeichen, @..., \textwidth
                      txt = '@%s %s%s' % (
                              self['descriptor'],
                              self['l10n_type'],
                              gmTools.coalesce(self['reaction'], '', ': %s')
                      )
                      if strict:
                              return txt[:200]
                      return txt

              #--------------------------------------------------------
              def _get_as_amts_data(self, strict=True):
                      txt = '%s %s%s' % (
                              self['descriptor'],
                              self['l10n_type'],
                              gmTools.coalesce(self['reaction'], '', ': %s')
                      )
                      if strict:
                              txt = txt[:200]
                      # Freitextzeile: 200 Zeichen
                      return '<X t="%s"/>' % txt

              as_amts_data = property(_get_as_amts_data)

  ### Ancestors

  - cBusinessDBObject

  ### Instance variables

  `var as_amts_data`
    Expand source code

        def _get_as_amts_data(self, strict=True):
                txt = '%s %s%s' % (
                        self['descriptor'],
                        self['l10n_type'],
                        gmTools.coalesce(self['reaction'], '', ': %s')
                )
                if strict:
                        txt = txt[:200]
                # Freitextzeile: 200 Zeichen
                return '<X t="%s"/>' % txt

  `var as_amts_latex`
    Expand source code

        def _get_as_amts_latex(self, strict=True):
                # Freitextzeile: 200 Zeichen, @...
                cells = ['\\multicolumn{1}{>{\\RaggedRight}p{4cm}}{%s}' % gmTools.tex_escape_string(self['descriptor'])]
                txt = '%s%s' % (
                        self['l10n_type'],
                        gmTools.coalesce(self['reaction'], '', ': %s')
                )
                if strict:
                        txt = txt[:(200-len(self['descriptor']))]
                cells.append('\\multicolumn{10}{>{\\RaggedRight}p{23.9cm}}{%s}' % gmTools.tex_escape_string(txt))
                table_row = ' & '.join(cells)
                table_row += '\\tabularnewline'
                return table_row

  ### Methods

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

        def format_maximum_information(self, patient=None):
                lines = []
                lines.append('%s%s: %s     [#%s]' % (
                        self._payload['l10n_type'],
                        gmTools.bool2subst (
                                self._payload['definite'],
                                ' (%s)' % _('definite'),
                                ' (%s)' % _('indefinite'),
                                ''
                        ),
                        self._payload['descriptor'],
                        self._payload['pk_allergy']
                ))
                if self._payload['reaction'] is not None:
                        lines.append(' ' + _('Reaction:') + ' ' + self._payload['reaction'])
                if self._payload['date'] is not None:
                        lines.append(' ' + _('Noted:') + ' ' + gmDateTime.pydt_strftime(self._payload['date'], '%Y %b %d'))
                if self._payload['allergene'] is not None:
                        lines.append(' ' + _('Allergene:') + ' ' + self._payload['allergene'])
                if self._payload['substance'] is not None:
                        lines.append(' ' + _('Substance:') + ' ' + self._payload['substance'])
                if self._payload['substance_code'] is not None:
                        lines.append(' ' + _('Code:') + ' ' + self._payload['substance_code'])
                if self._payload['atc_code'] is not None:
                        lines.append(' ' + _('ATC:') + ' ' + self._payload['atc_code'])
                lines.append(' ' + _('Specific to:') + ' ' + gmTools.bool2subst (
                        self._payload['generic_specific'],
                        _('this substance only'),
                        _('drug class'),
                        _('unknown')
                ))
                if self._payload['generics']:
                        lines.append(' ' + _('Generics:') + ' ' + self._payload['generics'])
                return lines

  ### 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 cAllergyState (aPK_obj: Union[int, dict] = None, row: psycopg2.extras.DictRow = None, link_obj=None)`

  Represents the allergy state of one patient.

  Call init 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
  - for example:

        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 cAllergyState(gmBusinessDBObject.cBusinessDBObject):
              """Represents the allergy state of one patient."""

              _cmd_fetch_payload = "select * from clin.v_pat_allergy_state where pk_allergy_state = %s"
              _cmds_store_payload = [
                      """update clin.allergy_state set
                                      last_confirmed = %(last_confirmed)s,
                                      has_allergy = %(has_allergy)s,
                                      comment = gm.nullify_empty_string(%(comment)s)
                              where
                                      pk = %(pk_allergy_state)s and
                                      xmin = %(xmin_allergy_state)s""",
                      """select xmin_allergy_state from clin.v_pat_allergy_state where pk_allergy_state = %(pk_allergy_state)s"""
              ]
              _updatable_fields = [
                      'last_confirmed',               # special value u'now' will set to datetime.datetime.now() in the local time zone
                      'has_allergy',                  # verified against allergy_states (see above)
                      'comment'                               # u'' maps to None / NULL
              ]

              #--------------------------------------------------------
              def format_maximum_information(self, patient=None):
                      lines = []
                      lines.append('%s (%s)' % (
                              self.state_string,
                              gmDateTime.pydt_strftime(self['last_confirmed'], '%Y %b %d', none_str = '?')
                      ))
                      if self._payload['comment']:
                              lines.append(' %s' % self._payload['comment'])
                      return lines

              #--------------------------------------------------------
              # properties
              #--------------------------------------------------------
              def _get_as_string(self):
                      if self._payload['has_allergy'] is None:
                              return _('unknown allergy state')
                      if self._payload['has_allergy'] == 0:
                              return _('no known allergies')
                      if self._payload['has_allergy'] == 1:
                              return _('*does* have allergies')
                      _log.error('unknown allergy state [%s]', self._payload['has_allergy'])
                      return _('ERROR: unknown allergy state [%s]') % self._payload['has_allergy']

              state_string = property(_get_as_string)

              #--------------------------------------------------------
              def _get_as_symbol(self):
                      if self._payload['has_allergy'] is None:
                              if self._payload['comment'] is None:
                                      return '?'
                              else:
                                      return '?!'

                      if self._payload['has_allergy'] == 0:
                              if self._payload['comment'] is None:
                                      return '\u2300'
                              else:
                                      return '\u2300!'

                      if self._payload['has_allergy'] == 1:
                              return '!'

                      _log.error('unknown allergy state [%s]', self._payload['has_allergy'])
                      return _('ERROR: unknown allergy state [%s]') % self._payload['has_allergy']

              state_symbol = property(_get_as_symbol)

              #--------------------------------------------------------
              def _get_as_amts_latex(self, strict=True):
                      table_rows = []
                      # Trennzeile als leere Zeile für bessere Lesbarkeit
                      table_rows.append('\\multicolumn{11}{l}{}\\tabularnewline')
                      # Zwischenüberschrift: 31 Zeichen, $..., 14pt, no frame, \textwidth
                      state = '%s (%s)' % (
                              self.state_string,
                              gmDateTime.pydt_strftime(self['last_confirmed'], '%b %Y', none_str = '?')
                      )
                      if strict:
                              state = state[:31]
                      table_rows.append('\\multicolumn{11}{>{\\RaggedRight}p{27.9cm}}{\\rule{0pt}{4.5mm} \\fontsize{14pt}{16pt}\selectfont %s\label{AnchorAllergieDetails}}\\tabularnewline' % gmTools.tex_escape_string(state))
                      # Freitextzeile: 200 Zeichen, @..., \textwidth
                      if self['comment'] is not None:
                              if strict:
                                      cmt = self['comment'].strip()[:200]
                              else:
                                      cmt = self['comment'].strip()
                              table_rows.append('\\multicolumn{11}{>{\\RaggedRight}p{27.9cm}}{%s}\\tabularnewline') % gmTools.tex_escape_string(cmt)
                      return table_rows

              as_amts_latex = property(_get_as_amts_latex)

              #--------------------------------------------------------
              def _get_as_amts_data_v_2_0(self, strict=True):
                      lines = []
                      # Trennzeile für bessere Lesbarkeit als leere Zwischenüberschrift
                      lines.append('$ ')
                      # Zwischenüberschrift: 31 Zeichen, $..., \textwidth
                      txt = '$%s (%s)' % (
                              self.state_string,
                              gmDateTime.pydt_strftime(self['last_confirmed'], '%b %Y', none_str = '?')
                      )
                      if strict:
                              lines.append(txt[:32])
                      else:
                              lines.append(txt)
                      # Freitextzeile: 200 Zeichen, @..., \textwidth
                      if self['comment']:
                              if strict:
                                      lines.append('@%s' % self['comment'][:200])
                              else:
                                      lines.append('@%s' % self['comment'])
                      return lines

              #--------------------------------------------------------
              def _get_as_amts_data(self, strict=True):
                      # Zwischenüberschrift
                      state = '%s (%s)' % (self.state_string, gmDateTime.pydt_strftime(self['last_confirmed'], '%b %Y', none_str = '?'))
                      if strict:
                              state = state[:32]
                      # Freitextzeile
                      if self['comment'] is None:
                              comment = ''
                      else:
                              comment = '<X t="%s"/>' % self['comment']
                              if strict:
                                      comment = '<X t="%s"/>' % self['comment'][:200]
                      return '<S t="%s">%s%%s</S>' % (state, comment)

              as_amts_data = property(_get_as_amts_data)

              #--------------------------------------------------------
              def __setitem__(self, attribute, value):
                      if attribute == 'comment':
                              if value is not None:
                                      if value.strip() == '':
                                              value = None

                      elif attribute == 'last_confirmed':
                              if value == 'now':
                                      value = pyDT.datetime.now(tz = gmDateTime.gmCurrentLocalTimezone)

                      elif attribute == 'has_allergy':
                              if value not in allergy_states:
                                      raise ValueError('invalid allergy state [%s]' % value)

                      gmBusinessDBObject.cBusinessDBObject.__setitem__(self, attribute, value)

  ### Ancestors

  - cBusinessDBObject

  ### Instance variables

  `var as_amts_data`
    Expand source code

        def _get_as_amts_data(self, strict=True):
                # Zwischenüberschrift
                state = '%s (%s)' % (self.state_string, gmDateTime.pydt_strftime(self['last_confirmed'], '%b %Y', none_str = '?'))
                if strict:
                        state = state[:32]
                # Freitextzeile
                if self['comment'] is None:
                        comment = ''
                else:
                        comment = '<X t="%s"/>' % self['comment']
                        if strict:
                                comment = '<X t="%s"/>' % self['comment'][:200]
                return '<S t="%s">%s%%s</S>' % (state, comment)

  `var as_amts_latex`
    Expand source code

        def _get_as_amts_latex(self, strict=True):
                table_rows = []
                # Trennzeile als leere Zeile für bessere Lesbarkeit
                table_rows.append('\\multicolumn{11}{l}{}\\tabularnewline')
                # Zwischenüberschrift: 31 Zeichen, $..., 14pt, no frame, \textwidth
                state = '%s (%s)' % (
                        self.state_string,
                        gmDateTime.pydt_strftime(self['last_confirmed'], '%b %Y', none_str = '?')
                )
                if strict:
                        state = state[:31]
                table_rows.append('\\multicolumn{11}{>{\\RaggedRight}p{27.9cm}}{\\rule{0pt}{4.5mm} \\fontsize{14pt}{16pt}\selectfont %s\label{AnchorAllergieDetails}}\\tabularnewline' % gmTools.tex_escape_string(state))
                # Freitextzeile: 200 Zeichen, @..., \textwidth
                if self['comment'] is not None:
                        if strict:
                                cmt = self['comment'].strip()[:200]
                        else:
                                cmt = self['comment'].strip()
                        table_rows.append('\\multicolumn{11}{>{\\RaggedRight}p{27.9cm}}{%s}\\tabularnewline') % gmTools.tex_escape_string(cmt)
                return table_rows

  `var state_string`
    Expand source code

        def _get_as_string(self):
                if self._payload['has_allergy'] is None:
                        return _('unknown allergy state')
                if self._payload['has_allergy'] == 0:
                        return _('no known allergies')
                if self._payload['has_allergy'] == 1:
                        return _('*does* have allergies')
                _log.error('unknown allergy state [%s]', self._payload['has_allergy'])
                return _('ERROR: unknown allergy state [%s]') % self._payload['has_allergy']

  `var state_symbol`
    Expand source code

        def _get_as_symbol(self):
                if self._payload['has_allergy'] is None:
                        if self._payload['comment'] is None:
                                return '?'
                        else:
                                return '?!'

                if self._payload['has_allergy'] == 0:
                        if self._payload['comment'] is None:
                                return '\u2300'
                        else:
                                return '\u2300!'

                if self._payload['has_allergy'] == 1:
                        return '!'

                _log.error('unknown allergy state [%s]', self._payload['has_allergy'])
                return _('ERROR: unknown allergy state [%s]') % self._payload['has_allergy']

  ### Methods

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

        def format_maximum_information(self, patient=None):
                lines = []
                lines.append('%s (%s)' % (
                        self.state_string,
                        gmDateTime.pydt_strftime(self['last_confirmed'], '%Y %b %d', none_str = '?')
                ))
                if self._payload['comment']:
                        lines.append(' %s' % self._payload['comment'])
                return lines

  ### 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`