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

# Source Code for Module Gnumed.business.gmDemographicRecord

      1  # -*- coding: utf8 -*-
      2  """GNUmed demographics object.
      3
      4  This is a patient object intended to let a useful client-side
      5  API crystallize from actual use in true XP fashion.
      6
      7  license: GPL v2 or later
      8  """
      9  #============================================================
     10  __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>, I.Haywood <ihaywood@gnu.org>"
     11
     12  # stdlib
     13  import sys
     14  import os
     15  import os.path
     16  import logging
     17
     18
     19  # GNUmed
     20  if __name__ == '__main__':
     21          sys.path.insert(0, '../../')
     22  from Gnumed.pycommon import gmDispatcher
     23  from Gnumed.pycommon import gmBusinessDBObject
     24  from Gnumed.pycommon import gmPG2
     25  from Gnumed.pycommon import gmTools
     26
     27
     28  _log = logging.getLogger('gm.business')
     29
     30  try:
     31          _
     32  except NameError:
     33          _ = lambda x:x
     34
     35  #============================================================
     36  # occupation handling
     37  #------------------------------------------------------------
     38 -def get_occupations(pk_identity=None):
     39          cmd = u"""
     40                  SELECT *
     41                  FROM dem.v_person_jobs
     42                  WHERE pk_identity = %(pk)s
     43                  ORDER BY l10n_occupation
     44          """
     45          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'pk': pk_identity}}])
     46          return rows
     47  #============================================================
     48  # text+image tags
     49  #------------------------------------------------------------
     50  _SQL_get_tag_image = u"SELECT * FROM ref.v_tag_images_no_data WHERE %s"
     51
     52 -class cTagImage(gmBusinessDBObject.cBusinessDBObject):
     53
     54          _cmd_fetch_payload = _SQL_get_tag_image % u"pk_tag_image = %s"
     55          _cmds_store_payload = [
     56                  u"""
     57                          UPDATE ref.tag_image SET
     58                                  description = gm.nullify_empty_string(%(description)s),
     59                                  filename = gm.nullify_empty_string(%(filename)s)
     60                          WHERE
     61                                  pk = %(pk_tag_image)s
     62                                          AND
     63                                  xmin = %(xmin_tag_image)s
     64                          RETURNING
     65                                  pk as pk_tag_image,
     66                                  xmin as xmin_tag_image
     67                  """
     68          ]
     69          _updatable_fields = [u'description', u'filename']
     70          #--------------------------------------------------------
     71 -        def export_image2file(self, aChunkSize=0, filename=None):
     72
     73                  if self._payload[self._idx['size']] == 0:
     74                          return None
     75
     76                  if filename is None:
     77                          suffix = None
     78                          # preserve original filename extension if available
     79                          if self._payload[self._idx['filename']] is not None:
     80                                  name, suffix = os.path.splitext(self._payload[self._idx['filename']])
     81                                  suffix = suffix.strip()
     82                                  if suffix == u'':
     83                                          suffix = None
     84                          # get unique filename
     85                          filename = gmTools.get_unique_filename (
     86                                  prefix = 'gm-tag_image-',
     87                                  suffix = suffix
     88                          )
     89
     90                  success = gmPG2.bytea2file (
     91                          data_query = {
     92                                  'cmd': u'SELECT substring(image from %(start)s for %(size)s) FROM ref.tag_image WHERE pk = %(pk)s',
     93                                  'args': {'pk': self.pk_obj}
     94                          },
     95                          filename = filename,
     96                          chunk_size = aChunkSize,
     97                          data_size = self._payload[self._idx['size']]
     98                  )
     99
    100                  if success:
    101                          return filename
    102
    103                  return None
    104          #--------------------------------------------------------
    105 -        def update_image_from_file(self, filename=None):
    106                  # sanity check
    107                  if not (os.access(filename, os.R_OK) and os.path.isfile(filename)):
    108                          _log.error('[%s] is not a readable file' % filename)
    109                          return False
    110
    111                  gmPG2.file2bytea (
    112                          query = u"UPDATE ref.tag_image SET image = %(data)s::bytea WHERE pk = %(pk)s",
    113                          filename = filename,
    114                          args = {'pk': self.pk_obj}
    115                  )
    116
    117                  # must update XMIN now ...
    118                  self.refetch_payload()
    119                  return True
    120  #------------------------------------------------------------
    121 -def get_tag_images(order_by=None):
    122          if order_by is None:
    123                  order_by = u'true'
    124          else:
    125                  order_by = 'true ORDER BY %s' % order_by
    126
    127          cmd = _SQL_get_tag_image % order_by
    128          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True)
    129          return [ cTagImage(row = {'data': r, 'idx': idx, 'pk_field': 'pk_tag_image'}) for r in rows ]
    130  #------------------------------------------------------------
    131 -def create_tag_image(description=None, link_obj=None):
    132
    133          args = {u'desc': description, u'img': u''}
    134          cmd = u"""
    135                  INSERT INTO ref.tag_image (
    136                          description,
    137                          image
    138                  ) VALUES (
    139                          %(desc)s,
    140                          %(img)s::bytea
    141                  )
    142                  RETURNING pk
    143          """
    144          rows, idx = gmPG2.run_rw_queries (
    145                  link_obj = link_obj,
    146                  queries = [{'cmd': cmd, 'args': args}],
    147                  end_tx = True,
    148                  return_data = True,
    149                  get_col_idx = False
    150          )
    151
    152          return cTagImage(aPK_obj = rows[0]['pk'])
    153  #------------------------------------------------------------
    154 -def delete_tag_image(tag_image=None):
    155          args = {'pk': tag_image}
    156          cmd = u"""
    157                  DELETE FROM ref.tag_image
    158                  WHERE
    159                          pk = %(pk)s
    160                                  AND
    161                          NOT EXISTS (
    162                                  SELECT 1
    163                                  FROM dem.identity_tag
    164                                  WHERE fk_tag = %(pk)s
    165                                  LIMIT 1
    166                          )
    167                  RETURNING 1
    168          """
    169          rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
    170          if len(rows) == 0:
    171                  return False
    172          return True
    173
    174  #============================================================
    175  _SQL_get_identity_tags = u"""SELECT * FROM dem.v_identity_tags WHERE %s"""
    176
    177 -class cIdentityTag(gmBusinessDBObject.cBusinessDBObject):
    178
    179          _cmd_fetch_payload = _SQL_get_identity_tags % u"pk_identity_tag = %s"
    180          _cmds_store_payload = [
    181                  u"""
    182                          UPDATE dem.identity_tag SET
    183                                  fk_tag = %(pk_tag_image)s,
    184                                  comment = gm.nullify_empty_string(%(comment)s)
    185                          WHERE
    186                                  pk = %(pk_identity_tag)s
    187                                          AND
    188                                  xmin = %(xmin_identity_tag)s
    189                          RETURNING
    190                                  pk as pk_identity_tag,
    191                                  xmin as xmin_identity_tag
    192                  """
    193          ]
    194          _updatable_fields = [u'fk_tag', u'comment']
    195          #--------------------------------------------------------
    196 -        def export_image2file(self, aChunkSize=0, filename=None):
    197
    198                  if self._payload[self._idx['image_size']] == 0:
    199                          return None
    200
    201                  if filename is None:
    202                          suffix = None
    203                          # preserve original filename extension if available
    204                          if self._payload[self._idx['filename']] is not None:
    205                                  name, suffix = os.path.splitext(self._payload[self._idx['filename']])
    206                                  suffix = suffix.strip()
    207                                  if suffix == u'':
    208                                          suffix = None
    209                          # get unique filename
    210                          filename = gmTools.get_unique_filename (
    211                                  prefix = 'gm-identity_tag-',
    212                                  suffix = suffix
    213                          )
    214
    215                  exported = gmPG2.bytea2file (
    216                          data_query = {
    217                                  'cmd': u'SELECT substring(image from %(start)s for %(size)s) FROM ref.tag_image WHERE pk = %(pk)s',
    218                                  'args': {'pk': self._payload[self._idx['pk_tag_image']]}
    219                          },
    220                          filename = filename,
    221                          chunk_size = aChunkSize,
    222                          data_size = self._payload[self._idx['image_size']]
    223                  )
    224                  if exported:
    225                          return filename
    226
    227                  return None
    228  #============================================================
    229  #============================================================
    230 -def get_countries():
    231          cmd = u"""
    232                  select
    233                          _(name) as l10n_country, name, code, deprecated
    234                  from dem.country
    235                  order by l10n_country"""
    236          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}])
    237          return rows
    238  #============================================================
    239 -def get_country_for_region(region=None):
    240          cmd = u"""
    241  SELECT code_country, l10n_country FROM dem.v_state WHERE l10n_state = %(region)s
    242          union
    243  SELECT code_country, l10n_country FROM dem.v_state WHERE state = %(region)s
    244  """
    245          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'region': region}}])
    246          return rows
    247  #============================================================
    248 -def delete_province(province=None, delete_urbs=False):
    249
    250          args = {'prov': province}
    251
    252          queries = []
    253          if delete_urbs:
    254                  queries.append ({
    255                          'cmd': u"""
    256                                  delete from dem.urb du
    257                                  where
    258                                          du.id_state = %(prov)s
    259                                                  and
    260                                          not exists (select 1 from dem.street ds where ds.id_urb = du.id)""",
    261                          'args': args
    262                  })
    263
    264          queries.append ({
    265                  'cmd': u"""
    266                          delete from dem.state ds
    267                          where
    268                                  ds.id = %(prov)s
    269                                          and
    270                                  not exists (select 1 from dem.urb du where du.id_state = ds.id)""",
    271                  'args': args
    272          })
    273
    274          gmPG2.run_rw_queries(queries = queries)
    275
    276          return True
    277  #------------------------------------------------------------
    278 -def create_province(name=None, code=None, country=None):
    279
    280          args = {'code': code, 'country': country, 'name': name}
    281
    282          cmd = u"""SELECT EXISTS (SELECT 1 FROM dem.state WHERE name = %(name)s)"""
    283          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
    284
    285          if rows[0][0]:
    286                  return
    287
    288          cmd = u"""
    289                  INSERT INTO dem.state (
    290                          code, country, name
    291                  ) VALUES (
    292                          %(code)s, %(country)s, %(name)s
    293                  )"""
    294          gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
    295  #------------------------------------------------------------
    296 -def get_provinces():
    297          cmd = u"""
    298                  select
    299                          l10n_state, l10n_country, state, code_state, code_country, pk_state, country_deprecated
    300                  from dem.v_state
    301                  order by l10n_country, l10n_state"""
    302          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}])
    303          return rows
    304  #============================================================
    305  # address related classes
    306  #------------------------------------------------------------
    307 -class cAddress(gmBusinessDBObject.cBusinessDBObject):
    308          """A class representing an address as an entity in itself.
    309
    310          We consider addresses to be self-complete "labels" for locations.
    311          It does not depend on any people actually living there. Thus
    312          an address can get attached to as many people as we want to
    313          signify that that is their place of residence/work/...
    314
    315          This class acts on the address as an entity. Therefore it can
    316          modify the address fields. Think carefully about *modifying*
    317          addresses attached to people, though. Most times when you think
    318          person.modify_address() what you *really* want is as sequence of
    319          person.unlink_address(old) and person.link_address(new).
    320
    321          Modifying an address may or may not be the proper thing to do as
    322          it will transparently modify the address for *all* the people to
    323          whom it is attached. In many cases you will want to create a *new*
    324          address and link it to a person instead of the old address.
    325          """
    326          _cmd_fetch_payload = u"select * from dem.v_address where pk_address = %s"
    327          _cmds_store_payload = [
    328                  u"""UPDATE dem.address SET
    329                                  aux_street = %(notes_street)s,
    330                                  subunit = %(subunit)s,
    331                                  addendum = %(notes_subunit)s,
    332                                  lat_lon = %(lat_lon_street)s
    333                          WHERE
    334                                  id = %(pk_address)s
    335                                          AND
    336                                  xmin = %(xmin_address)s
    337                          RETURNING
    338                                  xmin AS xmin_address"""
    339          ]
    340          _updatable_fields = [
    341                  'notes_street',
    342                  'subunit',
    343                  'notes_subunit',
    344                  'lat_lon_address'
    345          ]
    346          #--------------------------------------------------------
    347 -        def format(self, single_line=False, verbose=False, show_type=False):
    348                  if single_line:
    349                          return format_address_single_line(address = self, show_type = False, verbose = verbose)
    350                  return format_address(address = self, show_type = False)
    351  #------------------------------------------------------------
    352 -def address_exists(country=None, state=None, urb=None, postcode=None, street=None, number=None, subunit=None):
    353
    354          cmd = u"""SELECT dem.address_exists(%(country)s, %(state)s, %(urb)s, %(postcode)s, %(street)s, %(number)s, %(subunit)s)"""
    355          args = {
    356                  'country': country,
    357                  'state': state,
    358                  'urb': urb,
    359                  'postcode': postcode,
    360                  'street': street,
    361                  'number': number,
    362                  'subunit': subunit
    363          }
    364
    365          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
    366          if rows[0][0] is None:
    367                  _log.debug('address does not exist')
    368                  for key, val in args.items():
    369                          _log.debug('%s: %s', key, val)
    370                  return None
    371
    372          return rows[0][0]
    373  #------------------------------------------------------------
    374 -def create_address(country=None, state=None, urb=None, suburb=None, postcode=None, street=None, number=None, subunit=None):
    375
    376          if suburb is not None:
    377                  suburb = gmTools.none_if(suburb.strip(), u'')
    378
    379          pk_address = address_exists (
    380                  country = country,
    381                  state = state,
    382                  urb = urb,
    383  #               suburb = suburb,
    384                  postcode = postcode,
    385                  street = street,
    386                  number = number,
    387                  subunit = subunit
    388          )
    389          if pk_address is not None:
    390                  return cAddress(aPK_obj = pk_address)
    391
    392          cmd = u"""
    393  SELECT dem.create_address (
    394          %(number)s,
    395          %(street)s,
    396          %(postcode)s,
    397          %(urb)s,
    398          %(state)s,
    399          %(country)s,
    400          %(subunit)s
    401  )"""
    402          args = {
    403                  'number': number,
    404                  'street': street,
    405                  'postcode': postcode,
    406                  'urb': urb,
    407                  'state': state,
    408                  'country': country,
    409                  'subunit': subunit
    410          }
    411          queries = [{'cmd': cmd, 'args': args}]
    412
    413          rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True)
    414          adr = cAddress(aPK_obj = rows[0][0])
    415
    416          if suburb is not None:
    417                  queries = [{
    418                          # CAVE: suburb will be ignored if there already is one
    419                          'cmd': u"UPDATE dem.street SET suburb = %(suburb)s WHERE id = %(pk_street)s AND suburb IS NULL",
    420                          'args': {'suburb': suburb, 'pk_street': adr['pk_street']}
    421                  }]
    422                  rows, idx = gmPG2.run_rw_queries(queries = queries)
    423
    424          return adr
    425  #------------------------------------------------------------
    426 -def delete_address(pk_address=None):
    427          cmd = u"""
    428                  DELETE FROM dem.address
    429                  WHERE
    430                          id = %(pk)s
    431                                  AND
    432                          NOT EXISTS ((
    433                                  SELECT 1 FROM dem.org_unit WHERE fk_address = %(pk)s LIMIT 1
    434                                          ) UNION (
    435                                  SELECT 1 FROM dem.lnk_identity2comm WHERE fk_address = %(pk)s LIMIT 1
    436                                          ) UNION (
    437                                  SELECT 1 FROM dem.lnk_person_org_address WHERE id_address = %(pk)s LIMIT 1
    438                          ))
    439                  """
    440          rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': pk_address}}])
    441          return True
    442  #------------------------------------------------------------
    443 -def format_address_single_line(address=None, verbose=False, show_type=False):
    444          data = {
    445                  'pk_adr': address['pk_address'],
    446                  'street': address['street'],
    447                  'notes_street': gmTools.coalesce(address['notes_street'], u'', u' (%s)'),
    448                  'number': address['number'],
    449                  'subunit': gmTools.coalesce(address['subunit'], u'', u'/%s'),
    450                  'notes_subunit': gmTools.coalesce(address['notes_subunit'], u'', u' (%s)'),
    451                  'zip': address['postcode'],
    452                  'urb': address['urb'],
    453                  'suburb': gmTools.coalesce(address['suburb'], u'', u' (%s)'),
    454                  'l10n_state': address['l10n_state'],
    455                  'code_state': address['code_state'],
    456                  'l10n_country': address['l10n_country'],
    457                  'code_country': address['code_country']
    458          }
    459          if show_type:
    460                  data['type'] = address['l10n_address_type']
    461
    462          if verbose:
    463                  if show_type:
    464                          template = _('%(type)s: %(street)s %(number)s%(subunit)s, %(zip)s %(urb)s %(suburb)s, %(code_state)s, %(code_country)s')
    465                  else:
    466                          template = _('%(street)s %(number)s%(subunit)s, %(zip)s %(urb)s %(suburb)s, %(code_state)s, %(code_country)s')
    467          else:
    468                  if show_type:
    469                          template = _('%(type)s: %(street)s %(number)s%(subunit)s, %(zip)s %(urb)s, %(code_state)s, %(code_country)s')
    470                  else:
    471                          template = _('%(street)s %(number)s%(subunit)s, %(zip)s %(urb)s, %(code_state)s, %(code_country)s')
    472
    473          return template % data
    474  #------------------------------------------------------------
    475 -def format_address(address=None, show_type=False):
    476          data = {
    477                  'pk_adr': address['pk_address'],
    478                  'street': address['street'],
    479                  'notes_street': gmTools.coalesce(address['notes_street'], u'', u' (%s)'),
    480                  'number': address['number'],
    481                  'subunit': gmTools.coalesce(address['subunit'], u'', u'/%s'),
    482                  'notes_subunit': gmTools.coalesce(address['notes_subunit'], u'', u' (%s)'),
    483                  'zip': address['postcode'],
    484                  'urb': address['urb'],
    485                  'suburb': gmTools.coalesce(address['suburb'], u'', u' (%s)'),
    486                  'l10n_state': address['l10n_state'],
    487                  'code_state': address['code_state'],
    488                  'l10n_country': address['l10n_country'],
    489                  'code_country': address['code_country']
    490          }
    491          if show_type:
    492                  data['type'] = address['l10n_address_type']
    493                  template = _(
    494                          'Address (%(type)s) [#%(pk_adr)s]\n'
    495                          ' Street: %(street)s%(notes_street)s\n'
    496                          ' Number/Unit: %(number)s%(subunit)s%(notes_subunit)s\n'
    497                          ' Location: %(zip)s %(urb)s%(suburb)s\n'
    498                          ' Region: %(l10n_state)s, %(code_state)s\n'
    499                          ' Country: %(l10n_country)s, %(code_country)s'
    500                  )
    501          else:
    502                  template = _(
    503                          'Address [#%(pk_adr)s]\n'
    504                          ' Street: %(street)s%(notes_street)s\n'
    505                          ' Number/Unit: %(number)s%(subunit)s%(notes_subunit)s\n'
    506                          ' Location: %(zip)s %(urb)s%(suburb)s\n'
    507                          ' Region: %(l10n_state)s, %(code_state)s\n'
    508                          ' Country: %(l10n_country)s, %(code_country)s'
    509                  )
    510          txt = template % data
    511          return txt.split('\n')
    512  #------------------------------------------------------------
    513 -def get_address_types(identity=None):
    514          cmd = u'select id as pk, name, _(name) as l10n_name from dem.address_type'
    515          rows, idx = gmPG2.run_rw_queries(queries=[{'cmd': cmd}])
    516          return rows
    517  #------------------------------------------------------------
    518 -def get_addresses(order_by=None):
    519
    520          if order_by is None:
    521                  order_by = u''
    522          else:
    523                  order_by = u'ORDER BY %s' % order_by
    524
    525          cmd = u"SELECT * FROM dem.v_address %s" % order_by
    526          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True)
    527          return [ cAddress(row = {'data': r, 'idx': idx, 'pk_field': u'pk_address'}) for r in rows ]
    528  #------------------------------------------------------------
    529 -def get_address_from_patient_address_pk(pk_patient_address=None):
    530          cmd = u"""
    531                  SELECT * FROM dem.v_address WHERE
    532                          pk_address = (
    533                                  SELECT id_address
    534                                  FROM dem.lnk_person_org_address
    535                                  WHERE id = %(pk_pat_adr)s
    536                          )
    537          """
    538          args = {'pk_pat_adr': pk_patient_address}
    539          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
    540          if len(rows) == 0:
    541                  return None
    542          return cAddress(row = {'data': rows[0], 'idx': idx, 'pk_field': u'pk_address'})
    543
    544  #===================================================================
    545 -def get_patient_address(pk_patient_address=None):
    546          cmd = u'SELECT * FROM dem.v_pat_addresses WHERE pk_lnk_person_org_address = %(pk)s'
    547          args = {'pk': pk_patient_address}
    548          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
    549          if len(rows) == 0:
    550                  return None
    551          return cPatientAddress(row = {'data': rows[0], 'idx': idx, 'pk_field': u'pk_address'})
    552  #-------------------------------------------------------------------
    553 -def get_patient_address_by_type(pk_patient=None, adr_type=None):
    554          cmd = u'SELECT * FROM dem.v_pat_addresses WHERE pk_identity = %(pat)s AND address_type = %(typ)s'
    555          args = {'pat': pk_patient, 'typ': adr_type}
    556          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
    557          if len(rows) == 0:
    558                  return None
    559          return cPatientAddress(row = {'data': rows[0], 'idx': idx, 'pk_field': u'pk_address'})
    560  #-------------------------------------------------------------------
    561 -class cPatientAddress(gmBusinessDBObject.cBusinessDBObject):
    562
    563          _cmd_fetch_payload = u"SELECT * FROM dem.v_pat_addresses WHERE pk_address = %s"
    564          _cmds_store_payload = [
    565                  u"""UPDATE dem.lnk_person_org_address SET
    566                                  id_type = %(pk_address_type)s
    567                          WHERE
    568                                  id = %(pk_lnk_person_org_address)s
    569                                          AND
    570                                  xmin = %(xmin_lnk_person_org_address)s
    571                          RETURNING
    572                                  xmin AS xmin_lnk_person_org_address
    573                  """
    574          ]
    575          _updatable_fields = ['pk_address_type']
    576          #---------------------------------------------------------------
    577 -        def get_identities(self, same_lastname=False):
    578                  pass
    579          #--------------------------------------------------------
    580 -        def format(self, single_line=False, verbose=False, show_type=True):
    581                  if single_line:
    582                          return format_address_single_line(address = self, verbose = verbose, show_type = show_type)
    583                  txt = format_address(address = self, show_type = show_type)
    584                  return txt
    585          #--------------------------------------------------------
    586 -        def _get_address(self):
    587                  return cAddress(aPK_obj = self._payload[self._idx['pk_address']])
    588
    589          address = property(_get_address, lambda x:x)
    590
    591  #===================================================================
    592  # communication channels API
    593  #-------------------------------------------------------------------
    594 -class cCommChannel(gmBusinessDBObject.cBusinessDBObject):
    595
    596          _cmd_fetch_payload = u"SELECT * FROM dem.v_person_comms WHERE pk_lnk_identity2comm = %s"
    597          _cmds_store_payload = [
    598                  u"""UPDATE dem.lnk_identity2comm SET
    599                                  --fk_address = %(pk_address)s,
    600                                  fk_type = dem.create_comm_type(%(comm_type)s),
    601                                  url = %(url)s,
    602                                  is_confidential = %(is_confidential)s,
    603                                  comment = gm.nullify_empty_string(%(comment)s)
    604                          WHERE
    605                                  pk = %(pk_lnk_identity2comm)s
    606                                          AND
    607                                  xmin = %(xmin_lnk_identity2comm)s
    608                          RETURNING
    609                                  xmin AS xmin_lnk_identity2comm
    610                  """
    611          ]
    612          _updatable_fields = [
    613                  'url',
    614                  'comm_type',
    615                  'is_confidential',
    616                  'comment'
    617          ]
    618
    619  #-------------------------------------------------------------------
    620 -class cOrgCommChannel(gmBusinessDBObject.cBusinessDBObject):
    621
    622          _cmd_fetch_payload = u"SELECT * FROM dem.v_org_unit_comms WHERE pk_lnk_org_unit2comm = %s"
    623          _cmds_store_payload = [
    624                  u"""UPDATE dem.lnk_org_unit2comm SET
    625                                  fk_type = dem.create_comm_type(%(comm_type)s),
    626                                  url = %(url)s,
    627                                  is_confidential = %(is_confidential)s,
    628                                  comment = gm.nullify_empty_string(%(comment)s)
    629                          WHERE
    630                                  pk = %(pk_lnk_org_unit2comm)s
    631                                          AND
    632                                  xmin = %(xmin_lnk_org_unit2comm)s
    633                          RETURNING
    634                                  xmin AS xmin_lnk_org_unit2comm
    635                  """
    636          ]
    637          _updatable_fields = [
    638                  'url',
    639                  'comm_type',
    640                  'is_confidential',
    641                  'comment'
    642          ]
    643
    644  #-------------------------------------------------------------------
    645 -def create_comm_channel(comm_medium=None, url=None, is_confidential=False, pk_channel_type=None, pk_identity=None, pk_org_unit=None):
    646          """Create a communications channel for a patient."""
    647
    648          if url is None:
    649                  return None
    650
    651          args = {
    652                  'url': url,
    653                  'secret': is_confidential,
    654                  'pk_type': pk_channel_type,
    655                  'type': comm_medium
    656          }
    657
    658          if pk_identity is not None:
    659                  args['pk_owner'] = pk_identity
    660                  tbl = u'dem.lnk_identity2comm'
    661                  col = u'fk_identity'
    662                  view = u'dem.v_person_comms'
    663                  view_pk = u'pk_lnk_identity2comm'
    664                  channel_class = cCommChannel
    665          if pk_org_unit is not None:
    666                  args['pk_owner'] = pk_org_unit
    667                  tbl = u'dem.lnk_org_unit2comm'
    668                  col = u'fk_org_unit'
    669                  view = u'dem.v_org_unit_comms'
    670                  view_pk = u'pk_lnk_org_unit2comm'
    671                  channel_class = cOrgCommChannel
    672
    673          if pk_channel_type is None:
    674                  cmd = u"""INSERT INTO %s (
    675                          %s,
    676                          url,
    677                          fk_type,
    678                          is_confidential
    679                  ) VALUES (
    680                          %%(pk_owner)s,
    681                          %%(url)s,
    682                          dem.create_comm_type(%%(type)s),
    683                          %%(secret)s
    684                  )""" % (tbl, col)
    685          else:
    686                  cmd = u"""INSERT INTO %s (
    687                          %s,
    688                          url,
    689                          fk_type,
    690                          is_confidential
    691                  ) VALUES (
    692                          %%(pk_owner)s,
    693                          %%(url)s,
    694                          %%(pk_type)s,
    695                          %%(secret)s
    696                  )""" % (tbl, col)
    697
    698          queries = [{'cmd': cmd, 'args': args}]
    699          cmd = u"SELECT * FROM %s WHERE %s = currval(pg_get_serial_sequence('%s', 'pk'))" % (view, view_pk, tbl)
    700          queries.append({'cmd': cmd})
    701
    702          rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True, get_col_idx = True)
    703
    704          if pk_identity is not None:
    705                  return cCommChannel(row = {'pk_field': view_pk, 'data': rows[0], 'idx': idx})
    706
    707          return channel_class(row = {'pk_field': view_pk, 'data': rows[0], 'idx': idx})
    708  #-------------------------------------------------------------------
    709 -def delete_comm_channel(pk=None, pk_patient=None, pk_org_unit=None):
    710          if pk_patient is not None:
    711                  query = {
    712                          'cmd': u"DELETE FROM dem.lnk_identity2comm WHERE pk = %(pk)s AND fk_identity = %(pat)s",
    713                          'args': {'pk': pk, 'pat': pk_patient}
    714                  }
    715          if pk_org_unit is not None:
    716                  query = {
    717                          'cmd': u"DELETE FROM dem.lnk_org_unit2comm WHERE pk = %(pk)s AND fk_org_unit = %(unit)s",
    718                          'args': {'pk': pk, 'unit': pk_org_unit}
    719                  }
    720          gmPG2.run_rw_queries(queries = [query])
    721  #-------------------------------------------------------------------
    722 -def get_comm_channel_types():
    723          cmd = u"SELECT pk, _(description) AS l10n_description, description FROM dem.enum_comm_types"
    724          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False)
    725          return rows
    726  #-------------------------------------------------------------------
    727 -def delete_comm_channel_type(pk_channel_type=None):
    728          cmd = u"""
    729                  DELETE FROM dem.enum_comm_types
    730                  WHERE
    731                          pk = %(pk)s
    732                          AND NOT EXISTS (
    733                                  SELECT 1 FROM dem.lnk_identity2comm WHERE fk_type = %(pk)s
    734                          )
    735                          AND NOT EXISTS (
    736                                  SELECT 1 FROM dem.lnk_org_unit2comm WHERE fk_type = %(pk)s
    737                          )
    738          """
    739          gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': pk_channel_type}}])
    740          return True
    741  #===================================================================
    742  #-------------------------------------------------------------------
    743
    744  #==============================================================================
    745 -def get_time_tuple (mx):
    746          """
    747          wrap mx.DateTime brokenness
    748          Returns 9-tuple for use with pyhon time functions
    749          """
    750          return [ int(x) for x in  str(mx).split(' ')[0].split('-') ] + [0,0,0, 0,0,0]
    751  #----------------------------------------------------------------
    752 -def getAddressTypes():
    753          """Gets a dict matching address types to their ID"""
    754          row_list = gmPG.run_ro_query('personalia', "select name, id from dem.address_type")
    755          if row_list is None:
    756                  return {}
    757          if len(row_list) == 0:
    758                  return {}
    759          return dict (row_list)
    760  #----------------------------------------------------------------
    761 -def getMaritalStatusTypes():
    762          """Gets a dictionary matching marital status types to their internal ID"""
    763          row_list = gmPG.run_ro_query('personalia', "select name, pk from dem.marital_status")
    764          if row_list is None:
    765                  return {}
    766          if len(row_list) == 0:
    767                  return {}
    768          return dict(row_list)
    769  #------------------------------------------------------------------
    770 -def getRelationshipTypes():
    771          """Gets a dictionary of relationship types to internal id"""
    772          row_list = gmPG.run_ro_query('personalia', "select description, id from dem.relation_types")
    773          if row_list is None:
    774                  return None
    775          if len (row_list) == 0:
    776                  return None
    777          return dict(row_list)
    778
    779  #----------------------------------------------------------------
    780 -def getUrb (id_urb):
    781          cmd = """
    782  select
    783          dem.state.name,
    784          dem.urb.postcode
    785  from
    786          dem.urb,
    787          dem.state
    788  where
    789          dem.urb.id = %s and
    790          dem.urb.id_state = dem.state.id"""
    791          row_list = gmPG.run_ro_query('personalia', cmd, None, id_urb)
    792          if not row_list:
    793                  return None
    794          else:
    795                  return (row_list[0][0], row_list[0][1])
    796
    797 -def getStreet (id_street):
    798          cmd = """
    799  select
    800          dem.state.name,
    801          coalesce (dem.street.postcode, dem.urb.postcode),
    802          dem.urb.name
    803  from
    804          dem.urb,
    805          dem.state,
    806          dem.street
    807  where
    808          dem.street.id = %s and
    809          dem.street.id_urb = dem.urb.id and
    810          dem.urb.id_state = dem.state.id
    811  """
    812          row_list = gmPG.run_ro_query('personalia', cmd, None, id_street)
    813          if not row_list:
    814                  return None
    815          else:
    816                  return (row_list[0][0], row_list[0][1], row_list[0][2])
    817
    818 -def getCountry (country_code):
    819          row_list = gmPG.run_ro_query('personalia', "select name from dem.country where code = %s", None, country_code)
    820          if not row_list:
    821                  return None
    822          else:
    823                  return row_list[0][0]
    824  #-------------------------------------------------------------------------------
    825 -def get_town_data (town):
    826          row_list = gmPG.run_ro_query ('personalia', """
    827  select
    828          dem.urb.postcode,
    829          dem.state.code,
    830          dem.state.name,
    831          dem.country.code,
    832          dem.country.name
    833  from
    834          dem.urb,
    835          dem.state,
    836          dem.country
    837  where
    838          dem.urb.name = %s and
    839          dem.urb.id_state = dem.state.id and
    840          dem.state.country = dem.country.code""", None, town)
    841          if not row_list:
    842                  return (None, None, None, None, None)
    843          else:
    844                  return tuple (row_list[0])
    845  #============================================================
    846  # callbacks
    847  #------------------------------------------------------------
    848 -def _post_patient_selection(**kwargs):
    849          print "received post_patient_selection notification"
    850          print kwargs['kwds']
    851  #============================================================
    852
    853  #============================================================
    854  # main
    855  #------------------------------------------------------------
    856  if __name__ == "__main__":
    857
    858          if len(sys.argv) < 2:
    859                  sys.exit()
    860
    861          if sys.argv[1] != 'test':
    862                  sys.exit()
    863
    864          import random
    865          #--------------------------------------------------------
    866 -        def test_address_exists():
    867
    868                  addresses = [
    869                          {
    870                          'country': 'Germany',
    871                          'state': 'Sachsen',
    872                          'urb': 'Leipzig',
    873                          'postcode': '04318',
    874                          'street': u'Cunnersdorfer Strasse',
    875                          'number': '11'
    876                          },
    877                          {
    878                          'country': 'DE',
    879                          'state': 'SN',
    880                          'urb': 'Leipzig',
    881                          'postcode': '04317',
    882                          'street': u'Riebeckstraße',
    883                          'number': '65',
    884                          'subunit': 'Parterre'
    885                          },
    886                          {
    887                          'country': 'DE',
    888                          'state': 'SN',
    889                          'urb': 'Leipzig',
    890                          'postcode': '04317',
    891                          'street': u'Riebeckstraße',
    892                          'number': '65',
    893                          'subunit': '1. Stock'
    894                          },
    895                          {
    896                          'country': 'DE',
    897                          'state': 'SN',
    898                          'urb': 'Leipzig',
    899                          'postcode': '04317',
    900                          'street': u'Riebeckstraße',
    901                          'number': '65',
    902                          'subunit': '1. Stock'
    903                          },
    904                          {
    905  #                       'country': 'DE',
    906  #                       'state': 'SN',
    907                          'urb': 'Leipzig',
    908                          'postcode': '04317',
    909                          'street': u'Riebeckstraße',
    910                          'number': '65',
    911                          'subunit': '1. Stock'
    912                          },
    913                  ]
    914
    915                  for adr in addresses:
    916                          print adr
    917                          exists = address_exists(**adr)
    918                          if exists is None:
    919                                  print "address does not exist"
    920                          else:
    921                                  print "address exists, primary key:", exists
    922
    923          #--------------------------------------------------------
    924 -        def test_create_address():
    925                  address = create_address (
    926                          country ='DE',
    927                          state ='SN',
    928                          urb ='Leipzig',
    929                          suburb ='Sellerhausen',
    930                          postcode ='04318',
    931                          street = u'Cunnersdorfer Strasse',
    932                          number = '11'
    933  #                       ,notes_subunit = '4.Stock rechts'
    934                  )
    935                  print "created existing address"
    936                  print address.format()
    937
    938                  su = str(random.random())
    939
    940                  address = create_address (
    941                          country ='DE',
    942                          state = 'SN',
    943                          urb ='Leipzig',
    944                          suburb ='Sellerhausen',
    945                          postcode ='04318',
    946                          street = u'Cunnersdorfer Strasse',
    947                          number = '11',
    948  #                       notes_subunit = '4.Stock rechts',
    949                          subunit = su
    950                  )
    951                  print "created new address with subunit", su
    952                  print address
    953                  print address.format()
    954                  print "deleted address:", delete_address(pk_address = address['pk_address'])
    955          #--------------------------------------------------------
    956 -        def test_get_countries():
    957                  for c in get_countries():
    958                          print c
    959          #--------------------------------------------------------
    960 -        def test_get_country_for_region():
    961                  region = raw_input("Please enter a region: ")
    962                  print "country for region [%s] is: %s" % (region, get_country_for_region(region = region))
    963          #--------------------------------------------------------
    964 -        def test_delete_tag():
    965                  if delete_tag_image(tag_image = 9999):
    966                          print "deleted tag 9999"
    967                  else:
    968                          print "did not delete tag 9999"
    969                  if delete_tag_image(tag_image = 1):
    970                          print "deleted tag 1"
    971                  else:
    972                          print "did not delete tag 1"
    973          #--------------------------------------------------------
    974 -        def test_tag_images():
    975                  tag = cTagImage(aPK_obj = 1)
    976                  print tag
    977                  #print get_tag_images()
    978          #--------------------------------------------------------
    979 -        def test_get_billing_address():
    980                  print get_patient_address_by_type(pk_patient = 12, adr_type = u'billing')
    981          #--------------------------------------------------------
    982          #gmPG2.get_connection()
    983
    984          #test_address_exists()
    985          #test_create_address()
    986          #test_get_countries()
    987          #test_get_country_for_region()
    988          #test_delete_tag()
    989          test_tag_images()
    990          #test_get_billing_address()
    991
    992          sys.exit()
    993  #============================================================
    994