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: 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 try: 187 rows, idx = gmPG2.run_rw_queries(link_obj = conn, queries = queries, end_tx = True) 188 except gmPG2.dbapi.IntegrityError as e: 189 if e.pgcode == gmPG2.sql_error_codes.UNIQUE_VIOLATION: 190 msg = _( 191 'Cannot add GNUmed user.\n' 192 '\n' 193 'The database account [%s] is already listed as a\n' 194 'GNUmed user. There can only be one GNUmed user\n' 195 'for each database account.\n' 196 ) % db_account 197 return False, msg 198 raise 199 200 return True, None
201 202 #------------------------------------------------------------
203 -def delete_staff(conn=None, pk_staff=None):
204 queries = [{'cmd': 'DELETE FROM dem.staff WHERE pk = %(pk)s', 'args': {'pk': pk_staff}}] 205 try: 206 rows, idx = gmPG2.run_rw_queries(link_obj = conn, queries = queries, end_tx = True) 207 except gmPG2.dbapi.IntegrityError as e: 208 if e.pgcode == gmPG2.sql_error_codes.FOREIGN_KEY_VIOLATION: # 23503 foreign_key_violation 209 msg = _( 210 'Cannot delete GNUmed staff member because the\n' 211 'database still contains data linked to it.\n' 212 '\n' 213 'The account was deactivated instead.' 214 ) 215 deactivate_staff(conn = conn, pk_staff = pk_staff) 216 return False, msg 217 raise 218 219 return True, None
220 221 #------------------------------------------------------------
222 -def activate_staff(conn=None, pk_staff=None):
223 # 1) activate staff entry 224 staff = cStaff(aPK_obj = pk_staff) 225 staff['is_active'] = True 226 staff.save_payload(conn=conn) # FIXME: error handling 227 228 # 2) enable database account login 229 rowx, idx = gmPG2.run_rw_queries ( 230 link_obj = conn, 231 # password does not matter because PG account must already exist 232 queries = [{'cmd': 'select gm.create_user(%s, %s)', 'args': [staff['db_user'], 'flying wombat']}], 233 end_tx = True 234 ) 235 236 return True
237 238 #------------------------------------------------------------
239 -def deactivate_staff(conn=None, pk_staff=None):
240 241 # 1) inactivate staff entry 242 staff = cStaff(aPK_obj = pk_staff) 243 staff['is_active'] = False 244 staff.save_payload(conn = conn) # FIXME: error handling 245 246 # 2) disable database account login 247 rows, idx = gmPG2.run_rw_queries ( 248 link_obj = conn, 249 queries = [{'cmd': 'select gm.disable_user(%s)', 'args': [staff['db_user']]}], 250 end_tx = True 251 ) 252 253 return True
254 255 #============================================================
256 -def set_current_provider_to_logged_on_user():
257 gmCurrentProvider(provider = cStaff())
258 259 #============================================================
260 -class gmCurrentProvider(gmBorg.cBorg):
261 """Staff member Borg to hold currently logged on provider. 262 263 There may be many instances of this but they all share state. 264 """
265 - def __init__(self, provider=None):
266 """Change or get currently logged on provider. 267 268 provider: 269 * None: get copy of current instance 270 * cStaff instance: change logged on provider (role) 271 """ 272 # make sure we do have a provider pointer 273 try: 274 self.provider 275 except AttributeError: 276 self.provider = gmNull.cNull() 277 278 # user wants copy of currently logged on provider 279 if provider is None: 280 return None 281 282 # must be cStaff instance, then 283 if not isinstance(provider, cStaff): 284 raise ValueError('cannot set logged on provider to [%s], must be either None or cStaff instance' % str(provider)) 285 286 # first invocation 287 if isinstance(self.provider, gmNull.cNull): 288 self.provider = provider 289 return None 290 291 # same ID, no change needed 292 if self.provider['pk_staff'] == provider['pk_staff']: 293 return None 294 295 # user wants different provider 296 raise ValueError('provider change [%s] -> [%s] not yet supported' % (self.provider['pk_staff'], provider['pk_staff']))
297 298 #--------------------------------------------------------
299 - def get_staff(self):
300 return self.provider
301 302 #-------------------------------------------------------- 303 # __getitem__ handling 304 #--------------------------------------------------------
305 - def __getitem__(self, aVar):
306 """Return any attribute if known how to retrieve it by proxy. 307 """ 308 return self.provider[aVar]
309 310 #-------------------------------------------------------- 311 # __s/getattr__ handling 312 #--------------------------------------------------------
313 - def __getattr__(self, attribute):
314 if attribute == 'provider': # so we can __init__ ourselves 315 raise AttributeError 316 if not isinstance(self.provider, gmNull.cNull): 317 return getattr(self.provider, attribute)
318 # raise AttributeError 319 320 #============================================================ 321 # main/testing 322 #============================================================ 323 if __name__ == '__main__': 324 325 if len(sys.argv) == 1: 326 sys.exit() 327 328 if sys.argv[1] != 'test': 329 sys.exit() 330 331 import datetime 332 from Gnumed.pycommon import gmI18N 333 from Gnumed.pycommon import gmDateTime 334 335 gmI18N.activate_locale() 336 gmI18N.install_domain() 337 gmDateTime.init() 338 339 #--------------------------------------------------------
340 - def test_staff():
341 staff = cStaff() 342 print(staff) 343 print(staff.inbox) 344 print(staff.inbox.messages)
345 #--------------------------------------------------------
346 - def test_current_provider():
347 staff = cStaff() 348 provider = gmCurrentProvider(provider = staff) 349 print(provider) 350 print(provider.inbox) 351 print(provider.inbox.messages) 352 print(provider.database_language) 353 tmp = provider.database_language 354 provider.database_language = None 355 print(provider.database_language) 356 provider.database_language = tmp 357 print(provider.database_language)
358 #-------------------------------------------------------- 359 test_staff() 360 #test_current_provider() 361 362 #============================================================ 363