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

Source Code for Module Gnumed.business.gmStaff

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