Gnumed.business.gmOrganization

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

# Source Code for Module Gnumed.business.gmOrganization

       1  """Organization classes
       2
       3  author: Karsten Hilbert et al
       4  """
       5  #============================================================
       6  __license__ = "GPL"
       7
       8
       9  import sys, logging
      10
      11
      12  if __name__ == '__main__':
      13          sys.path.insert(0, '../../')
      14  from Gnumed.pycommon import gmPG2
      15  from Gnumed.pycommon import gmTools
      16  from Gnumed.pycommon import gmBusinessDBObject
      17
      18  from Gnumed.business import gmDemographicRecord
      19
      20
      21  _log = logging.getLogger('gm.org')
      22
      23  #============================================================
      24 -def create_org_category(category=None, link_obj=None):
      25          args = {'cat': category}
      26          cmd1 = """INSERT INTO dem.org_category (description) SELECT %(cat)s
      27  WHERE NOT EXISTS (
      28          SELECT 1 FROM dem.org_category WHERE description = %(cat)s or _(description) = %(cat)s
      29  )"""
      30          cmd2 = """SELECT pk FROM dem.org_category WHERE description = %(cat)s or _(description) = %(cat)s LIMIT 1"""
      31          queries = [
      32                  {'cmd': cmd1, 'args': args},
      33                  {'cmd': cmd2, 'args': args}
      34          ]
      35          rows, idx = gmPG2.run_rw_queries(link_obj = link_obj, queries = queries, get_col_idx = False, return_data = True)
      36          return rows[0][0]
      37
      38  #============================================================
      39  # organization API
      40  #------------------------------------------------------------
      41  _SQL_get_org = 'SELECT * FROM dem.v_orgs WHERE %s'
      42
      43 -class cOrg(gmBusinessDBObject.cBusinessDBObject):
      44
      45          _cmd_fetch_payload = _SQL_get_org % 'pk_org = %s'
      46          _cmds_store_payload = [
      47                  """UPDATE dem.org SET
      48                                  description = %(organization)s,
      49                                  fk_category = %(pk_category_org)s
      50                          WHERE
      51                                  pk = %(pk_org)s
      52                                          AND
      53                                  xmin = %(xmin_org)s
      54                          RETURNING
      55                                  xmin AS xmin_org"""
      56          ]
      57          _updatable_fields = [
      58                  'organization',
      59                  'pk_category_org'
      60          ]
      61          #--------------------------------------------------------
      62 -        def add_unit(self, unit=None):
      63                  return create_org_unit(pk_organization = self._payload[self._idx['pk_org']], unit = unit)
      64          #--------------------------------------------------------
      65 -        def format(self):
      66                  lines = []
      67                  lines.append(_('Organization #%s') % self._payload[self._idx['pk_org']])
      68                  lines.append('')
      69                  lines.append(' %s "%s"' % (
      70                          self._payload[self._idx['l10n_category']],
      71                          self._payload[self._idx['organization']]
      72                  ))
      73                  if self._payload[self._idx['is_praxis']]:
      74                          lines.append('')
      75                          lines.append(' ' + _('This is your praxis !'))
      76                  return '\n'.join(lines)
      77          #--------------------------------------------------------
      78          # properties
      79          #--------------------------------------------------------
      80 -        def _get_units(self):
      81                  return get_org_units(order_by = 'unit', org = self._payload[self._idx['pk_org']])
      82
      83          units = property(_get_units, lambda x:x)
      84
      85  #------------------------------------------------------------
      86 -def org_exists(organization=None, category=None, link_obj=None):
      87          args = {'desc': organization, 'cat': category}
      88
      89          if isinstance(category, str):
      90                  cat_part = 'fk_category = (SELECT pk FROM dem.org_category WHERE description = %(cat)s)'
      91          elif category is None:
      92                  cat_part = 'True'
      93          else:
      94                  cat_part = 'fk_category = %(cat)s'
      95
      96          cmd = 'SELECT pk FROM dem.org WHERE description = %%(desc)s AND %s' % cat_part
      97          rows, idx = gmPG2.run_ro_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
      98          if len(rows) > 0:
      99                  return cOrg(aPK_obj = rows[0][0])
     100
     101          return None
     102  #------------------------------------------------------------
     103 -def create_org(organization=None, category=None, link_obj=None):
     104
     105          org = org_exists(link_obj = link_obj, organization = organization, category = category)
     106          if org is not None:
     107                  return org
     108
     109          args = {'desc': organization, 'cat': category}
     110
     111          if isinstance(category, str):
     112                  cat_part = '(SELECT pk FROM dem.org_category WHERE description = %(cat)s)'
     113          else:
     114                  cat_part = '%(cat)s'
     115
     116          cmd = 'INSERT INTO dem.org (description, fk_category) VALUES (%%(desc)s, %s) RETURNING pk' % cat_part
     117          rows, idx = gmPG2.run_rw_queries(link_obj = link_obj, queries = [{'cmd': cmd, 'args': args}], get_col_idx = False, return_data = True)
     118
     119          return cOrg(aPK_obj = rows[0][0], link_obj = link_obj)
     120  #------------------------------------------------------------
     121 -def delete_org(organization=None):
     122          args = {'pk': organization}
     123          cmd = """
     124                  DELETE FROM dem.org
     125                  WHERE
     126                          pk = %(pk)s
     127                          AND NOT EXISTS (
     128                                  SELECT 1 FROM dem.org_unit WHERE fk_org = %(pk)s
     129                          )
     130          """
     131          rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
     132          return True
     133  #------------------------------------------------------------
     134 -def get_orgs(order_by=None):
     135
     136          if order_by is None:
     137                  order_by = ''
     138          else:
     139                  order_by = 'ORDER BY %s' % order_by
     140
     141          cmd = _SQL_get_org % ('TRUE %s' % order_by)
     142          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True)
     143
     144          return [ cOrg(row = {'data': r, 'idx': idx, 'pk_field': 'pk_org'}) for r in rows ]
     145
     146  #============================================================
     147  # organizational units API
     148  #------------------------------------------------------------
     149  _SQL_get_org_unit = 'SELECT * FROM dem.v_org_units WHERE %s'
     150
     151 -class cOrgUnit(gmBusinessDBObject.cBusinessDBObject):
     152
     153          _cmd_fetch_payload = _SQL_get_org_unit % 'pk_org_unit = %s'
     154          _cmds_store_payload = [
     155                  """UPDATE dem.org_unit SET
     156                                  description = %(unit)s,
     157                                  fk_org = %(pk_org)s,
     158                                  fk_category = %(pk_category_unit)s,
     159                                  fk_address = %(pk_address)s
     160                          WHERE
     161                                  pk = %(pk_org_unit)s
     162                                          AND
     163                                  xmin = %(xmin_org_unit)s
     164                          RETURNING
     165                                  xmin AS xmin_org_unit"""
     166          ]
     167          _updatable_fields = [
     168                  'unit',
     169                  'pk_org',
     170                  'pk_category_unit',
     171                  'pk_address'
     172          ]
     173          #--------------------------------------------------------
     174          # comms API
     175          #--------------------------------------------------------
     176 -        def get_comm_channels(self, comm_medium=None):
     177
     178                  args = {'pk': self.pk_obj, 'medium': comm_medium}
     179
     180                  if comm_medium is None:
     181                          cmd = """
     182                                  SELECT *
     183                                  FROM dem.v_org_unit_comms
     184                                  WHERE
     185                                          pk_org_unit = %(pk)s
     186                          """
     187                  else:
     188                          cmd = """
     189                                  SELECT *
     190                                  FROM dem.v_org_unit_comms
     191                                  WHERE
     192                                          pk_org_unit = %(pk)s
     193                                                  AND
     194                                          comm_type = %(medium)s
     195                          """
     196                  rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
     197
     198                  return [ gmDemographicRecord.cOrgCommChannel(row = {
     199                                          'pk_field': 'pk_lnk_org_unit2comm',
     200                                          'data': r,
     201                                          'idx': idx
     202                                  }) for r in rows
     203                          ]
     204
     205          comm_channels = property(get_comm_channels, lambda x:x)
     206
     207          #--------------------------------------------------------
     208 -        def link_comm_channel(self, comm_medium=None, url=None, is_confidential=False, pk_channel_type=None):
     209                  """Link a communication medium with this org unit.
     210
     211                  @param comm_medium The name of the communication medium.
     212                  @param url The communication resource locator.
     213                  @type url A str instance.
     214                  @param is_confidential Wether the data must be treated as confidential.
     215                  @type is_confidential A bool instance.
     216                  """
     217                  return gmDemographicRecord.create_comm_channel (
     218                          comm_medium = comm_medium,
     219                          url = url,
     220                          is_confidential = is_confidential,
     221                          pk_channel_type = pk_channel_type,
     222                          pk_org_unit = self.pk_obj
     223                  )
     224          #--------------------------------------------------------
     225 -        def unlink_comm_channel(self, comm_channel=None):
     226                  gmDemographicRecord.delete_comm_channel (
     227                          pk = comm_channel['pk_lnk_org_unit2comm'],
     228                          pk_org_unit = self.pk_obj
     229                  )
     230          #--------------------------------------------------------
     231          # external IDs
     232          #--------------------------------------------------------
     233 -        def get_external_ids(self, id_type=None, issuer=None):
     234                  where_parts = ['pk_org_unit = %(unit)s']
     235                  args = {'unit': self.pk_obj}
     236
     237                  if id_type is not None:
     238                          where_parts.append('name = %(name)s')
     239                          args['name'] = id_type.strip()
     240
     241                  if issuer is not None:
     242                          where_parts.append('issuer = %(issuer)s')
     243                          args['issuer'] = issuer.strip()
     244
     245                  cmd = "SELECT * FROM dem.v_external_ids4org_unit WHERE %s" % ' AND '.join(where_parts)
     246                  rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
     247
     248                  return rows
     249
     250          external_ids = property(get_external_ids, lambda x:x)
     251          #--------------------------------------------------------
     252 -        def add_external_id(self, type_name=None, value=None, issuer=None, comment=None, pk_type=None):
     253                  """Adds an external ID to an org unit.
     254
     255                  creates ID type if necessary
     256                  """
     257                  args = {
     258                          'unit': self.pk_obj,
     259                          'val': value,
     260                          'type_name': type_name,
     261                          'pk_type': pk_type,
     262                          'issuer': issuer,
     263                          'comment': comment
     264                  }
     265                  # check for existing ID
     266                  if pk_type is not None:
     267                          cmd = """
     268                                  SELECT * FROM dem.v_external_ids4org_unit WHERE
     269                                  pk_org_unit = %(unit)s
     270                                          AND
     271                                  pk_type = %(pk_type)s
     272                                          AND
     273                                  value = %(val)s"""
     274                  else:
     275                          # by type/value/issuer
     276                          if issuer is None:
     277                                  cmd = """
     278                                          SELECT * FROM dem.v_external_ids4org_unit WHERE
     279                                          pk_org_unit = %(unit)s
     280                                                  AND
     281                                          name = %(type_name)s
     282                                                  AND
     283                                          value = %(val)s"""
     284                          else:
     285                                  cmd = """
     286                                          SELECT * FROM dem.v_external_ids4org_unit WHERE
     287                                          pk_org_unit = %(unit)s
     288                                                  AND
     289                                          name = %(type_name)s
     290                                                  AND
     291                                          value = %(val)s
     292                                                  AND
     293                                          issuer = %(issuer)s"""
     294                  rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
     295
     296                  # create new ID if not found
     297                  if len(rows) == 0:
     298                          if pk_type is None:
     299                                  cmd = """INSERT INTO dem.lnk_org_unit2ext_id (external_id, fk_type, comment, fk_org_unit) VALUES (
     300                                          %(val)s,
     301                                          (SELECT dem.add_external_id_type(%(type_name)s, %(issuer)s)),
     302                                          %(comment)s,
     303                                          %(unit)s
     304                                  )"""
     305                          else:
     306                                  cmd = """INSERT INTO dem.lnk_org_unit2ext_id (external_id, fk_type, comment, fk_org_unit) VALUES (
     307                                          %(val)s,
     308                                          %(pk_type)s,
     309                                          %(comment)s,
     310                                          %(unit)s
     311                                  )"""
     312                          rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
     313
     314                  # or update comment of existing ID
     315                  else:
     316                          row = rows[0]
     317                          if comment is not None:
     318                                  # comment not already there ?
     319                                  if gmTools.coalesce(row['comment'], '').find(comment.strip()) == -1:
     320                                          comment = '%s%s' % (gmTools.coalesce(row['comment'], '', '%s // '), comment.strip)
     321                                          cmd = "UPDATE dem.lnk_org_unit2ext_id SET comment = %(comment)s WHERE pk = %(pk)s"
     322                                          args = {'comment': comment, 'pk': row['pk_id']}
     323                                          rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
     324
     325          #--------------------------------------------------------
     326 -        def update_external_id(self, pk_id=None, type=None, value=None, issuer=None, comment=None):
     327                  """Edits an existing external ID.
     328
     329                  Creates ID type if necessary.
     330                  """
     331                  cmd = """
     332                          UPDATE dem.lnk_org_unit2ext_id SET
     333                                  fk_type = (SELECT dem.add_external_id_type(%(type)s, %(issuer)s)),
     334                                  external_id = %(value)s,
     335                                  comment = gm.nullify_empty_string(%(comment)s)
     336                          WHERE
     337                                  pk = %(pk)s
     338                  """
     339                  args = {'pk': pk_id, 'value': value, 'type': type, 'issuer': issuer, 'comment': comment}
     340                  rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
     341
     342          #--------------------------------------------------------
     343 -        def delete_external_id(self, pk_ext_id=None):
     344                  cmd = """
     345                          DELETE FROM dem.lnk_org_unit2ext_id
     346                          WHERE fk_org_unit = %(unit)s AND pk = %(pk)s
     347                  """
     348                  args = {'unit': self.pk_obj, 'pk': pk_ext_id}
     349                  gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
     350
     351          #--------------------------------------------------------
     352          # address API
     353          #--------------------------------------------------------
     354 -        def link_address(self, id_type=None, address=None):
     355                  self.address = address
     356                  return address
     357          #--------------------------------------------------------
     358 -        def unlink_address(self, address=None, pk_address=None):
     359                  """Remove an address from the org unit.
     360
     361                  The address itself remains in the database.
     362                  The address can be either cAdress or cPatientAdress.
     363                  """
     364                  self.address = None
     365          #--------------------------------------------------------
     366 -        def format(self, with_address=False, with_org=True, with_comms=False):
     367                  lines = []
     368                  lines.append(_('Unit%s: %s%s') % (
     369                          gmTools.bool2subst (
     370                                  self._payload[self._idx['is_praxis_branch']],
     371                                  _(' (of your praxis)'),
     372                                  ''
     373                          ),
     374                          self._payload[self._idx['unit']],
     375                          gmTools.coalesce(self._payload[self._idx['l10n_unit_category']], '', ' (%s)')
     376                  ))
     377                  if with_org:
     378                          lines.append(_('Organization: %s (%s)') % (
     379                                  self._payload[self._idx['organization']],
     380                                  self._payload[self._idx['l10n_organization_category']]
     381                          ))
     382                  if with_address:
     383                          adr = self.address
     384                          if adr is not None:
     385                                  lines.extend(adr.format())
     386                  if with_comms:
     387                          for comm in self.comm_channels:
     388                                  lines.append('%s: %s%s' % (
     389                                          comm['l10n_comm_type'],
     390                                          comm['url'],
     391                                          gmTools.bool2subst(comm['is_confidential'], _(' (confidential)'), '', '')
     392                                  ))
     393                  return lines
     394
     395          #--------------------------------------------------------
     396          # properties
     397          #--------------------------------------------------------
     398 -        def _get_address(self):
     399                  if self._payload[self._idx['pk_address']] is None:
     400                          return None
     401                  return gmDemographicRecord.cAddress(aPK_obj = self._payload[self._idx['pk_address']])
     402
     403 -        def _set_address(self, address):
     404                  self['pk_address'] = address['pk_address']
     405                  self.save()
     406
     407          address = property(_get_address, _set_address)
     408
     409          #--------------------------------------------------------
     410 -        def _get_org(self):
     411                  return cOrg(aPK_obj = self._payload[self._idx['pk_org']])
     412
     413          organization = property(_get_org, lambda x:x)
     414          org = property(_get_org, lambda x:x)
     415
     416          comm_channels = property(get_comm_channels, lambda x:x)
     417
     418  #------------------------------------------------------------
     419 -def create_org_unit(pk_organization=None, unit=None, link_obj=None):
     420          _log.debug('creating org unit [%s:%s]', unit, pk_organization)
     421          args = {'desc': unit, 'pk_org': pk_organization}
     422          cmd1 = """
     423                  INSERT INTO dem.org_unit (description, fk_org) SELECT
     424                          %(desc)s,
     425                          %(pk_org)s
     426                  WHERE NOT EXISTS (
     427                          SELECT 1 FROM dem.org_unit WHERE description = %(desc)s AND fk_org = %(pk_org)s
     428                  )"""
     429          cmd2 = _SQL_get_org_unit % 'unit = %(desc)s AND pk_org = %(pk_org)s'
     430          queries = [
     431                  {'cmd': cmd1, 'args': args},
     432                  {'cmd': cmd2, 'args': args}
     433          ]
     434          rows, idx = gmPG2.run_rw_queries(link_obj = link_obj, queries = queries, get_col_idx = True, return_data = True)
     435          return cOrgUnit(row = {'data': rows[0], 'idx': idx, 'pk_field': 'pk_org_unit'})
     436
     437  #------------------------------------------------------------
     438 -def delete_org_unit(unit=None):
     439          args = {'pk': unit}
     440          cmd = """DELETE FROM dem.org_unit WHERE
     441                  pk = %(pk)s
     442                          AND
     443                  NOT EXISTS (
     444                          SELECT 1 FROM clin.encounter where fk_location = %(pk)s
     445                  )       AND
     446                  NOT EXISTS (
     447                          SELECT 1 FROM clin.hospital_stay where fk_org_unit = %(pk)s
     448                  )       AND
     449                  NOT EXISTS (
     450                          SELECT 1 FROM clin.procedure where fk_org_unit = %(pk)s
     451                  )       AND
     452                  NOT EXISTS (
     453                          SELECT 1 FROM clin.test_org where fk_org_unit = %(pk)s
     454                  )       AND
     455                  NOT EXISTS (
     456                          SELECT 1 FROM dem.lnk_org_unit2comm where fk_org_unit = %(pk)s
     457                  )       AND
     458                  NOT EXISTS (
     459                          SELECT 1 FROM dem.lnk_org_unit2ext_id where fk_org_unit = %(pk)s
     460                  )
     461          """
     462          rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
     463          return True
     464  #------------------------------------------------------------
     465 -def get_org_units(order_by=None, org=None):
     466
     467          if order_by is None:
     468                  order_by = ''
     469          else:
     470                  order_by = ' ORDER BY %s' % order_by
     471
     472          if org is None:
     473                  where_part = 'TRUE'
     474          else:
     475                  where_part = 'pk_org = %(org)s'
     476
     477          args = {'org': org}
     478          cmd = (_SQL_get_org_unit % where_part) + order_by
     479          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
     480
     481          return [ cOrgUnit(row = {'data': r, 'idx': idx, 'pk_field': 'pk_org_unit'}) for r in rows ]
     482
     483  #======================================================================
     484  # main
     485  #----------------------------------------------------------------------
     486  if __name__ == "__main__":
     487
     488          if len(sys.argv) < 2:
     489                  sys.exit()
     490
     491          if sys.argv[1] != 'test':
     492                  sys.exit()
     493
     494
     495          print(cOrgUnit(aPK_obj = 21825))
     496
     497
     498  #       for unit in get_org_units():
     499  #               print unit
     500
     501          sys.exit(0)
     502  #============================================================
     503  #============================================================
     504  # outdated code below =======================================
     505  #============================================================
     506  #============================================================
     507  #============================================================
     508  #============================================================
     509  #============================================================
     510  #============================================================
     511  #============================================================
     512  #============================================================
     513  #============================================================
     514 -def get_comm_channels_data_for_org_ids( idList):
     515          """gets comm_channels for a list of org_id.
     516          returns a map keyed by org_id with lists of comm_channel data (url, type).
     517          this allows a single fetch of comm_channel data for multiple orgs"""
     518
     519          ids = ", ".join( [ str(x) for x in idList])
     520          cmd = """select l.id_org, id_type, url
     521                          from dem.comm_channel c, dem.lnk_org2comm_channel l
     522                          where
     523                                  c.id = l.id_comm and
     524                                  l.id_org in ( select id from dem.org where id in (%s) )
     525                  """ % ids
     526          result = gmPG.run_ro_query("personalia", cmd)
     527          if result == None:
     528                  _log.error("Unable to load comm channels for org" )
     529                  return None
     530          m = {}
     531          for (id_org, id_type, url) in result:
     532                  if id_org not in m:
     533                          m[id_org] = []
     534                  m[id_org].append( (id_type, url) )
     535
     536          return m # is a Map[id_org] = list of comm_channel data
     537
     538 -def get_address_data_for_org_ids( idList):
     539          """gets addresses for a list of valid id values for orgs.
     540          returns a map keyed by org_id with the address data
     541          """
     542
     543          ids = ", ".join( [ str(x) for x in idList])
     544          cmd = """select l.id_org, number, street, city, postcode, region, country
     545                          from dem.v_basic_address v , dem.lnk_org2address l
     546                                  where v.addr_id = l.id_address and
     547                                  l.id_org in ( select id from dem.org where id in (%s) ) """ % ids
     548          result = gmPG.run_ro_query( "personalia", cmd)
     549
     550          if result == None:
     551                  _log.error("failure in org address load" )
     552                  return None
     553          m = {}
     554          for (id_org, n,s,ci,p,st,co) in result:
     555                  m[id_org] =  (n,s,ci,p,st,co)
     556          return m
     557
     558 -def get_org_data_for_org_ids(idList):
     559          """ for a given list of org id values ,
     560                  returns a map of id_org vs. org attributes: description, id_category"""
     561
     562          ids = ", ".join( [ str(x) for x in idList])
     563          cmd = """select id, description, id_category  from dem.org
     564                          where id in ( select id from dem.org where id in( %s) )""" % ids
     565          #<DEBUG>
     566          print(cmd)
     567          #</DEBUG>
     568          result = gmPG.run_ro_query("personalia", cmd, )
     569          if result is None:
     570                  _log.error("Unable to load orgs with ids (%s)" %ids)
     571                  return None
     572          m = {}
     573          for (id_org, d, id_cat) in result:
     574                  m[id_org] = (d, id_cat)
     575          return m
     576  #============================================================
     577  #
     578  #  IGNORE THE FOLLOWING, IF NOT INTERESTED IN TEST CODE
     579  #
     580  #
     581
     582  if __name__ == '__main__':
     583          print("Please enter a write-enabled user e.g. _test-doc ")
     584
     585 -        def testListOrgs():
     586                  print("running test listOrg")
     587                  for (f,a) in get_test_data():
     588                          h = cOrgImpl1()
     589                          h.set(*f)
     590                          h.setAddress(*a)
     591                          if not h.save():
     592                                  print("did not save ", f)
     593
     594                  orgs = cOrgHelperImpl1().findAllOrganizations()
     595
     596                  for org in orgs:
     597                          print("Found org ", org.get(), org.getAddress())
     598                          if not org.shallow_del():
     599                                  print("Unable to delete above org")
     600
     601
     602
     603
     604
     605
     606 -        def get_test_data():
     607                  """test org data for unit testing in testOrg()"""
     608                  return [
     609                                  ( ["Box Hill Hospital", "", "", "Eastern", "hospital", "0398953333", "111-1111","bhh@oz", ""],  ["33", "Nelson Rd", "Box Hill", "3128", None , None] ),
     610                                  ( ["Frankston Hospital", "", "", "Peninsula", "hospital", "0397847777", "03784-3111","fh@oz", ""],  ["21", "Hastings Rd", "Frankston", "3199", None , None] )
     611                          ]
     612
     613 -        def get_test_persons():
     614                  return { "Box Hill Hospital":
     615                                  [
     616                                  ['Dr.', 'Bill' , 'Smith', '123-4567', '0417 111 222'],
     617                                  ['Ms.', 'Anita', 'Jones', '124-5544', '0413 222 444'],
     618                                  ['Dr.', 'Will', 'Stryker', '999-4444', '0402 333 111']  ],
     619                          "Frankston Hospital":
     620                                  [ [ "Dr.", "Jason", "Boathead", "444-5555", "0403 444 2222" ],
     621                                  [ "Mr.", "Barnie", "Commuter", "222-1111", "0444 999 3333"],
     622                                  [ "Ms.", "Morita", "Traveller", "999-1111", "0222 333 1111"]] }
     623
     624 -        def testOrgPersons():
     625                  m = get_test_persons()
     626                  d  = dict(  [  (f[0] , (f, a)) for (f, a) in get_test_data() ] )
     627                  for orgName , personList in m.items():
     628                          f1 , a1 = d[orgName][0], d[orgName][1]
     629                          _testOrgClassPersonRun( f1, a1, personList, cOrgImpl1)
     630                          _testOrgClassPersonRun( f1, a1, personList, cCompositeOrgImpl1)
     631                          _testOrgClassPersonRun( f1, a1, personList, cOrgHelperImpl1().create)
     632                          _testOrgClassPersonRun( f1, a1, personList, cOrgHelperImpl2().create)
     633                          _testOrgClassPersonRun( f1, a1, personList, cOrgHelperImpl3().create)
     634                          _testOrgClassPersonRun( f1, a1, personList, cOrgHelperImpl3().create, getTestIdentityUsing_cOrgDemographicAdapter)
     635
     636
     637 -        def _outputPersons( org):
     638                  m = org.getPersonMap()
     639
     640                  if m== []:
     641                          print("NO persons were found unfortunately")
     642
     643                  print(""" TestOrgPersonRun got back for """)
     644                  a = org.getAddress()
     645                  print(org["name"], a["number"], a["street"], a["urb"], a["postcode"] , " phone=", org['phone'])
     646
     647                  for id, r in m.items():
     648                          print("\t",", ".join( [ " ".join(r.get_names().values()),
     649                                                  "work no=", r.getCommChannel(gmDemographicRecord.WORK_PHONE),
     650                                                  "mobile no=", r.getCommChannel(gmDemographicRecord.MOBILE)
     651                                                  ] ))
     652
     653
     654 -        def _testOrgPersonRun(f1, a1, personList):
     655                  print("Using test data :f1 = ", f1, "and a1 = ", a1 , " and lp = ", personList)
     656                  print("-" * 50)
     657                  _testOrgClassPersonRun( f1, a1, personList, cOrgImpl1)
     658                  _testOrgClassPersonRun( f1, a1, personList, cCompositeOrgImpl1)
     659                  _testOrgClassPersonRun( f1, a1, personList, cOrgHelperImpl1().create)
     660                  _testOrgClassPersonRun( f1, a1, personList, cOrgHelperImpl2().create)
     661
     662
     663 -        def _setIdentityTestData(identity, data):
     664                  identity.addName(data[1], data[2], True)
     665                  identity.setTitle(data[0])
     666                  identity.linkCommChannel( gmDemographicRecord.WORK_PHONE, data[3])
     667                  identity.linkCommChannel( gmDemographicRecord.MOBILE, data[4])
     668
     669 -        def getTestIdentityUsingDirectDemographicRecord( data, org):
     670                  id = gmPerson.create_dummy_identity()
     671                  identity = gmDemographicRecord.cDemographicRecord_SQL(id)
     672                  _setIdentityTestData(identity, data)
     673                  return identity
     674
     675 -        def getTestIdentityUsing_cOrgDemographicAdapter( data, org):
     676                  helper = cOrgHelperImpl3()
     677                  orgPerson= helper.createOrgPerson()
     678                  orgPerson.setParent(org)
     679                  orgPerson['name'] = ' '.join( [data[0], data[1], data[2]])
     680                  orgPerson['phone'] = data[3]
     681                  orgPerson['mobile'] = data[4]
     682                  orgPerson.save()
     683                  return orgPerson.getDemographicRecord()
     684
     685
     686 -        def _testOrgClassPersonRun(f1, a1, personList, orgCreate, identityCreator = getTestIdentityUsingDirectDemographicRecord):
     687                  print("-" * 50)
     688                  print("Testing org creator ", orgCreate)
     689                  print(" and identity creator ", identityCreator)
     690                  print("-" * 50)
     691                  h = orgCreate()
     692                  h.set(*f1)
     693                  h.setAddress(*a1)
     694                  if not h.save():
     695                          print("Unable to save org for person test")
     696                          h.shallow_del()
     697                          return False
     698                  # use gmDemographicRecord to convert person list
     699                  for lp in personList:
     700                          identity = identityCreator(lp, h)
     701                          result , msg = h.linkPerson(identity)
     702                          print(msg)
     703
     704                  _outputPersons(h)
     705                  deletePersons(h)
     706
     707                  if h.shallow_del():
     708                          print("Managed to dispose of org")
     709                  else:
     710                          print("unable to dispose of org")
     711
     712                  return True
     713
     714  #       def testOrgPerson(f1, a1, personList):
     715
     716 -        def deletePerson(id):
     717                  cmds = [ ( "delete from dem.lnk_identity2comm_chan where fk_identity=%d"%id,[]),
     718                          ("delete from dem.names where id_identity=%d"%id,[]),
     719                          ("delete from dem.identity where id = %d"%id,[]) ]
     720                  result = gmPG.run_commit("personalia", cmds)
     721                  return result
     722
     723 -        def deletePersons( org):
     724                  map = org.getPersonMap()
     725                  for id, r in map.items():
     726                          org.unlinkPerson(r)
     727
     728                          result = deletePerson(r.getID())
     729                          if result == None:
     730                                  _log.error("FAILED TO CLEANUP PERSON %d" %r.getID() )
     731
     732
     733
     734 -        def testOrg():
     735                  """runs a test of load, save , shallow_del  on items in from get_test_data"""
     736                  l = get_test_data()
     737                  results = []
     738                  for (f, a) in l:
     739                          result, obj =   _testOrgRun(f, a)
     740                          results.append( (result, obj) )
     741                  return results
     742
     743
     744
     745 -        def _testOrgRun( f1, a1):
     746
     747                  print("""testing single level orgs""")
     748                  f = [ "name", "office", "subtype",  "memo", "category", "phone", "fax", "email","mobile"]
     749                  a = ["number", "street", "urb", "postcode", 'region', "country"]
     750                  h = cOrgImpl1()
     751
     752                  h.set(*f1)
     753                  h.setAddress(*a1)
     754
     755                  print("testing get, getAddress")
     756                  print(h.get())
     757                  print(h.getAddressDict())
     758
     759                  import sys
     760                  if not  h.save():
     761                          print("failed to save first time. Is an old test org needing manual removal?")
     762                          return False, h
     763                  print("saved pk =", h.getId())
     764
     765
     766                  pk = h.getId()
     767                  if h.shallow_del():
     768                          print("shallow deleted ", h['name'])
     769                  else:
     770                          print("failed shallow delete of ", h['name'])
     771
     772
     773
     774                  h2 = cOrgImpl1()
     775
     776                  print("testing load")
     777
     778                  print("should fail")
     779                  if not h2.load(pk):
     780                          print("Failed as expected")
     781
     782                  if h.save():
     783                          print("saved ", h['name'] , "again")
     784                  else:
     785                          print("failed re-save")
     786                          return False, h
     787
     788                  h['fax'] = '222-1111'
     789                  print("using update save")
     790
     791                  if h.save():
     792                          print("saved updated passed")
     793                          print("Test reload next")
     794                  else:
     795                          print("failed save of updated data")
     796                          print("continuing to reload")
     797
     798
     799                  if not h2.load(h.getId()):
     800                          print("failed load")
     801                          return False, h
     802                  print("reloaded values")
     803                  print(h2.get())
     804                  print(h2.getAddressDict())
     805
     806                  print("** End of Test org")
     807
     808                  if h2.shallow_del():
     809                          print("cleaned up")
     810                  else:
     811                          print("Test org needs to be manually removed")
     812
     813                  return True, h2
     814
     815 -        def clean_test_org():
     816                  l = get_test_data()
     817
     818                  names = [ "".join( ["'" ,str(org[0]), "'"] )  for ( org, address) in l]
     819                  names += [ "'John Hunter Hospital'", "'Belmont District Hospital'"]
     820                  nameList = ",".join(names)
     821                  categoryList = "'hospital'"
     822
     823                  cmds = [ ( """create temp table del_org as
     824                                  select id  from dem.org
     825                                  where description in(%s) or
     826                                  id_category in ( select id from dem.org_category c
     827                                                          where c.description in (%s))
     828                          """ % (nameList, categoryList), [] ),
     829                          ("""create temp table del_identity as
     830                          select id  from dem.identity
     831                          where id in
     832                                  (
     833                                          select id_identity from dem.lnk_person_org_address
     834                                          where id_org in ( select id from del_org)
     835                                  )""",[] ),
     836                          ("""create temp table del_comm as
     837                          (select id_comm from dem.lnk_org2comm_channel where
     838                                  id_org in ( select id from del_org)
     839                          ) UNION
     840                          (select id_comm from dem.lnk_identity2comm_chan where
     841                                  id_identity in ( select id from del_identity)
     842                          )""", [] ),
     843                          ("""delete from dem.names where id_identity in
     844                                          (select id from del_identity)""",[]),
     845                          ("""delete from dem.lnk_person_org_address where
     846                                          id_org in (select id from del_org )""",[]),
     847                          ("""delete from dem.lnk_person_org_address where
     848                                          id_identity in (select id from del_identity)""", []),
     849                          ("""delete from dem.lnk_org2comm_channel
     850                          where id_org in (select id from del_org) """,[]),
     851                          ("""delete from dem.lnk_identity2comm_chan
     852                                          where id_identity in (select id from del_identity)""",[] ),
     853                          ("""delete from dem.comm_channel where id in ( select id_comm from del_comm)""",[]),
     854                          ("""delete from dem.lnk_job2person where id_identity in (select id from del_identity)""", []),
     855                          ("""delete from dem.identity where id in (select id from del_identity)""",[] ),
     856                          ("""delete from dem.org where id in ( select id from del_org) """ , [] ),
     857                          ("""drop table del_comm""",[]),
     858                          ("""drop table del_identity""",[]),
     859                          ("""drop table del_org""", [])
     860
     861                          ]
     862                  result = (gmPG.run_commit("personalia", cmds) is not None)
     863
     864                  return result
     865
     866
     867 -        def login_user_and_test(logintest, service = 'personalia', msg = "failed test" , use_prefix_rw= False):
     868                  """ tries to get and verify a read-write connection
     869                  which has permission to write to org tables, so the test case
     870                  can run.
     871                  """
     872                  login2 = gmPG.request_login_params()
     873
     874                  #login as the RW user
     875                  p = gmPG.ConnectionPool( login2)
     876                  if use_prefix_rw:
     877                          conn = p.GetConnection( service, readonly = 0)
     878                  else:
     879                          conn = p.GetConnection(service)
     880                  result = logintest(conn)
     881
     882                  if result is False:
     883                          print(msg)
     884
     885                  p.ReleaseConnection(service)
     886                  return result, login2
     887
     888 -        def test_rw_user(conn):
     889                  # test it is a RW user, by making a entry and deleting it
     890                  try:
     891                          c.reload("org_category")
     892                          cursor = conn.cursor()
     893
     894                          cursor.execute("select last_value from dem.org_id_seq")
     895                          [org_id_seq] = cursor.fetchone()
     896
     897                          cursor.execute("""
     898                  insert into dem.org ( description, id_category, id)
     899                  values ( 'xxxDEFAULTxxx', %d,
     900                  %d)
     901                          """ % ( c.getId('org_category', 'hospital') , org_id_seq + 1 ) )
     902                          cursor.execute("""
     903                  delete from dem.org where id = %d""" % ( org_id_seq + 1) )
     904                  # make sure this exercise is committed, else a deadlock will occur
     905                          conn.commit()
     906                  except:
     907                          _log.exception("Test of Update Permission failed")
     908                          return False
     909                  return True
     910
     911 -        def test_admin_user(conn):
     912                  try:
     913                          cursor = conn.cursor()
     914
     915                          cursor.execute("select last_value from dem.org_category_id_seq")
     916                          [org_cat_id_seq] = cursor.fetchone()
     917
     918                          cursor.execute("""
     919                  insert into dem.org_category ( description, id)
     920                  values ( 'xxxDEFAULTxxx',%d)
     921                          """ %   (org_cat_id_seq + 1 ) )
     922                          cursor.execute("""
     923                  delete from dem.org_category where description like 'xxxDEFAULTxxx' """ )
     924                  # make sure this exercise is committed, else a deadlock will occur
     925                          conn.commit()
     926                  except:
     927                          _log.exception("Test of Update Permission failed")
     928                          return False
     929                  return True
     930
     931 -        def login_rw_user():
     932                  return  login_user_and_test( test_rw_user, "login cannot update org", use_prefix_rw = True)
     933
     934
     935 -        def login_admin_user():
     936                  return  login_user_and_test( test_admin_user, "login cannot update org_category" )
     937
     938
     939 -        def create_temp_categories( categories = ['hospital']):
     940                  print("NEED TO CREATE TEMPORARY ORG_CATEGORY.\n\n ** PLEASE ENTER administrator login  : e.g  user 'gm-dbo' and  his password")
     941                  #get a admin login
     942                  for i in range(0, 4):
     943                          result ,tmplogin = login_admin_user()
     944                          if result:
     945                                  break
     946                  if i == 4:
     947                          print("Failed to login")
     948                          return categories
     949
     950                  # and save it , for later removal of test categories.
     951                  from Gnumed.pycommon import gmLoginInfo
     952                  adminlogin = gmLoginInfo.LoginInfo(*tmplogin.GetInfo())
     953
     954                  #login as admin
     955                  p = gmPG.ConnectionPool( tmplogin)
     956                  conn = p.GetConnection("personalia")
     957
     958                  # use the last value + 1 of the relevant sequence, but don't increment it
     959                  cursor = conn.cursor()
     960
     961                  failed_categories = []
     962                  n =1
     963                  for cat in categories:
     964                          cursor.execute("select last_value from dem.org_category_id_seq")
     965                          [org_cat_id_seq] = cursor.fetchone()
     966
     967                          cursor.execute( "insert into dem.org_category(description, id) values('%s', %d)" % (cat, org_cat_id_seq + n) )
     968                          cursor.execute("select id from dem.org_category where description in ('%s')" % cat)
     969
     970                          result =  cursor.fetchone()
     971                          if result == None or len(result) == 0:
     972                                  failed_categories.append(cat)
     973                                  print("Failed insert of category", cat)
     974                                  conn.rollback()
     975                          else:
     976                                  conn.commit()
     977                          n += 1
     978
     979                  conn.commit()
     980                  p.ReleaseConnection('personalia')
     981                  return failed_categories, adminlogin
     982
     983 -        def clean_org_categories(adminlogin = None, categories = ['hospital'], service='personalia'):
     984
     985                  print("""
     986
     987                  The temporary category(s) will now
     988                  need to be removed under an administrator login
     989                  e.g. gm-dbo
     990                  Please enter login for administrator:
     991                  """)
     992                  if adminlogin is None:
     993                          for i in range(0, 4):
     994                                  result, adminlogin = login_admin_user()
     995                                  if  result:
     996                                          break
     997                          if i == 4:
     998                                  print("FAILED TO LOGIN")
     999                                  return categories
    1000
    1001                  p = gmPG.ConnectionPool(adminlogin)
    1002                  conn = p.GetConnection(service)
    1003                  failed_remove = []
    1004                  for cat in categories:
    1005                          try:
    1006                                  cursor = conn.cursor()
    1007                                  cursor.execute( "delete from  dem.org_category where description in ('%s')"%cat)
    1008                                  conn.commit()
    1009                                  cursor.execute("select id from dem.org_category where description in ('%s')"%cat)
    1010                                  if cursor.fetchone() == None:
    1011                                          print("Succeeded in removing temporary org_category")
    1012                                  else:
    1013                                          print("*** Unable to remove temporary org_category")
    1014                                          failed_remove .append(cat)
    1015                          except:
    1016                                  import sys
    1017                                  print(sys.exc_info()[0], sys.exc_info()[1])
    1018                                  import traceback
    1019                                  traceback.print_tb(sys.exc_info()[2])
    1020
    1021                                  failed_remove.append(cat)
    1022
    1023                  conn = None
    1024                  p.ReleaseConnection(service)
    1025                  if failed_remove != []:
    1026                          print("FAILED TO REMOVE ", failed_remove)
    1027                  return failed_remove
    1028
    1029 -        def test_CatFinder():
    1030                  print("TESTING cCatFinder")
    1031
    1032                  print("""c = cCatFinder("org_category")""")
    1033                  c = cCatFinder("org_category")
    1034
    1035                  print(c.getCategories("org_category"))
    1036
    1037                  print("""c = cCatFinder("enum_comm_types")""")
    1038                  c = cCatFinder("enum_comm_types")
    1039
    1040                  l = c.getCategories("enum_comm_types")
    1041                  print("testing getId()")
    1042                  l2 = []
    1043                  for x in l:
    1044                          l2.append((x, c.getId("enum_comm_types", x)))
    1045                  print(l2)
    1046
    1047                  print("""testing borg behaviour of cCatFinder""")
    1048
    1049                  print(c.getCategories("org_category"))
    1050
    1051
    1052 -        def help():
    1053                  print("""\nNB If imports not found , try:
    1054
    1055                  change to gnumed/client directory , then
    1056
    1057                  export PYTHONPATH=$PYTHONPATH:../;python business/gmOrganization.py
    1058
    1059                          --clean , cleans the test data and categories
    1060
    1061                          --gui   sets up as for no arguments, then runs the client.
    1062                                  on normal exit of client, normal tests run, and
    1063                                  then cleanup of entered data.
    1064
    1065                          using the gui,
    1066
    1067                          the 'list organisations' toolbar button , loads all organisations
    1068                          in the database, and display suborgs and persons associated
    1069                          with each organisation.
    1070
    1071                          the 'add organisation' button will add a top-level organisation.
    1072                          the 'add branch/division' button will work when the last selected
    1073                          org was a top level org.
    1074
    1075                          the 'add person M|F' button works if an org is selected.
    1076
    1077                          the save button works when entry is finished.
    1078
    1079                          selecting on an item, will bring it into the editing area.
    1080
    1081                          No test yet for dirtied edit data, to query whether to
    1082                          save or discard. (30/5/2004)
    1083                  """)
    1084                  print()
    1085                  print("In the connection query, please enter")
    1086                  print("a WRITE-ENABLED user e.g. _test-doc (not test-doc), and the right password")
    1087                  print()
    1088                  print("Run the unit test with cmdline argument '--clean'  if trying to clean out test data")
    1089                  print()
    1090
    1091                  print("""You can get a sermon by running
    1092                  export PYTHONPATH=$PYTHONPATH:../;python business/gmOrganization.py --sermon
    1093                  """)
    1094                  print("""
    1095                  Pre-requisite data in database is :
    1096                  gnumed=# select * from org_category ;
    1097                  id | description
    1098                  ----+-------------
    1099                  1 | hospital
    1100                  (1 row)
    1101
    1102                  gnumed=# select * from enum_comm_types ;
    1103                  id | description
    1104                  ----+-------------
    1105                  1 | email
    1106                  2 | fax
    1107                  3 | homephone
    1108                  4 | workphone
    1109                  5 | mobile
    1110                  6 | web
    1111                  7 | jabber
    1112                  (7 rows)
    1113                  """)
    1114
    1115 -        def sermon():
    1116                                  print("""
    1117                  This test case shows how many things can go wrong , even with just a test case.
    1118                  Problem areas include:
    1119                  - postgres administration :  pg_ctl state, pg_hba.conf, postgres.conf  config files .
    1120                  - schema integrity constraints : deletion of table entries which are subject to foreign keys, no input for no default value and no null value columns, input with duplicated values where unique key constraint applies to non-primary key columns, dealing with access control by connection identity management.
    1121
    1122
    1123                  - efficiency trade-offs -e.g. using db objects for localising code with data and easier function call interface ( then hopefully, easier to program with) , vs. need to access many objects at once
    1124                  without calling the backend for each object.
    1125
    1126                  - error and exception handling - at what point in the call stack to handle an error.
    1127                  Better to use error return values and log exceptions near where they occur, vs. wrapping inside try: except: blocks and catching typed exceptions.
    1128
    1129
    1130                  - test-case construction:  test data is needed often, and the issue
    1131                  is whether it is better to keep the test data volatile in the test-case,
    1132                  which handles both its creation and deletion, or to add it to test data
    1133                  server configuration files, which may involve running backend scripts
    1134                  for loading and removing test data.
    1135
    1136
    1137
    1138                  - Database connection problems:
    1139                  -Is the problem in :
    1140                          - pg_ctl start -D  /...mydata-directory is wrong, and gnumed isn't existing there.
    1141
    1142                          - ..mydata-directory/pg_hba.conf
    1143                                  - can psql connect locally and remotely with the username and password.
    1144                                  - Am I using md5 authenentication and I've forgotten the password.
    1145                                          - I need to su postgres, alter pg_hba.conf to use trust for
    1146                                          the gnumed database, pg_ctl restart -D .., su normal_user,  psql gnumed, alter user my_username password 'doh'
    1147                                          - might be helpful: the default password for _test-doc is test-doc
    1148
    1149                          - ../mydata-directory/postgres.conf
    1150                                  - tcp connect  flag isn't set to true
    1151
    1152                          - remote/local mixup :
    1153                          a different set of user passwords on different hosts. e.g the password
    1154                          for _test-doc is 'pass' on localhost and 'test-doc' for the serverhost.
    1155                          - In the prompts for admin and user login, local host was used for one, and
    1156                          remote host for the other
    1157
    1158
    1159
    1160                  - test data won't go away :
    1161                  - 'hospital' category in org_category : the test case failed in a previous run
    1162                  and the test data was left there; now the test case won't try to delete it
    1163                  because it exists as a pre-existing category;
    1164                          soln : run with  --clean  option
    1165
    1166                  - test-case failed unexpectedly, or break key was hit in the middle of a test-case run.
    1167                          Soln: run with --clean option,
    1168
    1169
    1170                  """)
    1171
    1172
    1173  #============================================================
    1174
    1175          import sys
    1176          testgui = False
    1177          if len(sys.argv) > 1:
    1178                  if sys.argv[1] == '--clean':
    1179                          result = clean_test_org()
    1180                          p = gmPG.ConnectionPool()
    1181                          p.ReleaseConnection('personalia')
    1182                          if result:
    1183                                  print("probably succeeded in cleaning orgs")
    1184                          else:   print("failed to clean orgs")
    1185
    1186                          clean_org_categories()
    1187                          sys.exit(1)
    1188
    1189                  if sys.argv[1] == "--sermon":
    1190                          sermon()
    1191
    1192                  if sys.argv[1] == "--help":
    1193                          help()
    1194
    1195                  if sys.argv[1] =="--gui":
    1196                          testgui = True
    1197
    1198          print("*" * 50)
    1199          print("RUNNING UNIT TEST of gmOrganization ")
    1200
    1201
    1202          test_CatFinder()
    1203          tmp_category = False  # tmp_category means test data will need to be added and removed
    1204                          # for  org_category .
    1205
    1206          c = cCatFinder()
    1207          if not "hospital" in c.getCategories("org_category") :
    1208                  print("FAILED in prerequisite for org_category : test categories are not present.")
    1209
    1210                  tmp_category = True
    1211
    1212          if tmp_category:
    1213                  # test data in a categorical table (restricted access) is needed
    1214
    1215                  print("""You will need to switch login identity to database administrator in order
    1216                          to have permission to write to the org_category table,
    1217                          and then switch back to the ordinary write-enabled user in order
    1218                          to run the test cases.
    1219                          Finally you will need to switch back to administrator login to
    1220                          remove the temporary org_categories.
    1221                          """)
    1222                  categories = ['hospital']
    1223                  result, adminlogin = create_temp_categories(categories)
    1224                  if result == categories:
    1225                          print("Unable to create temporary org_category. Test aborted")
    1226                          sys.exit(-1)
    1227                  if result != []:
    1228                          print("UNABLE TO CREATE THESE CATEGORIES")
    1229                          if not input("Continue ?") in ['y', 'Y'] :
    1230                                  sys.exit(-1)
    1231
    1232          try:
    1233                  results = []
    1234                  if tmp_category:
    1235                                  print("succeeded in creating temporary org_category")
    1236                                  print()
    1237                                  print("** Now ** RESUME LOGIN **  of write-enabled user (e.g. _test-doc) ")
    1238                                  while (1):
    1239                                          # get the RW user for org tables (again)
    1240                                          if login_rw_user():
    1241                                                  break
    1242
    1243                  if testgui:
    1244                          if cCatFinder().getId('org_category','hospital') == None:
    1245                                  print("Needed to set up temporary org_category 'hospital")
    1246                                  sys.exit(-1)
    1247                          import os
    1248                          print(os.environ['PWD'])
    1249                          os.spawnl(os.P_WAIT, "/usr/bin/python", "/usr/bin/python","wxpython/gnumed.py", "--debug")
    1250
    1251                          #os.popen2('python client/wxpython/gnumed.py --debug')
    1252
    1253                          # run the test case
    1254                  results = testOrg()
    1255
    1256                          # cleanup after the test case
    1257                  for (result , org) in results:
    1258                          if not result and org.getId() is not None:
    1259                                  print("trying cleanup")
    1260                                  if  org.shallow_del(): print("  may have succeeded")
    1261                                  else:
    1262                                          print("May need manual removal of org id =", org.getId())
    1263
    1264                  testOrgPersons()
    1265
    1266                  testListOrgs()
    1267
    1268          except:
    1269                  import  sys
    1270                  print(sys.exc_info()[0], sys.exc_info()[1])
    1271                  _log.exception( "Fatal exception")
    1272
    1273                  # clean-up any temporary categories.
    1274          if tmp_category:
    1275                  try:
    1276                          clean_org_categories(adminlogin)
    1277                  except:
    1278                          while(not login_rw_user()[0]):
    1279                                  pass
    1280                          clean_test_org()
    1281                          clean_org_categories(adminlogin)
    1282