Gnumed.business.gmDemographicRecord

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

# Source Code for Module Gnumed.business.gmDemographicRecord

       1  # -*- coding: utf-8 -*-
       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  import urllib.parse
      18
      19
      20  # GNUmed
      21  if __name__ == '__main__':
      22          sys.path.insert(0, '../../')
      23  from Gnumed.pycommon import gmDispatcher
      24  from Gnumed.pycommon import gmBusinessDBObject
      25  from Gnumed.pycommon import gmPG2
      26  from Gnumed.pycommon import gmTools
      27
      28
      29  _log = logging.getLogger('gm.business')
      30
      31  #============================================================
      32  # occupation handling
      33  #------------------------------------------------------------
      34 -def get_occupations(pk_identity=None):
      35          cmd = """
      36                  SELECT *
      37                  FROM dem.v_person_jobs
      38                  WHERE pk_identity = %(pk)s
      39                  ORDER BY l10n_occupation
      40          """
      41          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'pk': pk_identity}}])
      42          return rows
      43  #============================================================
      44  # text+image tags
      45  #------------------------------------------------------------
      46  _SQL_get_tag_image = "SELECT * FROM ref.v_tag_images_no_data WHERE %s"
      47
      48 -class cTagImage(gmBusinessDBObject.cBusinessDBObject):
      49
      50          _cmd_fetch_payload = _SQL_get_tag_image % "pk_tag_image = %s"
      51          _cmds_store_payload = [
      52                  """
      53                          UPDATE ref.tag_image SET
      54                                  description = gm.nullify_empty_string(%(description)s),
      55                                  filename = gm.nullify_empty_string(%(filename)s)
      56                          WHERE
      57                                  pk = %(pk_tag_image)s
      58                                          AND
      59                                  xmin = %(xmin_tag_image)s
      60                          RETURNING
      61                                  pk as pk_tag_image,
      62                                  xmin as xmin_tag_image
      63                  """
      64          ]
      65          _updatable_fields = ['description', 'filename']
      66          #--------------------------------------------------------
      67 -        def export_image2file(self, aChunkSize=0, filename=None):
      68
      69                  if self._payload[self._idx['size']] == 0:
      70                          return None
      71
      72                  if filename is None:
      73                          suffix = None
      74                          # preserve original filename extension if available
      75                          if self._payload[self._idx['filename']] is not None:
      76                                  name, suffix = os.path.splitext(self._payload[self._idx['filename']])
      77                                  suffix = suffix.strip()
      78                                  if suffix == '':
      79                                          suffix = None
      80                          # get unique filename
      81                          filename = gmTools.get_unique_filename (
      82                                  prefix = 'gm-tag_image-',
      83                                  suffix = suffix
      84                          )
      85
      86                  success = gmPG2.bytea2file (
      87                          data_query = {
      88                                  'cmd': 'SELECT substring(image from %(start)s for %(size)s) FROM ref.tag_image WHERE pk = %(pk)s',
      89                                  'args': {'pk': self.pk_obj}
      90                          },
      91                          filename = filename,
      92                          chunk_size = aChunkSize,
      93                          data_size = self._payload[self._idx['size']]
      94                  )
      95
      96                  if success:
      97                          return filename
      98
      99                  return None
     100          #--------------------------------------------------------
     101 -        def update_image_from_file(self, filename=None):
     102                  # sanity check
     103                  if not (os.access(filename, os.R_OK) and os.path.isfile(filename)):
     104                          _log.error('[%s] is not a readable file' % filename)
     105                          return False
     106
     107                  gmPG2.file2bytea (
     108                          query = "UPDATE ref.tag_image SET image = %(data)s::bytea WHERE pk = %(pk)s",
     109                          filename = filename,
     110                          args = {'pk': self.pk_obj}
     111                  )
     112
     113                  # must update XMIN now ...
     114                  self.refetch_payload()
     115                  return True
     116  #------------------------------------------------------------
     117 -def get_tag_images(order_by=None):
     118          if order_by is None:
     119                  order_by = 'true'
     120          else:
     121                  order_by = 'true ORDER BY %s' % order_by
     122
     123          cmd = _SQL_get_tag_image % order_by
     124          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True)
     125          return [ cTagImage(row = {'data': r, 'idx': idx, 'pk_field': 'pk_tag_image'}) for r in rows ]
     126  #------------------------------------------------------------
     127 -def create_tag_image(description=None, link_obj=None):
     128
     129          args = {'desc': description, 'img': ''}
     130          cmd = """
     131                  INSERT INTO ref.tag_image (
     132                          description,
     133                          image
     134                  ) VALUES (
     135                          %(desc)s,
     136                          %(img)s::bytea
     137                  )
     138                  RETURNING pk
     139          """
     140          rows, idx = gmPG2.run_rw_queries (
     141                  link_obj = link_obj,
     142                  queries = [{'cmd': cmd, 'args': args}],
     143                  end_tx = True,
     144                  return_data = True,
     145                  get_col_idx = False
     146          )
     147
     148          return cTagImage(aPK_obj = rows[0]['pk'])
     149  #------------------------------------------------------------
     150 -def delete_tag_image(tag_image=None):
     151          args = {'pk': tag_image}
     152          cmd = """
     153                  DELETE FROM ref.tag_image
     154                  WHERE
     155                          pk = %(pk)s
     156                                  AND
     157                          NOT EXISTS (
     158                                  SELECT 1
     159                                  FROM dem.identity_tag
     160                                  WHERE fk_tag = %(pk)s
     161                                  LIMIT 1
     162                          )
     163                  RETURNING 1
     164          """
     165          rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
     166          if len(rows) == 0:
     167                  return False
     168          return True
     169
     170  #============================================================
     171  _SQL_get_person_tags = """SELECT * FROM dem.v_identity_tags WHERE %s"""
     172
     173 -class cPersonTag(gmBusinessDBObject.cBusinessDBObject):
     174
     175          _cmd_fetch_payload = _SQL_get_person_tags % "pk_identity_tag = %s"
     176          _cmds_store_payload = [
     177                  """
     178                          UPDATE dem.identity_tag SET
     179                                  fk_tag = %(pk_tag_image)s,
     180                                  comment = gm.nullify_empty_string(%(comment)s)
     181                          WHERE
     182                                  pk = %(pk_identity_tag)s
     183                                          AND
     184                                  xmin = %(xmin_identity_tag)s
     185                          RETURNING
     186                                  pk as pk_identity_tag,
     187                                  xmin as xmin_identity_tag
     188                  """
     189          ]
     190          _updatable_fields = ['fk_tag',  'comment']
     191          #--------------------------------------------------------
     192 -        def export_image2file(self, aChunkSize=0, filename=None):
     193
     194                  if self._payload[self._idx['image_size']] == 0:
     195                          return None
     196
     197                  if filename is None:
     198                          suffix = None
     199                          # preserve original filename extension if available
     200                          if self._payload[self._idx['filename']] is not None:
     201                                  name, suffix = os.path.splitext(self._payload[self._idx['filename']])
     202                                  suffix = suffix.strip()
     203                                  if suffix == '':
     204                                          suffix = None
     205                          # get unique filename
     206                          filename = gmTools.get_unique_filename (
     207                                  prefix = 'gm-person_tag-',
     208                                  suffix = suffix
     209                          )
     210
     211                  exported = gmPG2.bytea2file (
     212                          data_query = {
     213                                  'cmd': 'SELECT substring(image from %(start)s for %(size)s) FROM ref.tag_image WHERE pk = %(pk)s',
     214                                  'args': {'pk': self._payload[self._idx['pk_tag_image']]}
     215                          },
     216                          filename = filename,
     217                          chunk_size = aChunkSize,
     218                          data_size = self._payload[self._idx['image_size']]
     219                  )
     220                  if exported:
     221                          return filename
     222
     223                  return None
     224
     225  #============================================================
     226  # country/region related
     227  #============================================================
     228 -def get_countries():
     229          cmd = """
     230                  SELECT
     231                          _(name) AS l10n_country, name, code, deprecated
     232                  FROM dem.country
     233                  ORDER BY l10n_country"""
     234          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}])
     235          return rows
     236
     237  #------------------------------------------------------------
     238 -def get_country_for_region(region=None):
     239          cmd = """
     240  SELECT code_country, l10n_country FROM dem.v_region WHERE lower(l10n_region) = lower(%(region)s)
     241          union
     242  SELECT code_country, l10n_country FROM dem.v_region WHERE lower(region) = lower(%(region)s)
     243  """
     244          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'region': region}}])
     245          return rows
     246
     247  #------------------------------------------------------------
     248 -def map_country2code(country=None):
     249          cmd = """
     250                  SELECT code FROM dem.country WHERE lower(_(name)) = lower(%(country)s)
     251                          UNION
     252                  SELECT code FROM dem.country WHERE lower(name) = lower(%(country)s)
     253          """
     254          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'country': country}}], get_col_idx = False)
     255          if len(rows) == 0:
     256                  return None
     257          return rows[0][0]
     258
     259  #------------------------------------------------------------
     260 -def map_urb_zip_region2country(urb=None, zip=None, region=None):
     261
     262          args = {'urb': urb, 'zip': zip, 'region': region}
     263          cmd = """(
     264                  -- find by using all known details
     265                  SELECT
     266                          1 AS rank,
     267                          country,
     268                          l10n_country,
     269                          code_country
     270                  FROM dem.v_urb WHERE
     271                          postcode_urb = %(zip)s
     272                                  AND
     273                          lower(urb) = lower(%(urb)s)
     274                                  AND
     275                          (
     276                                  (lower(region) = lower(coalesce(%(region)s, 'state/territory/province/region not available')))
     277                                          OR
     278                                  (lower(l10n_region) = lower(coalesce(%(region)s, _('state/territory/province/region not available'))))
     279                          )
     280
     281                  ) UNION (
     282
     283                  -- find by using zip/urb
     284                  SELECT
     285                          2 AS rank,
     286                          country,
     287                          l10n_country,
     288                          code_country
     289                  FROM dem.v_urb WHERE
     290                          postcode_urb = %(zip)s
     291                                  AND
     292                          lower(urb) = lower(%(urb)s)
     293
     294                  ) UNION (
     295
     296                  -- find by using zip/region
     297                  SELECT
     298                          2 AS rank,
     299                          country,
     300                          l10n_country,
     301                          code_country
     302                  FROM dem.v_urb WHERE
     303                          postcode_urb = %(zip)s
     304                                  AND
     305                          (
     306                                  (lower(region) = lower(%(region)s))
     307                                          OR
     308                                  (lower(l10n_region) = lower(%(region)s))
     309                          )
     310
     311                  ) UNION (
     312
     313                  -- find by using urb/region
     314                  SELECT
     315                          2 AS rank,
     316                          country,
     317                          l10n_country,
     318                          code_country
     319                  FROM dem.v_urb WHERE
     320                          lower(urb) = lower(%(urb)s)
     321                                  AND
     322                          ((lower(region) = lower(%(region)s))
     323                                  OR
     324                          (lower(l10n_region) = lower(%(region)s)))
     325
     326                  ) UNION (
     327
     328                  -- find by region
     329                  SELECT
     330                          2 AS rank,
     331                          country,
     332                          l10n_country,
     333                          code_country
     334                  FROM dem.v_region WHERE
     335                          lower(region) = lower(%(region)s)
     336                                  OR
     337                          lower(l10n_region) = lower(%(region)s)
     338
     339                  ) ORDER BY rank"""
     340
     341          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
     342          if len(rows) == 0:
     343                  _log.debug('zip [%s] / urb [%s] / region [%s] => ??', zip, urb, region)
     344                  return None
     345          if len(rows) > 2:
     346                  _log.debug('zip [%s] / urb [%s] / region [%s] => [%s]', zip, urb, region, rows)
     347                  return None
     348          country = rows[0]
     349          _log.debug('zip [%s] / urb [%s] / region [%s] => [%s]', zip, urb, region, country)
     350          return country
     351
     352  #------------------------------------------------------------
     353 -def map_urb_zip_country2region(urb=None, zip=None, country=None, country_code=None):
     354
     355          args = {'urb': urb, 'zip': zip, 'country': country, 'country_code': country_code}
     356          cmd = """(
     357                  -- find by using all known details
     358                  SELECT
     359                          1 AS rank,
     360                          region,
     361                          l10n_region,
     362                          code_region
     363                  FROM dem.v_urb WHERE
     364                          postcode_urb = %(zip)s
     365                                  AND
     366                          lower(urb) = lower(%(urb)s)
     367                                  AND
     368                          (
     369                                  (lower(country) = lower(%(country)s))
     370                                          OR
     371                                  (lower(l10n_country) = lower(%(country)s))
     372                                          OR
     373                                  (code_country = %(country_code)s)
     374                          )
     375
     376                  ) UNION (
     377
     378                  -- find by zip / urb
     379                  SELECT
     380                          2 AS rank,
     381                          region,
     382                          l10n_region,
     383                          code_region
     384                  FROM dem.v_urb WHERE
     385                          postcode_urb = %(zip)s
     386                                  AND
     387                          lower(urb) = lower(%(urb)s)
     388
     389                  ) UNION (
     390
     391                  -- find by zip / country
     392                  SELECT
     393                          2 AS rank,
     394                          region,
     395                          l10n_region,
     396                          code_region
     397                  FROM dem.v_urb WHERE
     398                          postcode_urb = %(zip)s
     399                                  AND
     400                          (
     401                                  (lower(country) = lower(%(country)s))
     402                                          OR
     403                                  (lower(l10n_country) = lower(%(country)s))
     404                                          OR
     405                                  (code_country = %(country_code)s)
     406                          )
     407
     408                  ) UNION (
     409
     410                  -- find by urb / country
     411                  SELECT
     412                          2 AS rank,
     413                          region,
     414                          l10n_region,
     415                          code_region
     416                  FROM dem.v_urb WHERE
     417                          lower(urb) = lower(%(urb)s)
     418                                  AND
     419                          (
     420                                  (lower(country) = lower(%(country)s))
     421                                          OR
     422                                  (lower(l10n_country) = lower(%(country)s))
     423                                          OR
     424                                  (code_country = %(country_code)s)
     425                          )
     426
     427                  ) ORDER BY rank"""
     428
     429          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
     430
     431          if len(rows) == 0:
     432                  cmd = """
     433                  -- find by country (some countries will only have one region)
     434                  SELECT
     435                          1 AS rank,              -- dummy to conform with function result structure at Python level
     436                          region,
     437                          l10n_region,
     438                          code_region
     439                  FROM dem.v_region WHERE
     440                          (lower(country) = lower(%(country)s))
     441                                  OR
     442                          (lower(l10n_country) = lower(%(country)s))
     443                                  OR
     444                          (code_country = %(country_code)s)
     445                  """
     446                  rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
     447                  if len(rows) == 1:
     448                          region = rows[0]
     449                          _log.debug('zip [%s] / urb [%s] / country [%s] (%s) => [%s]', zip, urb, country, country_code, region)
     450                          return region
     451                  _log.debug('zip [%s] / urb [%s] / country [%s] (%s) => [??]', zip, urb, country, country_code)
     452                  return None
     453
     454          if len(rows) > 2:
     455                  _log.debug('zip [%s] / urb [%s] / country [%s] (%s) => [%s]', zip, urb, country, country_code, rows)
     456                  return None
     457
     458          region = rows[0]
     459          _log.debug('zip [%s] / urb [%s] / country [%s] (%s) => [%s]', zip, urb, country, country_code, region)
     460          return region
     461
     462  #------------------------------------------------------------
     463 -def map_region2code(region=None, country_code=None):
     464          if country_code is None:
     465                  cmd = """
     466                          SELECT code FROM dem.region WHERE lower(_(name)) = lower(%(region)s)
     467                                  UNION
     468                          SELECT code FROM dem.region WHERE lower(name) = lower(%(region)s)
     469                  """
     470          else:
     471                  cmd = """
     472                          SELECT code FROM dem.region WHERE lower(_(name)) = lower(%(region)s) AND lower(country) = lower(%(country_code)s)
     473                                  UNION
     474                          SELECT code FROM dem.region WHERE lower(name) = %(region)s AND lower(country) = lower(%(country_code)s)
     475                  """
     476          args = {
     477                  'country_code': country_code,
     478                  'region': region
     479          }
     480          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
     481          if len(rows) == 0:
     482                  return None
     483          return rows[0][0]
     484
     485  #------------------------------------------------------------
     486 -def delete_region(region=None, delete_urbs=False):
     487
     488          args = {'region': region}
     489
     490          queries = []
     491          if delete_urbs:
     492                  queries.append ({
     493                          'cmd': """
     494                                  delete from dem.urb du
     495                                  where
     496                                          du.fk_region = %(region)s
     497                                                  and
     498                                          not exists (select 1 from dem.street ds where ds.id_urb = du.id)""",
     499                          'args': args
     500                  })
     501
     502          queries.append ({
     503                  'cmd': """
     504                          DELETE FROM dem.region d_r
     505                          WHERE
     506                                  d_r.pk = %(region)s
     507                                          AND
     508                                  NOT EXISTS (SELECT 1 FROM dem.urb du WHERE du.fk_region = d_r.pk)""",
     509                  'args': args
     510          })
     511
     512          gmPG2.run_rw_queries(queries = queries)
     513
     514          return True
     515
     516  #------------------------------------------------------------
     517 -def create_region(name=None, code=None, country=None):
     518
     519          args = {'code': code, 'country': country, 'name': name}
     520
     521          cmd = """SELECT EXISTS (SELECT 1 FROM dem.region WHERE name = %(name)s)"""
     522          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
     523
     524          if rows[0][0]:
     525                  return
     526
     527          cmd = """
     528                  INSERT INTO dem.region (
     529                          code, country, name
     530                  ) VALUES (
     531                          %(code)s, %(country)s, %(name)s
     532                  )"""
     533          gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
     534  #------------------------------------------------------------
     535 -def get_regions():
     536          cmd = """
     537                  select
     538                          l10n_region, l10n_country, region, code_region, code_country, pk_region, country_deprecated
     539                  from dem.v_region
     540                  order by l10n_country, l10n_region"""
     541          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}])
     542          return rows
     543
     544  #============================================================
     545  # address related classes
     546  #------------------------------------------------------------
     547 -class cAddress(gmBusinessDBObject.cBusinessDBObject):
     548          """A class representing an address as an entity in itself.
     549
     550          We consider addresses to be self-complete "labels" for locations.
     551          It does not depend on any people actually living there. Thus
     552          an address can get attached to as many people as we want to
     553          signify that that is their place of residence/work/...
     554
     555          This class acts on the address as an entity. Therefore it can
     556          modify the address fields. Think carefully about *modifying*
     557          addresses attached to people, though. Most times when you think
     558          person.modify_address() what you *really* want is as sequence of
     559          person.unlink_address(old) and person.link_address(new).
     560
     561          Modifying an address may or may not be the proper thing to do as
     562          it will transparently modify the address for *all* the people to
     563          whom it is attached. In many cases you will want to create a *new*
     564          address and link it to a person instead of the old address.
     565          """
     566          _cmd_fetch_payload = "SELECT * FROM dem.v_address WHERE pk_address = %s"
     567          _cmds_store_payload = [
     568                  """UPDATE dem.address SET
     569                                  aux_street = %(notes_street)s,
     570                                  subunit = %(subunit)s,
     571                                  addendum = %(notes_subunit)s,
     572                                  lat_lon = %(lat_lon_street)s
     573                          WHERE
     574                                  id = %(pk_address)s
     575                                          AND
     576                                  xmin = %(xmin_address)s
     577                          RETURNING
     578                                  xmin AS xmin_address"""
     579          ]
     580          _updatable_fields = [
     581                  'notes_street',
     582                  'subunit',
     583                  'notes_subunit',
     584                  'lat_lon_address'
     585          ]
     586          #--------------------------------------------------------
     587 -        def format(self, single_line=False, verbose=False, show_type=False):
     588                  if single_line:
     589                          return format_address_single_line(address = self, show_type = False, verbose = verbose)
     590                  return format_address(address = self, show_type = False)
     591
     592          #--------------------------------------------------------
     593 -        def _get_as_map_url(self):
     594                  url = 'http://nominatim.openstreetmap.org/search/%s/%s/%s/%s?limit=3' % (
     595                          urllib.parse.quote(self['country'].encode('utf8')),
     596                          urllib.parse.quote(self['urb'].encode('utf8')),
     597                          urllib.parse.quote(self['street'].encode('utf8')),
     598                          urllib.parse.quote(self['number'].encode('utf8'))
     599                  )
     600                  return url
     601
     602          as_map_url = property(_get_as_map_url, lambda x:x)
     603
     604  #------------------------------------------------------------
     605 -def address_exists(country_code=None, region_code=None, urb=None, postcode=None, street=None, number=None, subunit=None):
     606
     607          cmd = """SELECT dem.address_exists(%(country_code)s, %(region_code)s, %(urb)s, %(postcode)s, %(street)s, %(number)s, %(subunit)s)"""
     608          args = {
     609                  'country_code': country_code,
     610                  'region_code': region_code,
     611                  'urb': urb,
     612                  'postcode': postcode,
     613                  'street': street,
     614                  'number': number,
     615                  'subunit': subunit
     616          }
     617
     618          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
     619          if rows[0][0] is None:
     620                  _log.debug('address does not exist')
     621                  for key, val in args.items():
     622                          _log.debug('%s: %s', key, val)
     623                  return None
     624
     625          return rows[0][0]
     626
     627  #------------------------------------------------------------
     628 -def create_address(country_code=None, region_code=None, urb=None, suburb=None, postcode=None, street=None, number=None, subunit=None):
     629
     630          if suburb is not None:
     631                  suburb = gmTools.none_if(suburb.strip(), '')
     632
     633          pk_address = address_exists (
     634                  country_code = country_code,
     635                  region_code = region_code,
     636                  urb = urb,
     637  #               suburb = suburb,
     638                  postcode = postcode,
     639                  street = street,
     640                  number = number,
     641                  subunit = subunit
     642          )
     643          if pk_address is not None:
     644                  return cAddress(aPK_obj = pk_address)
     645
     646          cmd = """
     647  SELECT dem.create_address (
     648          %(number)s,
     649          %(street)s,
     650          %(postcode)s,
     651          %(urb)s,
     652          %(region_code)s,
     653          %(country_code)s,
     654          %(subunit)s
     655  )"""
     656          args = {
     657                  'number': number,
     658                  'street': street,
     659                  'postcode': postcode,
     660                  'urb': urb,
     661                  'region_code': region_code,
     662                  'country_code': country_code,
     663                  'subunit': subunit
     664          }
     665          queries = [{'cmd': cmd, 'args': args}]
     666
     667          rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True)
     668          adr = cAddress(aPK_obj = rows[0][0])
     669
     670          if suburb is not None:
     671                  queries = [{
     672                          # CAVE: suburb will be ignored if there already is one
     673                          'cmd': "UPDATE dem.street SET suburb = %(suburb)s WHERE id = %(pk_street)s AND suburb IS NULL",
     674                          'args': {'suburb': suburb, 'pk_street': adr['pk_street']}
     675                  }]
     676                  rows, idx = gmPG2.run_rw_queries(queries = queries)
     677
     678          return adr
     679  #------------------------------------------------------------
     680 -def delete_address(pk_address=None):
     681          cmd = """
     682                  DELETE FROM dem.address
     683                  WHERE
     684                          id = %(pk)s
     685                                  AND
     686                          NOT EXISTS ((
     687                                  SELECT 1 FROM dem.org_unit WHERE fk_address = %(pk)s LIMIT 1
     688                                          ) UNION (
     689                                  SELECT 1 FROM dem.lnk_identity2comm WHERE fk_address = %(pk)s LIMIT 1
     690                                          ) UNION (
     691                                  SELECT 1 FROM dem.lnk_person_org_address WHERE id_address = %(pk)s LIMIT 1
     692                          ))
     693                  """
     694          rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': pk_address}}])
     695          return True
     696
     697  #------------------------------------------------------------
     698 -def format_address_single_line(address=None, verbose=False, show_type=False):
     699          data = {
     700                  'pk_adr': address['pk_address'],
     701                  'street': address['street'],
     702                  'notes_street': gmTools.coalesce(address['notes_street'], '', ' (%s)'),
     703                  'number': address['number'],
     704                  'subunit': gmTools.coalesce(address['subunit'], '', '/%s'),
     705                  'notes_subunit': gmTools.coalesce(address['notes_subunit'], '', ' (%s)'),
     706                  'zip': address['postcode'],
     707                  'urb': address['urb'],
     708                  'suburb': gmTools.coalesce(address['suburb'], '', ' (%s)'),
     709                  'l10n_region': address['l10n_region'],
     710                  'code_region': address['code_region'],
     711                  'l10n_country': address['l10n_country'],
     712                  'code_country': address['code_country']
     713          }
     714          if show_type:
     715                  data['type'] = address['l10n_address_type']
     716
     717          if verbose:
     718                  if show_type:
     719                          template = _('%(type)s: %(street)s %(number)s%(subunit)s, %(zip)s %(urb)s %(suburb)s, %(code_region)s, %(code_country)s (%(l10n_region)s, %(l10n_country)s)')
     720                  else:
     721                          template = _('%(street)s %(number)s%(subunit)s, %(zip)s %(urb)s %(suburb)s, %(code_region)s, %(code_country)s (%(l10n_region)s, %(l10n_country)s)')
     722          else:
     723                  if show_type:
     724                          template = _('%(type)s: %(street)s %(number)s%(subunit)s, %(zip)s %(urb)s, %(code_region)s, %(code_country)s (%(l10n_region)s, %(l10n_country)s)')
     725                  else:
     726                          template = _('%(street)s %(number)s%(subunit)s, %(zip)s %(urb)s, %(code_region)s, %(code_country)s (%(l10n_region)s, %(l10n_country)s)')
     727
     728          return template % data
     729
     730  #------------------------------------------------------------
     731 -def format_address(address=None, show_type=False):
     732          data = {
     733                  'pk_adr': address['pk_address'],
     734                  'street': address['street'],
     735                  'notes_street': gmTools.coalesce(address['notes_street'], '', ' (%s)'),
     736                  'number': address['number'],
     737                  'subunit': gmTools.coalesce(address['subunit'], '', '/%s'),
     738                  'notes_subunit': gmTools.coalesce(address['notes_subunit'], '', ' (%s)'),
     739                  'zip': address['postcode'],
     740                  'urb': address['urb'],
     741                  'suburb': gmTools.coalesce(address['suburb'], '', ' (%s)'),
     742                  'l10n_region': address['l10n_region'],
     743                  'code_region': address['code_region'],
     744                  'l10n_country': address['l10n_country'],
     745                  'code_country': address['code_country']
     746          }
     747          if show_type:
     748                  data['type'] = address['l10n_address_type']
     749                  template = _(
     750                          'Address (%(type)s) [#%(pk_adr)s]\n'
     751                          ' Street: %(street)s%(notes_street)s\n'
     752                          ' Number/Unit: %(number)s%(subunit)s%(notes_subunit)s\n'
     753                          ' Location: %(zip)s %(urb)s%(suburb)s\n'
     754                          ' Region: %(l10n_region)s, %(code_region)s\n'
     755                          ' Country: %(l10n_country)s, %(code_country)s'
     756                  )
     757          else:
     758                  template = _(
     759                          'Address [#%(pk_adr)s]\n'
     760                          ' Street: %(street)s%(notes_street)s\n'
     761                          ' Number/Unit: %(number)s%(subunit)s%(notes_subunit)s\n'
     762                          ' Location: %(zip)s %(urb)s%(suburb)s\n'
     763                          ' Region: %(l10n_region)s, %(code_region)s\n'
     764                          ' Country: %(l10n_country)s, %(code_country)s'
     765                  )
     766          txt = template % data
     767          return txt.split('\n')
     768
     769  #------------------------------------------------------------
     770 -def create_address_type(address_type=None):
     771          args = {'typ': address_type}
     772          cmd = 'INSERT INTO dem.address_type (name) SELECT %(typ)s WHERE NOT EXISTS (SELECT 1 FROM dem.address_type WHERE name = %(typ)s OR _(name) = %(typ)s)'
     773          rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
     774          cmd = 'SELECT id FROM dem.address_type WHERE name = %(typ)s OR _(name) = %(typ)s'
     775          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
     776          return rows[0][0]
     777
     778  #------------------------------------------------------------
     779 -def get_address_types(identity=None):
     780          cmd = 'select id as pk, name, _(name) as l10n_name from dem.address_type'
     781          rows, idx = gmPG2.run_rw_queries(queries=[{'cmd': cmd}])
     782          return rows
     783  #------------------------------------------------------------
     784 -def get_addresses(order_by=None):
     785
     786          if order_by is None:
     787                  order_by = ''
     788          else:
     789                  order_by = 'ORDER BY %s' % order_by
     790
     791          cmd = "SELECT * FROM dem.v_address %s" % order_by
     792          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True)
     793          return [ cAddress(row = {'data': r, 'idx': idx, 'pk_field': 'pk_address'}) for r in rows ]
     794  #------------------------------------------------------------
     795 -def get_address_from_patient_address_pk(pk_patient_address=None):
     796          cmd = """
     797                  SELECT * FROM dem.v_address WHERE
     798                          pk_address = (
     799                                  SELECT id_address
     800                                  FROM dem.lnk_person_org_address
     801                                  WHERE id = %(pk_pat_adr)s
     802                          )
     803          """
     804          args = {'pk_pat_adr': pk_patient_address}
     805          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
     806          if len(rows) == 0:
     807                  return None
     808          return cAddress(row = {'data': rows[0], 'idx': idx, 'pk_field': 'pk_address'})
     809
     810  #===================================================================
     811 -def get_patient_address(pk_patient_address=None):
     812          cmd = 'SELECT * FROM dem.v_pat_addresses WHERE pk_lnk_person_org_address = %(pk)s'
     813          args = {'pk': pk_patient_address}
     814          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
     815          if len(rows) == 0:
     816                  return None
     817          return cPatientAddress(row = {'data': rows[0], 'idx': idx, 'pk_field': 'pk_address'})
     818
     819  #-------------------------------------------------------------------
     820 -def get_patient_address_by_type(pk_patient=None, adr_type=None):
     821          cmd = 'SELECT * FROM dem.v_pat_addresses WHERE pk_identity = %(pat)s AND (address_type = %(typ)s OR l10n_address_type = %(typ)s)'
     822          args = {'pat': pk_patient, 'typ': adr_type}
     823          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
     824          if len(rows) == 0:
     825                  return None
     826          return cPatientAddress(row = {'data': rows[0], 'idx': idx, 'pk_field': 'pk_address'})
     827
     828  #-------------------------------------------------------------------
     829 -class cPatientAddress(gmBusinessDBObject.cBusinessDBObject):
     830
     831          _cmd_fetch_payload = "SELECT * FROM dem.v_pat_addresses WHERE pk_address = %s"
     832          _cmds_store_payload = [
     833                  """UPDATE dem.lnk_person_org_address SET
     834                                  id_type = %(pk_address_type)s
     835                          WHERE
     836                                  id = %(pk_lnk_person_org_address)s
     837                                          AND
     838                                  xmin = %(xmin_lnk_person_org_address)s
     839                          RETURNING
     840                                  xmin AS xmin_lnk_person_org_address
     841                  """
     842          ]
     843          _updatable_fields = ['pk_address_type']
     844          #---------------------------------------------------------------
     845 -        def get_identities(self, same_lastname=False):
     846                  pass
     847          #--------------------------------------------------------
     848 -        def format(self, single_line=False, verbose=False, show_type=True):
     849                  if single_line:
     850                          return format_address_single_line(address = self, verbose = verbose, show_type = show_type)
     851                  txt = format_address(address = self, show_type = show_type)
     852                  return txt
     853          #--------------------------------------------------------
     854 -        def _get_address(self):
     855                  return cAddress(aPK_obj = self._payload[self._idx['pk_address']])
     856
     857          address = property(_get_address, lambda x:x)
     858
     859          #--------------------------------------------------------
     860 -        def _get_as_map_url(self):
     861                  return self.address.as_map_url
     862
     863          as_map_url = property(_get_as_map_url, lambda x:x)
     864
     865  #===================================================================
     866  # communication channels API
     867  #-------------------------------------------------------------------
     868 -class cCommChannel(gmBusinessDBObject.cBusinessDBObject):
     869
     870          _cmd_fetch_payload = "SELECT * FROM dem.v_person_comms WHERE pk_lnk_identity2comm = %s"
     871          _cmds_store_payload = [
     872                  """UPDATE dem.lnk_identity2comm SET
     873                                  --fk_address = %(pk_address)s,
     874                                  fk_type = dem.create_comm_type(%(comm_type)s),
     875                                  url = %(url)s,
     876                                  is_confidential = %(is_confidential)s,
     877                                  comment = gm.nullify_empty_string(%(comment)s)
     878                          WHERE
     879                                  pk = %(pk_lnk_identity2comm)s
     880                                          AND
     881                                  xmin = %(xmin_lnk_identity2comm)s
     882                          RETURNING
     883                                  xmin AS xmin_lnk_identity2comm
     884                  """
     885          ]
     886          _updatable_fields = [
     887                  'url',
     888                  'comm_type',
     889                  'is_confidential',
     890                  'comment'
     891          ]
     892
     893  #-------------------------------------------------------------------
     894 -class cOrgCommChannel(gmBusinessDBObject.cBusinessDBObject):
     895
     896          _cmd_fetch_payload = "SELECT * FROM dem.v_org_unit_comms WHERE pk_lnk_org_unit2comm = %s"
     897          _cmds_store_payload = [
     898                  """UPDATE dem.lnk_org_unit2comm SET
     899                                  fk_type = dem.create_comm_type(%(comm_type)s),
     900                                  url = %(url)s,
     901                                  is_confidential = %(is_confidential)s,
     902                                  comment = gm.nullify_empty_string(%(comment)s)
     903                          WHERE
     904                                  pk = %(pk_lnk_org_unit2comm)s
     905                                          AND
     906                                  xmin = %(xmin_lnk_org_unit2comm)s
     907                          RETURNING
     908                                  xmin AS xmin_lnk_org_unit2comm
     909                  """
     910          ]
     911          _updatable_fields = [
     912                  'url',
     913                  'comm_type',
     914                  'is_confidential',
     915                  'comment'
     916          ]
     917
     918  #-------------------------------------------------------------------
     919 -def create_comm_channel(comm_medium=None, url=None, is_confidential=False, pk_channel_type=None, pk_identity=None, pk_org_unit=None):
     920          """Create a communications channel for a patient."""
     921
     922          if url is None:
     923                  return None
     924
     925          args = {
     926                  'url': url,
     927                  'secret': is_confidential,
     928                  'pk_type': pk_channel_type,
     929                  'type': comm_medium
     930          }
     931
     932          if pk_identity is not None:
     933                  args['pk_owner'] = pk_identity
     934                  tbl = 'dem.lnk_identity2comm'
     935                  col = 'fk_identity'
     936                  view = 'dem.v_person_comms'
     937                  view_pk = 'pk_lnk_identity2comm'
     938                  channel_class = cCommChannel
     939          if pk_org_unit is not None:
     940                  args['pk_owner'] = pk_org_unit
     941                  tbl = 'dem.lnk_org_unit2comm'
     942                  col = 'fk_org_unit'
     943                  view = 'dem.v_org_unit_comms'
     944                  view_pk = 'pk_lnk_org_unit2comm'
     945                  channel_class = cOrgCommChannel
     946
     947          if pk_channel_type is None:
     948                  cmd = """INSERT INTO %s (
     949                          %s,
     950                          url,
     951                          fk_type,
     952                          is_confidential
     953                  ) VALUES (
     954                          %%(pk_owner)s,
     955                          %%(url)s,
     956                          dem.create_comm_type(%%(type)s),
     957                          %%(secret)s
     958                  )""" % (tbl, col)
     959          else:
     960                  cmd = """INSERT INTO %s (
     961                          %s,
     962                          url,
     963                          fk_type,
     964                          is_confidential
     965                  ) VALUES (
     966                          %%(pk_owner)s,
     967                          %%(url)s,
     968                          %%(pk_type)s,
     969                          %%(secret)s
     970                  )""" % (tbl, col)
     971
     972          queries = [{'cmd': cmd, 'args': args}]
     973          cmd = "SELECT * FROM %s WHERE %s = currval(pg_get_serial_sequence('%s', 'pk'))" % (view, view_pk, tbl)
     974          queries.append({'cmd': cmd})
     975
     976          rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True, get_col_idx = True)
     977
     978          if pk_identity is not None:
     979                  return cCommChannel(row = {'pk_field': view_pk, 'data': rows[0], 'idx': idx})
     980
     981          return channel_class(row = {'pk_field': view_pk, 'data': rows[0], 'idx': idx})
     982  #-------------------------------------------------------------------
     983 -def delete_comm_channel(pk=None, pk_patient=None, pk_org_unit=None):
     984          if pk_patient is not None:
     985                  query = {
     986                          'cmd': "DELETE FROM dem.lnk_identity2comm WHERE pk = %(pk)s AND fk_identity = %(pat)s",
     987                          'args': {'pk': pk, 'pat': pk_patient}
     988                  }
     989          if pk_org_unit is not None:
     990                  query = {
     991                          'cmd': "DELETE FROM dem.lnk_org_unit2comm WHERE pk = %(pk)s AND fk_org_unit = %(unit)s",
     992                          'args': {'pk': pk, 'unit': pk_org_unit}
     993                  }
     994          gmPG2.run_rw_queries(queries = [query])
     995  #-------------------------------------------------------------------
     996 -def get_comm_channel_types():
     997          cmd = "SELECT pk, _(description) AS l10n_description, description FROM dem.enum_comm_types"
     998          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False)
     999          return rows
    1000  #-------------------------------------------------------------------
    1001 -def delete_comm_channel_type(pk_channel_type=None):
    1002          cmd = """
    1003                  DELETE FROM dem.enum_comm_types
    1004                  WHERE
    1005                          pk = %(pk)s
    1006                          AND NOT EXISTS (
    1007                                  SELECT 1 FROM dem.lnk_identity2comm WHERE fk_type = %(pk)s
    1008                          )
    1009                          AND NOT EXISTS (
    1010                                  SELECT 1 FROM dem.lnk_org_unit2comm WHERE fk_type = %(pk)s
    1011                          )
    1012          """
    1013          gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': pk_channel_type}}])
    1014          return True
    1015  #===================================================================
    1016  #-------------------------------------------------------------------
    1017
    1018  #==============================================================================
    1019 -def get_time_tuple (mx):
    1020          """
    1021          wrap mx.DateTime brokenness
    1022          Returns 9-tuple for use with pyhon time functions
    1023          """
    1024          return [ int(x) for x in  str(mx).split(' ')[0].split('-') ] + [0,0,0, 0,0,0]
    1025  #----------------------------------------------------------------
    1026 -def getAddressTypes():
    1027          """Gets a dict matching address types to their ID"""
    1028          row_list = gmPG.run_ro_query('personalia', "select name, id from dem.address_type")
    1029          if row_list is None:
    1030                  return {}
    1031          if len(row_list) == 0:
    1032                  return {}
    1033          return dict (row_list)
    1034  #----------------------------------------------------------------
    1035 -def getMaritalStatusTypes():
    1036          """Gets a dictionary matching marital status types to their internal ID"""
    1037          row_list = gmPG.run_ro_query('personalia', "select name, pk from dem.marital_status")
    1038          if row_list is None:
    1039                  return {}
    1040          if len(row_list) == 0:
    1041                  return {}
    1042          return dict(row_list)
    1043  #------------------------------------------------------------------
    1044 -def getRelationshipTypes():
    1045          """Gets a dictionary of relationship types to internal id"""
    1046          row_list = gmPG.run_ro_query('personalia', "select description, id from dem.relation_types")
    1047          if row_list is None:
    1048                  return None
    1049          if len (row_list) == 0:
    1050                  return None
    1051          return dict(row_list)
    1052
    1053  #----------------------------------------------------------------
    1054 -def getUrb (id_urb):
    1055          cmd = """
    1056  select
    1057          dem.region.name,
    1058          dem.urb.postcode
    1059  from
    1060          dem.urb,
    1061          dem.region
    1062  where
    1063          dem.urb.id = %s and
    1064          dem.urb.fk_region = dem.region.pk"""
    1065          row_list = gmPG.run_ro_query('personalia', cmd, None, id_urb)
    1066          if not row_list:
    1067                  return None
    1068          else:
    1069                  return (row_list[0][0], row_list[0][1])
    1070
    1071 -def getStreet (id_street):
    1072          cmd = """
    1073  select
    1074          dem.region.name,
    1075          coalesce (dem.street.postcode, dem.urb.postcode),
    1076          dem.urb.name
    1077  from
    1078          dem.urb,
    1079          dem.region,
    1080          dem.street
    1081  where
    1082          dem.street.id = %s and
    1083          dem.street.id_urb = dem.urb.id and
    1084          dem.urb.fk_region = dem.region.pk
    1085  """
    1086          row_list = gmPG.run_ro_query('personalia', cmd, None, id_street)
    1087          if not row_list:
    1088                  return None
    1089          else:
    1090                  return (row_list[0][0], row_list[0][1], row_list[0][2])
    1091
    1092 -def getCountry (country_code):
    1093          row_list = gmPG.run_ro_query('personalia', "select name from dem.country where code = %s", None, country_code)
    1094          if not row_list:
    1095                  return None
    1096          else:
    1097                  return row_list[0][0]
    1098  #-------------------------------------------------------------------------------
    1099 -def get_town_data (town):
    1100          row_list = gmPG.run_ro_query ('personalia', """
    1101  select
    1102          dem.urb.postcode,
    1103          dem.region.code,
    1104          dem.region.name,
    1105          dem.country.code,
    1106          dem.country.name
    1107  from
    1108          dem.urb,
    1109          dem.region,
    1110          dem.country
    1111  where
    1112          dem.urb.name = %s and
    1113          dem.urb.fk_region = dem.region.pk and
    1114          dem.region.country = dem.country.code""", None, town)
    1115          if not row_list:
    1116                  return (None, None, None, None, None)
    1117          else:
    1118                  return tuple (row_list[0])
    1119  #============================================================
    1120  # callbacks
    1121  #------------------------------------------------------------
    1122 -def _post_patient_selection(**kwargs):
    1123          print("received post_patient_selection notification")
    1124          print(kwargs['kwds'])
    1125  #============================================================
    1126
    1127  #============================================================
    1128  # main
    1129  #------------------------------------------------------------
    1130  if __name__ == "__main__":
    1131
    1132          if len(sys.argv) < 2:
    1133                  sys.exit()
    1134
    1135          if sys.argv[1] != 'test':
    1136                  sys.exit()
    1137
    1138          import random
    1139          #--------------------------------------------------------
    1140 -        def test_address_exists():
    1141
    1142                  addresses = [
    1143                          {
    1144                          'country': 'Germany',
    1145                          'region_code': 'Sachsen',
    1146                          'urb': 'Hannover',
    1147                          'postcode': '06672',
    1148                          'street': 'Rommelsberger Strasse',
    1149                          'number': '11'
    1150                          },
    1151                          {
    1152                          'country': 'DE',
    1153                          'region_code': 'SN',
    1154                          'urb': 'Hannover',
    1155                          'postcode': '06671',
    1156                          'street': 'Tonnenstraße',
    1157                          'number': '65',
    1158                          'subunit': 'Parterre'
    1159                          },
    1160                          {
    1161                          'country': 'DE',
    1162                          'region_code': 'SN',
    1163                          'urb': 'Hannover',
    1164                          'postcode': '06671',
    1165                          'street': 'Tonnenstraße',
    1166                          'number': '65',
    1167                          'subunit': '1. Stock'
    1168                          },
    1169                          {
    1170                          'country': 'DE',
    1171                          'region_code': 'SN',
    1172                          'urb': 'Hannover',
    1173                          'postcode': '06671',
    1174                          'street': 'Tonnenstraße',
    1175                          'number': '65',
    1176                          'subunit': '1. Stock'
    1177                          },
    1178                          {
    1179  #                       'country': 'DE',
    1180  #                       'region_code': 'HV',
    1181                          'urb': 'Hannover',
    1182                          'postcode': '06671',
    1183                          'street': 'Tonnenstraße',
    1184                          'number': '65',
    1185                          'subunit': '1. Stock'
    1186                          },
    1187                  ]
    1188
    1189                  for adr in addresses:
    1190                          print(adr)
    1191                          exists = address_exists(**adr)
    1192                          if exists is None:
    1193                                  print("address does not exist")
    1194                          else:
    1195                                  print("address exists, primary key:", exists)
    1196
    1197          #--------------------------------------------------------
    1198 -        def test_create_address():
    1199                  address = create_address (
    1200                          country_code = 'DE',
    1201                          region_code = 'SN',
    1202                          urb ='Hannover',
    1203                          suburb ='Grabenthal',
    1204                          postcode ='06672',
    1205                          street = 'Rommelsberger Strasse',
    1206                          number = '11'
    1207  #                       ,notes_subunit = '2.Stock oben'
    1208                  )
    1209                  print("created existing address")
    1210                  print(address.format())
    1211
    1212                  su = str(random.random())
    1213
    1214                  address = create_address (
    1215                          country_code = 'DE',
    1216                          region_code = 'SN',
    1217                          urb ='Hannover',
    1218                          suburb ='Grabenthal',
    1219                          postcode ='06672',
    1220                          street = 'Rommelsberger Strasse',
    1221                          number = '11',
    1222  #                       notes_subunit = '2.Stock oben',
    1223                          subunit = su
    1224                  )
    1225                  print("created new address with subunit", su)
    1226                  print(address)
    1227                  print(address.format())
    1228                  print(address.as_map_url)
    1229                  print("deleted address:", delete_address(pk_address = address['pk_address']))
    1230          #--------------------------------------------------------
    1231 -        def test_get_countries():
    1232                  for c in get_countries():
    1233                          print(c)
    1234          #--------------------------------------------------------
    1235 -        def test_get_country_for_region():
    1236                  region = input("Please enter a region: ")
    1237                  print("country for region [%s] is: %s" % (region, get_country_for_region(region = region)))
    1238          #--------------------------------------------------------
    1239 -        def test_delete_tag():
    1240                  if delete_tag_image(tag_image = 9999):
    1241                          print("deleted tag 9999")
    1242                  else:
    1243                          print("did not delete tag 9999")
    1244                  if delete_tag_image(tag_image = 1):
    1245                          print("deleted tag 1")
    1246                  else:
    1247                          print("did not delete tag 1")
    1248          #--------------------------------------------------------
    1249 -        def test_tag_images():
    1250                  tag = cTagImage(aPK_obj = 1)
    1251                  print(tag)
    1252                  #print get_tag_images()
    1253          #--------------------------------------------------------
    1254 -        def test_get_billing_address():
    1255                  print(get_patient_address_by_type(pk_patient = 12, adr_type = 'billing'))
    1256          #--------------------------------------------------------
    1257 -        def test_map_urb_zip_region2country():
    1258                  print(map_urb_zip_region2country(urb = 'Kassel', zip = '34119', region = 'Hessen'))
    1259                  print(map_urb_zip_region2country(urb = 'Kassel', zip = None, region = 'Hessen'))
    1260                  print(map_urb_zip_region2country(urb = None, zip = '34119', region = 'Hessen'))
    1261                  print(map_urb_zip_region2country(urb = 'Kassel', zip = '34119', region = None))
    1262          #--------------------------------------------------------
    1263 -        def test_map_urb_zip_country2region():
    1264                  print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = 'Germany', country_code = 'DE'))
    1265                  print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = 'Germany', country_code = None))
    1266                  print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = 'Deutschland', country_code = 'DE'))
    1267                  print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = 'Deutschland', country_code = None))
    1268                  print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = None, country_code = 'DE'))
    1269                  print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = None, country_code = None))
    1270
    1271  #               print map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = u'Deutschland', country_code = 'DE')
    1272  #               print map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = u'Deutschland', country_code = 'DE')
    1273  #               print map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = u'Deutschland', country_code = 'DE')
    1274  #               print map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = u'Deutschland', country_code = 'DE')
    1275
    1276          #--------------------------------------------------------
    1277          #gmPG2.get_connection()
    1278
    1279          #test_address_exists()
    1280          test_create_address()
    1281          #test_get_countries()
    1282          #test_get_country_for_region()
    1283          #test_delete_tag()
    1284          #test_tag_images()
    1285          #test_get_billing_address()
    1286          #test_map_urb_zip_region2country()
    1287          #test_map_urb_zip_country2region()
    1288