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