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

# Source Code for Module Gnumed.business.gmFamilyHistory

      1  """GNUmed family history handling middleware"""
      2  #============================================================
      3  __license__ = "GPL"
      4  __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>"
      5
      6
      7  # stdlib
      8  import sys, logging
      9
     10
     11  # GNUmed modules
     12  if __name__ == '__main__':
     13          sys.path.insert(0, '../../')
     14  from Gnumed.pycommon import gmPG2
     15  from Gnumed.pycommon import gmBusinessDBObject
     16  from Gnumed.pycommon import gmDateTime
     17  from Gnumed.pycommon import gmTools
     18
     19  from Gnumed.business import gmCoding
     20
     21
     22  _log = logging.getLogger('gm.fhx')
     23
     24  #============================================================
     25  # relationship type handling
     26  #------------------------------------------------------------
     27 -def create_relationship_type(relationship=None, genetic=None):
     28
     29          args = {'rel': relationship, 'gen': genetic}
     30
     31          # already exists ?
     32          cmd = """
     33                  SELECT *, _(description) as l10n_description
     34                  FROM clin.fhx_relation_type
     35                  WHERE
     36                          description = %(rel)s
     37                                  OR
     38                          _(description) = %(rel)s
     39          """
     40          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
     41          if len(rows) > 0:
     42                  return rows[0]
     43
     44          # create it
     45          cmd = """
     46                  INSERT INTO clin.fhx_relation_type (
     47                          description,
     48                          is_genetic
     49                  ) VALUES (
     50                          i18n.i18n(gm.nullify_empty_string(%(rel)s)),
     51                          %(gen)s
     52                  )
     53                  RETURNING *
     54          """
     55          rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
     56          return rows[0]
     57
     58  #============================================================
     59  # Family History item handling
     60  #------------------------------------------------------------
     61  _SQL_get_family_history = "SELECT * from clin.v_family_history WHERE %s"
     62
     63 -class cFamilyHistory(gmBusinessDBObject.cBusinessDBObject):
     64          """Represents a Family History item."""
     65
     66          _cmd_fetch_payload = _SQL_get_family_history % "pk_family_history = %s"
     67          _cmds_store_payload = [
     68                  """
     69                          UPDATE clin.family_history SET
     70                                  narrative = gm.nullify_empty_string(%(condition)s),
     71                                  age_noted = gm.nullify_empty_string(%(age_noted)s),
     72                                  age_of_death = %(age_of_death)s,
     73                                  contributed_to_death = %(contributed_to_death)s,
     74                                  clin_when = %(when_known_to_patient)s,
     75                                  name_relative = gm.nullify_empty_string(%(name_relative)s),
     76                                  dob_relative = %(dob_relative)s,
     77                                  comment = gm.nullify_empty_string(%(comment)s),
     78                                  fk_episode = %(pk_episode)s,
     79                                  fk_relation_type = %(pk_fhx_relation_type)s
     80                          WHERE
     81                                  pk = %(pk_family_history)s
     82                                          AND
     83                                  xmin = %(xmin_family_history)s
     84                          RETURNING
     85                                  pk as pk_family_history,
     86                                  xmin as xmin_family_history
     87                  """
     88          ]
     89          # view columns that can be updated:
     90          _updatable_fields = [
     91                  'condition',
     92                  'age_noted',
     93                  'age_of_death',
     94                  'contributed_to_death',
     95                  'when_known_to_patient',
     96                  'name_relative',
     97                  'dob_relative',
     98                  'pk_encounter',
     99                  'pk_episode',
    100                  'pk_fhx_relation_type',
    101                  'comment'
    102          ]
    103
    104          #--------------------------------------------------------
    105 -        def add_code(self, pk_code=None):
    106                  """<pk_code> must be a value from ref.coding_system_root.pk_coding_system (clin.lnk_code2item_root.fk_generic_code)"""
    107
    108                  if pk_code in self._payload[self._idx['pk_generic_codes']]:
    109                          return
    110
    111                  cmd = """
    112                          INSERT INTO clin.lnk_code2fhx
    113                                  (fk_item, fk_generic_code)
    114                          SELECT
    115                                  %(item)s,
    116                                  %(code)s
    117                          WHERE NOT EXISTS (
    118                                  SELECT 1 FROM clin.lnk_code2fhx
    119                                  WHERE
    120                                          fk_item = %(item)s
    121                                                  AND
    122                                          fk_generic_code = %(code)s
    123                          )"""
    124                  args = {
    125                          'item': self._payload[self._idx['pk_family_history']],
    126                          'code': pk_code
    127                  }
    128                  rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
    129                  return
    130
    131          #--------------------------------------------------------
    132 -        def remove_code(self, pk_code=None):
    133                  """<pk_code> must be a value from ref.coding_system_root.pk_coding_system (clin.lnk_code2item_root.fk_generic_code)"""
    134                  cmd = "DELETE FROM clin.lnk_code2fhx WHERE fk_item = %(item)s AND fk_generic_code = %(code)s"
    135                  args = {
    136                          'item': self._payload[self._idx['pk_family_history']],
    137                          'code': pk_code
    138                  }
    139                  rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
    140                  return True
    141
    142          #--------------------------------------------------------
    143 -        def format_maximum_information(self, patient=None):
    144
    145                  # include more fields from clin.v_family_history
    146
    147                  return self.format (
    148                          include_episode = True,
    149                          include_comment = True,
    150                          include_codes = True
    151                  ).split('\n')
    152
    153          #--------------------------------------------------------
    154 -        def format(self, left_margin=0, include_episode=False, include_comment=False, include_codes=False):
    155
    156                  line = '%s%s' % (
    157                          (' ' * left_margin),
    158                          self._payload[self._idx['l10n_relation']]
    159                  )
    160                  if self._payload[self._idx['age_of_death']] is not None:
    161                          line += ' (%s %s)' % (
    162                                  gmTools.u_latin_cross,
    163                                  gmDateTime.format_interval_medically(self._payload[self._idx['age_of_death']])
    164                          )
    165                  line += ': %s' % self._payload[self._idx['condition']]
    166                  if self._payload[self._idx['age_noted']] is not None:
    167                          line += gmTools.coalesce(self._payload[self._idx['age_noted']], '', ' (@ %s)')
    168                  if self._payload[self._idx['contributed_to_death']]:
    169                          line += ' %s %s' % (
    170                                  gmTools.u_arrow2right,
    171                                  gmTools.u_skull_and_crossbones
    172                          )
    173
    174                  if include_episode:
    175                          line += '\n%s  %s: %s' % (
    176                                  (' ' * left_margin),
    177                                  _('Episode'),
    178                                  self._payload[self._idx['episode']]
    179                          )
    180
    181                  if include_comment:
    182                          if self._payload[self._idx['comment']] is not None:
    183                                  line += '\n%s  %s' % (
    184                                          (' ' * left_margin),
    185                                          self._payload[self._idx['comment']]
    186                                  )
    187
    188                  if include_codes:
    189                          codes = self.generic_codes
    190                          if len(codes) > 0:
    191                                  line += '\n'
    192                          for c in codes:
    193                                  line += '%s  %s: %s (%s - %s)\n' % (
    194                                          (' ' * left_margin),
    195                                          c['code'],
    196                                          c['term'],
    197                                          c['name_short'],
    198                                          c['version']
    199                                  )
    200                          del codes
    201
    202                  return line
    203
    204          #--------------------------------------------------------
    205          # properties
    206          #--------------------------------------------------------
    207 -        def _get_generic_codes(self):
    208                  if len(self._payload[self._idx['pk_generic_codes']]) == 0:
    209                          return []
    210
    211                  cmd = gmCoding._SQL_get_generic_linked_codes % 'pk_generic_code IN %(pks)s'
    212                  args = {'pks': tuple(self._payload[self._idx['pk_generic_codes']])}
    213                  rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
    214                  return [ gmCoding.cGenericLinkedCode(row = {'data': r, 'idx': idx, 'pk_field': 'pk_lnk_code2item'}) for r in rows ]
    215
    216 -        def _set_generic_codes(self, pk_codes):
    217                  queries = []
    218                  # remove all codes
    219                  if len(self._payload[self._idx['pk_generic_codes']]) > 0:
    220                          queries.append ({
    221                                  'cmd': 'DELETE FROM clin.lnk_code2fhx WHERE fk_item = %(fhx)s AND fk_generic_code IN %(codes)s',
    222                                  'args': {
    223                                          'fhx': self._payload[self._idx['pk_family_history']],
    224                                          'codes': tuple(self._payload[self._idx['pk_generic_codes']])
    225                                  }
    226                          })
    227                  # add new codes
    228                  for pk_code in pk_codes:
    229                          queries.append ({
    230                                  'cmd': 'INSERT INTO clin.lnk_code2fhx (fk_item, fk_generic_code) VALUES (%(fhx)s, %(pk_code)s)',
    231                                  'args': {
    232                                          'fhx': self._payload[self._idx['pk_family_history']],
    233                                          'pk_code': pk_code
    234                                  }
    235                          })
    236                  if len(queries) == 0:
    237                          return
    238                  # run it all in one transaction
    239                  rows, idx = gmPG2.run_rw_queries(queries = queries)
    240                  return
    241
    242          generic_codes = property(_get_generic_codes, _set_generic_codes)
    243  #------------------------------------------------------------
    244 -def get_family_history(order_by=None, patient=None):
    245
    246          args = {}
    247          where_parts = []
    248
    249          if patient is not None:
    250                  where_parts.append('pk_patient = %(pat)s')
    251                  args['pat'] = patient
    252
    253          if order_by is None:
    254                  if len(where_parts) == 0:
    255                          order_by = 'true'
    256                  else:
    257                          order_by = ''
    258          else:
    259                  if len(where_parts) == 0:
    260                          order_by = 'true ORDER BY %s' % order_by
    261                  else:
    262                          order_by = 'ORDER BY %s' % order_by
    263
    264          cmd = _SQL_get_family_history % ' AND '.join(where_parts) + ' ' + order_by
    265          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
    266          return [ cFamilyHistory(row = {'data': r, 'idx': idx, 'pk_field': 'pk_family_history'}) for r in rows ]
    267  #------------------------------------------------------------
    268 -def create_family_history(encounter=None, episode=None, condition=None, relation=None):
    269
    270          args = {
    271                  'enc': encounter,
    272                  'epi': episode,
    273                  'cond': condition,
    274                  'rel': relation
    275          }
    276          cmd = """
    277                  INSERT INTO clin.family_history (
    278                          soap_cat,
    279                          fk_encounter,
    280                          fk_episode,
    281                          narrative,
    282                          fk_relation_type
    283                  ) VALUES (
    284                          's'::text,
    285                          %(enc)s,
    286                          %(epi)s,
    287                          gm.nullify_empty_string(%(cond)s),
    288                          %(rel)s
    289                  )
    290                  RETURNING pk
    291          """
    292          rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False)
    293
    294          return cFamilyHistory(aPK_obj = rows[0]['pk'])
    295  #------------------------------------------------------------
    296 -def delete_family_history(pk_family_history=None):
    297          args = {'pk': pk_family_history}
    298          cmd = "DELETE FROM clin.family_history WHERE pk = %(pk)s"
    299          gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
    300          return True
    301  #============================================================
    302  # main
    303  #------------------------------------------------------------
    304  if __name__ == "__main__":
    305
    306          if len(sys.argv) < 2:
    307                  sys.exit()
    308
    309          if sys.argv[1] != 'test':
    310                  sys.exit()
    311
    312          #----------------------------------------------------
    313 -        def test_get_fhx():
    314                  print("family history:")
    315                  for fhx in get_family_history():
    316                          print(fhx)
    317          #----------------------------------------------------
    318          test_get_fhx()
    319
    320  #============================================================
    321