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