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

# Source Code for Module Gnumed.business.gmStaff

      1  # -*- coding: utf8 -*-
      2  """GNUmed staff objects."""
      3  #============================================================
      4  __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>"
      5  __license__ = "GPL"
      6
      7  # std lib
      8  import sys
      9  import logging
     10
     11  # GNUmed
     12  if __name__ == '__main__':
     13          sys.path.insert(0, '../../')
     14  from Gnumed.pycommon import gmBusinessDBObject
     15  from Gnumed.pycommon import gmPG2
     16  from Gnumed.pycommon import gmNull
     17  from Gnumed.pycommon import gmBorg
     18  from Gnumed.pycommon import gmLog2
     19
     20
     21  _log = logging.getLogger('gm.staff')
     22
     23  _map_gm_role2pg_group = {
     24          u'public access': 'gm-public',
     25          u'non-clinical access': u'gm-staff',
     26          u'full clinical access': u'gm-doctors'
     27  }
     28
     29  #============================================================
     30  _SQL_fetch_staff_fields = u'SELECT *, _(role) AS l10n_role FROM dem.v_staff WHERE %s'
     31
     32 -class cStaff(gmBusinessDBObject.cBusinessDBObject):
     33          _cmd_fetch_payload = _SQL_fetch_staff_fields % u"pk_staff = %s"
     34          _cmds_store_payload = [
     35                  u"""UPDATE dem.staff SET
     36                                  short_alias = %(short_alias)s,
     37                                  comment = gm.nullify_empty_string(%(comment)s),
     38                                  is_active = %(is_active)s,
     39                                  db_user = %(db_user)s
     40                          WHERE
     41                                  pk = %(pk_staff)s
     42                                          AND
     43                                  xmin = %(xmin_staff)s
     44                          RETURNING
     45                                  xmin AS xmin_staff"""
     46          ]
     47          _updatable_fields = ['short_alias', 'comment', 'is_active', 'db_user']
     48          #--------------------------------------------------------
     49 -        def __init__(self, aPK_obj=None, row=None):
     50                  # by default get staff corresponding to CURRENT_USER
     51                  if (aPK_obj is None) and (row is None):
     52                          #cmd = u"select *, _(role) AS l10n_role from dem.v_staff where "
     53                          cmd = _SQL_fetch_staff_fields % u"db_user = CURRENT_USER"
     54                          try:
     55                                  rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx=True)
     56                          except:
     57                                  _log.exception('cannot instantiate staff instance')
     58                                  gmLog2.log_stack_trace()
     59                                  raise ValueError('cannot instantiate staff instance for database account CURRENT_USER')
     60                          if len(rows) == 0:
     61                                  raise ValueError('no staff record for database account CURRENT_USER')
     62                          row = {
     63                                  'pk_field': 'pk_staff',
     64                                  'idx': idx,
     65                                  'data': rows[0]
     66                          }
     67                          gmBusinessDBObject.cBusinessDBObject.__init__(self, row = row)
     68                  else:
     69                          gmBusinessDBObject.cBusinessDBObject.__init__(self, aPK_obj = aPK_obj, row = row)
     70
     71                  # are we SELF ?
     72                  self.__is_current_user = (gmPG2.get_current_user() == self._payload[self._idx['db_user']])
     73
     74                  self.__inbox = None
     75          #--------------------------------------------------------
     76 -        def __setitem__(self, attribute, value):
     77                  if attribute == 'db_user':
     78                          if self.__is_current_user:
     79                                  _log.debug('will not modify database account association of CURRENT_USER staff member')
     80                                  return
     81                  gmBusinessDBObject.cBusinessDBObject.__setitem__(self, attribute, value)
     82          #--------------------------------------------------------
     83 -        def _get_db_lang(self):
     84                  rows, idx = gmPG2.run_ro_queries (
     85                          queries = [{
     86                                  'cmd': u'select i18n.get_curr_lang(%(usr)s)',
     87                                  'args': {'usr': self._payload[self._idx['db_user']]}
     88                          }]
     89                  )
     90                  return rows[0][0]
     91
     92 -        def _set_db_lang(self, language):
     93                  if not gmPG2.set_user_language(language = language):
     94                          raise ValueError (
     95                                  u'Cannot set database language to [%s] for user [%s].' % (language, self._payload[self._idx['db_user']])
     96                          )
     97                  return
     98
     99          database_language = property(_get_db_lang, _set_db_lang)
    100          #--------------------------------------------------------
    101 -        def _get_inbox(self):
    102                  if self.__inbox is None:
    103                          from Gnumed.business import gmProviderInbox
    104                          self.__inbox = gmProviderInbox.cProviderInbox(provider_id = self._payload[self._idx['pk_staff']])
    105                  return self.__inbox
    106
    107 -        def _set_inbox(self, inbox):
    108                  return
    109
    110          inbox = property(_get_inbox, _set_inbox)
    111          #--------------------------------------------------------
    112 -        def _get_identity(self):
    113                  from Gnumed.business import gmPerson
    114                  return gmPerson.cIdentity(aPK_obj = self._payload[self._idx['pk_identity']])
    115
    116          identity = property(_get_identity, lambda x:x)
    117          #--------------------------------------------------------
    118 -        def set_role(self, conn=None, role=None):
    119                  if role.strip() == self._payload[self._idx['role']]:
    120                          return True
    121
    122                  cmd = u'SELECT gm.add_user_to_permission_group(%(usr)s::name, %(grp)s::name)'
    123                  args = {
    124                          'usr': self._payload[self._idx['db_user']],
    125                          'grp': _map_gm_role2pg_group[role.strip()]
    126                  }
    127                  rows, idx = gmPG2.run_rw_queries (
    128                          link_obj = conn,
    129                          queries = [{'cmd': cmd, 'args': args}],
    130                          get_col_idx = False,
    131                          return_data = True,
    132                          end_tx = True
    133                  )
    134                  if not rows[0][0]:
    135                          return False
    136                  self.refetch_payload()
    137                  return True
    138
    139          role = property(lambda x:x, set_role)
    140  #============================================================
    141 -def get_staff_list(active_only=False):
    142          if active_only:
    143                  cmd = _SQL_fetch_staff_fields % u'is_active ORDER BY can_login DESC, short_alias ASC'
    144          else:
    145                  cmd = _SQL_fetch_staff_fields % u'TRUE ORDER BY can_login DESC, is_active DESC, short_alias ASC'
    146          rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx=True)
    147          staff_list = []
    148          for row in rows:
    149                  obj_row = {
    150                          'idx': idx,
    151                          'data': row,
    152                          'pk_field': 'pk_staff'
    153                  }
    154                  staff_list.append(cStaff(row=obj_row))
    155          return staff_list
    156  #------------------------------------------------------------
    157 -def create_staff(conn=None, db_account=None, password=None, identity=None, short_alias=None):
    158          args = {
    159                  'pg_usr': db_account,
    160                  'pwd': password,
    161                  'person_id': identity,
    162                  'sig': short_alias
    163          }
    164
    165          queries = [
    166                  {'cmd': u'SELECT gm.create_user(%(pg_usr)s, %(pwd)s)', 'args': args},
    167                  {'cmd': u"""
    168                          INSERT INTO dem.staff
    169                                  (fk_identity, db_user, short_alias)
    170                          VALUES (
    171                                  %(person_id)s,
    172                                  %(pg_usr)s,
    173                                  %(sig)s
    174                          )""",
    175                   'args': args
    176                  }
    177          ]
    178
    179          try:
    180                  rows, idx = gmPG2.run_rw_queries(link_obj = conn, queries = queries, end_tx = True)
    181          except gmPG2.dbapi.IntegrityError, e:
    182                  if e.pgcode == gmPG2.sql_error_codes.UNIQUE_VIOLATION:
    183                          msg = _(
    184                                  'Cannot add GNUmed user.\n'
    185                                  '\n'
    186                                  'The database account [%s] is already listed as a\n'
    187                                  'GNUmed user. There can only be one GNUmed user\n'
    188                                  'for each database account.\n'
    189                          ) % db_account
    190                          return False, msg
    191                  raise
    192
    193          return True, None
    194  #------------------------------------------------------------
    195 -def delete_staff(conn=None, pk_staff=None):
    196          queries = [{'cmd': u'DELETE FROM dem.staff WHERE pk = %(pk)s', 'args': {'pk': pk_staff}}]
    197          try:
    198                  rows, idx = gmPG2.run_rw_queries(link_obj = conn, queries = queries, end_tx = True)
    199          except gmPG2.dbapi.IntegrityError, e:
    200                  if e.pgcode == gmPG2.sql_error_codes.FOREIGN_KEY_VIOLATION:             # 23503  foreign_key_violation
    201                          msg = _(
    202                                  'Cannot delete GNUmed staff member because the\n'
    203                                  'database still contains data linked to it.\n'
    204                                  '\n'
    205                                  'The account was deactivated instead.'
    206                          )
    207                          deactivate_staff(conn = conn, pk_staff = pk_staff)
    208                          return False, msg
    209                  raise
    210
    211          return True, None
    212  #------------------------------------------------------------
    213 -def activate_staff(conn=None, pk_staff=None):
    214          # 1) activate staff entry
    215          staff = cStaff(aPK_obj = pk_staff)
    216          staff['is_active'] = True
    217          staff.save_payload(conn=conn)                           # FIXME: error handling
    218
    219          # 2) enable database account login
    220          rowx, idx = gmPG2.run_rw_queries (
    221                  link_obj = conn,
    222                  # password does not matter because PG account must already exist
    223                  queries = [{'cmd': u'select gm.create_user(%s, %s)', 'args': [staff['db_user'], 'flying wombat']}],
    224                  end_tx = True
    225          )
    226
    227          return True
    228  #------------------------------------------------------------
    229 -def deactivate_staff(conn=None, pk_staff=None):
    230
    231          # 1) inactivate staff entry
    232          staff = cStaff(aPK_obj = pk_staff)
    233          staff['is_active'] = False
    234          staff.save_payload(conn = conn)                         # FIXME: error handling
    235
    236          # 2) disable database account login
    237          rows, idx = gmPG2.run_rw_queries (
    238                  link_obj = conn,
    239                  queries = [{'cmd': u'select gm.disable_user(%s)', 'args': [staff['db_user']]}],
    240                  end_tx = True
    241          )
    242
    243          return True
    244  #============================================================
    245 -def set_current_provider_to_logged_on_user():
    246          gmCurrentProvider(provider = cStaff())
    247  #============================================================
    248 -class gmCurrentProvider(gmBorg.cBorg):
    249          """Staff member Borg to hold currently logged on provider.
    250
    251          There may be many instances of this but they all share state.
    252          """
    253 -        def __init__(self, provider=None):
    254                  """Change or get currently logged on provider.
    255
    256                  provider:
    257                  * None: get copy of current instance
    258                  * cStaff instance: change logged on provider (role)
    259                  """
    260                  # make sure we do have a provider pointer
    261                  try:
    262                          self.provider
    263                  except AttributeError:
    264                          self.provider = gmNull.cNull()
    265
    266                  # user wants copy of currently logged on provider
    267                  if provider is None:
    268                          return None
    269
    270                  # must be cStaff instance, then
    271                  if not isinstance(provider, cStaff):
    272                          raise ValueError, 'cannot set logged on provider to [%s], must be either None or cStaff instance' % str(provider)
    273
    274                  # same ID, no change needed
    275                  if self.provider['pk_staff'] == provider['pk_staff']:
    276                          return None
    277
    278                  # first invocation
    279                  if isinstance(self.provider, gmNull.cNull):
    280                          self.provider = provider
    281                          return None
    282
    283                  # user wants different provider
    284                  raise ValueError, 'provider change [%s] -> [%s] not yet supported' % (self.provider['pk_staff'], provider['pk_staff'])
    285
    286          #--------------------------------------------------------
    287 -        def get_staff(self):
    288                  return self.provider
    289          #--------------------------------------------------------
    290          # __getitem__ handling
    291          #--------------------------------------------------------
    292 -        def __getitem__(self, aVar):
    293                  """Return any attribute if known how to retrieve it by proxy.
    294                  """
    295                  return self.provider[aVar]
    296          #--------------------------------------------------------
    297          # __s/getattr__ handling
    298          #--------------------------------------------------------
    299 -        def __getattr__(self, attribute):
    300                  if attribute == 'provider':                     # so we can __init__ ourselves
    301                          raise AttributeError
    302                  if not isinstance(self.provider, gmNull.cNull):
    303                          return getattr(self.provider, attribute)
    304  #               raise AttributeError
    305  #============================================================
    306  # main/testing
    307  #============================================================
    308  if __name__ == '__main__':
    309
    310          if len(sys.argv) == 1:
    311                  sys.exit()
    312
    313          if sys.argv[1] != 'test':
    314                  sys.exit()
    315
    316          import datetime
    317          from Gnumed.pycommon import gmI18N
    318          from Gnumed.pycommon import gmDateTime
    319
    320          gmI18N.activate_locale()
    321          gmI18N.install_domain()
    322          gmDateTime.init()
    323
    324          #--------------------------------------------------------
    325 -        def test_staff():
    326                  staff = cStaff()
    327                  print staff
    328                  print staff.inbox
    329                  print staff.inbox.messages
    330          #--------------------------------------------------------
    331 -        def test_current_provider():
    332                  staff = cStaff()
    333                  provider = gmCurrentProvider(provider = staff)
    334                  print provider
    335                  print provider.inbox
    336                  print provider.inbox.messages
    337                  print provider.database_language
    338                  tmp = provider.database_language
    339                  provider.database_language = None
    340                  print provider.database_language
    341                  provider.database_language = tmp
    342                  print provider.database_language
    343          #--------------------------------------------------------
    344          test_staff()
    345          #test_current_provider()
    346
    347  #============================================================
    348