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

Source Code for Module Gnumed.business.gmPraxis

  1  # -*- coding: utf8 -*- 
  2  """GNUmed Praxis related middleware.""" 
  3  #============================================================ 
  4  __license__ = "GPL" 
  5  __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>" 
  6   
  7   
  8  import sys 
  9  import logging 
 10  import io 
 11  import urllib.parse 
 12   
 13   
 14  if __name__ == '__main__': 
 15          sys.path.insert(0, '../../') 
 16  from Gnumed.pycommon import gmPG2 
 17  from Gnumed.pycommon import gmTools 
 18  from Gnumed.pycommon import gmBorg 
 19  from Gnumed.pycommon import gmCfg2 
 20  from Gnumed.pycommon import gmHooks 
 21  from Gnumed.pycommon import gmBusinessDBObject 
 22   
 23  from Gnumed.business import gmOrganization 
 24   
 25   
 26  _log = logging.getLogger('gm.praxis') 
 27  _cfg = gmCfg2.gmCfgData() 
 28   
 29  #============================================================ 
30 -def delete_workplace(workplace=None, delete_config=False, conn=None):
31 32 args = {'wp': workplace} 33 34 # delete workplace itself (plugin load list, that is) 35 queries = [ 36 {'cmd': """ 37 delete from cfg.cfg_item 38 where 39 fk_template = ( 40 select pk 41 from cfg.cfg_template 42 where name = 'horstspace.notebook.plugin_load_order' 43 ) 44 and 45 workplace = %(wp)s""", 46 'args': args 47 } 48 ] 49 50 # delete other config items associated with this workplace 51 if delete_config: 52 queries.append ({ 53 'cmd': """ 54 delete from cfg.cfg_item 55 where 56 workplace = %(wp)s""", 57 'args': args 58 }) 59 60 gmPG2.run_rw_queries(link_obj = conn, queries = queries, end_tx = True)
61 62 #============================================================ 63 # short description 64 #------------------------------------------------------------ 65 _SQL_get_praxis_branches = "SELECT * FROM dem.v_praxis_branches WHERE %s" 66
67 -class cPraxisBranch(gmBusinessDBObject.cBusinessDBObject):
68 """Represents a praxis branch""" 69 70 _cmd_fetch_payload = _SQL_get_praxis_branches % "pk_praxis_branch = %s" 71 _cmds_store_payload = [ 72 """UPDATE dem.praxis_branch SET 73 fk_org_unit = %(pk_org_unit)s 74 WHERE 75 pk = %(pk_praxis_branch)s 76 AND 77 xmin = %(xmin_praxis_branch)s 78 RETURNING 79 xmin as xmin_praxis_branch 80 """ 81 ] 82 _updatable_fields = [ 83 'pk_org_unit' 84 ] 85 #--------------------------------------------------------
86 - def format(self):
87 txt = _('Praxis branch #%s\n') % self._payload[self._idx['pk_praxis_branch']] 88 txt += ' ' 89 txt += '\n '.join(self.org_unit.format(with_address = True, with_org = True, with_comms = True)) 90 return txt
91 92 #--------------------------------------------------------
93 - def lock(self, exclusive=False):
94 return lock_praxis_branch(pk_praxis_branch = self._payload[self._idx['pk_praxis_branch']], exclusive = exclusive)
95 96 #--------------------------------------------------------
97 - def unlock(self, exclusive=False):
98 return unlock_praxis_branch(pk_praxis_branch = self._payload[self._idx['pk_praxis_branch']], exclusive = exclusive)
99 100 #--------------------------------------------------------
101 - def get_comm_channels(self, comm_medium=None):
102 return self.org_unit.get_comm_channels(comm_medium = comm_medium)
103 104 #--------------------------------------------------------
105 - def get_external_ids(self, id_type=None, issuer=None):
106 return self.org_unit.get_external_ids(id_type = id_type, issuer = issuer)
107 108 #--------------------------------------------------------
109 - def get_distance2address_url(self, address):
110 self_adr = self.address 111 url = 'https://www.luftlinie.org/%s-%s-%s-%s-%s/%s-%s-%s-%s-%s' % ( 112 urllib.parse.quote(self_adr['street'].encode('utf8')), 113 urllib.parse.quote(self_adr['number'].encode('utf8')), 114 urllib.parse.quote(self_adr['urb'].encode('utf8')), 115 urllib.parse.quote(self_adr['postcode'].encode('utf8')), 116 urllib.parse.quote(self_adr['country'].encode('utf8')), 117 urllib.parse.quote(address['street'].encode('utf8')), 118 urllib.parse.quote(address['number'].encode('utf8')), 119 urllib.parse.quote(address['urb'].encode('utf8')), 120 urllib.parse.quote(address['postcode'].encode('utf8')), 121 urllib.parse.quote(address['country'].encode('utf8')) 122 ) 123 return url
124 125 #-------------------------------------------------------- 126 # properties 127 #--------------------------------------------------------
128 - def _get_org_unit(self):
129 return gmOrganization.cOrgUnit(aPK_obj = self._payload[self._idx['pk_org_unit']])
130 131 org_unit = property(_get_org_unit, lambda x:x) 132 133 #--------------------------------------------------------
134 - def _get_org(self):
135 return gmOrganization.cOrg(aPK_obj = self._payload[self._idx['pk_org']])
136 137 organization = property(_get_org, lambda x:x) 138 139 #--------------------------------------------------------
140 - def _get_address(self):
141 return self.org_unit.address
142 143 address = property(_get_address, lambda x:x) 144 145 # def _set_address(self, address): 146 # self['pk_address'] = address['pk_address'] 147 # self.save() 148 # address = property(_get_address, _set_address) 149 150 #--------------------------------------------------------
151 - def _get_vcf(self):
152 vcf_fields = [ 153 'BEGIN:VCARD', 154 'VERSION:4.0', 155 'KIND:org', 156 _('FN:%(l10n_unit_category)s %(branch)s of %(l10n_organization_category)s %(praxis)s') % self, 157 'N:%(praxis)s;%(branch)s' % self 158 ] 159 adr = self.address 160 if adr is not None: 161 vcf_fields.append('ADR:;%(subunit)s;%(street)s %(number)s;%(urb)s;%(l10n_region)s;%(postcode)s;%(l10n_country)s' % adr) 162 comms = self.get_comm_channels(comm_medium = 'workphone') 163 if len(comms) > 0: 164 vcf_fields.append('TEL;VALUE=uri;TYPE=work:tel:%(url)s' % comms[0]) 165 comms = self.get_comm_channels(comm_medium = 'email') 166 if len(comms) > 0: 167 vcf_fields.append('EMAIL:%(url)s' % comms[0]) 168 vcf_fields.append('END:VCARD') 169 vcf_fname = gmTools.get_unique_filename ( 170 prefix = 'gm-praxis-', 171 suffix = '.vcf' 172 ) 173 vcf_file = io.open(vcf_fname, mode = 'wt', encoding = 'utf8') 174 vcf_file.write('\n'.join(vcf_fields)) 175 vcf_file.write('\n') 176 vcf_file.close() 177 return vcf_fname
178 179 vcf = property(_get_vcf, lambda x:x)
180 181 #------------------------------------------------------------
182 -def lock_praxis_branch(pk_praxis_branch=None, exclusive=False):
183 return gmPG2.lock_row(table = 'dem.praxis_branch', pk = pk_praxis_branch, exclusive = exclusive)
184 185 #------------------------------------------------------------
186 -def unlock_praxis_branch(pk_praxis_branch=None, exclusive=False):
187 return gmPG2.unlock_row(table = 'dem.praxis_branch', pk = pk_praxis_branch, exclusive = exclusive)
188 189 #------------------------------------------------------------
190 -def get_praxis_branches(order_by=None):
191 if order_by is None: 192 order_by = 'true' 193 else: 194 order_by = 'true ORDER BY %s' % order_by 195 196 cmd = _SQL_get_praxis_branches % order_by 197 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True) 198 return [ cPraxisBranch(row = {'data': r, 'idx': idx, 'pk_field': 'pk_praxis_branch'}) for r in rows ]
199 200 #------------------------------------------------------------
201 -def get_praxis_branch_by_org_unit(pk_org_unit=None):
202 cmd = _SQL_get_praxis_branches % 'pk_org_unit = %(pk_ou)s' 203 args = {'pk_ou': pk_org_unit} 204 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) 205 if len(rows) == 0: 206 return None 207 return cPraxisBranch(row = {'data': rows[0], 'idx': idx, 'pk_field': 'pk_praxis_branch'})
208 209 #------------------------------------------------------------
210 -def create_praxis_branch(pk_org_unit=None):
211 212 args = {'fk_unit': pk_org_unit} 213 cmd1 = """ 214 INSERT INTO dem.praxis_branch (fk_org_unit) 215 SELECT %(fk_unit)s WHERE NOT EXISTS ( 216 SELECT 1 FROM dem.praxis_branch WHERE fk_org_unit = %(fk_unit)s 217 ) 218 """ 219 cmd2 = """SELECT * from dem.v_praxis_branches WHERE pk_org_unit = %(fk_unit)s""" 220 queries = [ 221 {'cmd': cmd1, 'args': args}, 222 {'cmd': cmd2, 'args': args} 223 ] 224 rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True, get_col_idx = True) 225 return cPraxisBranch(row = {'data': rows[0], 'idx': idx, 'pk_field': 'pk_praxis_branch'})
226 227 #------------------------------------------------------------
228 -def create_praxis_branches(pk_org_units=None):
229 queries = [] 230 for pk in pk_org_units: 231 args = {'fk_unit': pk} 232 cmd = """ 233 INSERT INTO dem.praxis_branch (fk_org_unit) 234 SELECT %(fk_unit)s WHERE NOT EXISTS ( 235 SELECT 1 FROM dem.praxis_branch WHERE fk_org_unit = %(fk_unit)s 236 ) 237 """ 238 queries.append({'cmd': cmd, 'args': args}) 239 240 args = {'fk_units': tuple(pk_org_units)} 241 cmd = """SELECT * from dem.v_praxis_branches WHERE pk_org_unit IN %(fk_units)s""" 242 queries.append({'cmd': cmd, 'args': args}) 243 rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True, get_col_idx = True) 244 return [ cPraxisBranch(row = {'data': r, 'idx': idx, 'pk_field': 'pk_praxis_branch'}) for r in rows ]
245 246 #------------------------------------------------------------
247 -def delete_praxis_branch(pk_praxis_branch=None):
248 if not lock_praxis_branch(pk_praxis_branch = pk_praxis_branch, exclusive = True): 249 return False 250 args = {'pk': pk_praxis_branch} 251 cmd = "DELETE FROM dem.praxis_branch WHERE pk = %(pk)s" 252 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 253 unlock_praxis_branch(pk_praxis_branch = pk_praxis_branch, exclusive = True) 254 return True
255 256 #------------------------------------------------------------
257 -def delete_praxis_branches(pk_praxis_branches=None, except_pk_praxis_branches=None):
258 259 if pk_praxis_branches is None: 260 cmd = 'SELECT pk from dem.praxis_branch' 261 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False) 262 pks_to_lock = [ r[0] for r in rows ] 263 else: 264 pks_to_lock = pk_praxis_branches[:] 265 266 if except_pk_praxis_branches is not None: 267 for pk in except_pk_praxis_branches: 268 try: pks_to_lock.remove(pk) 269 except ValueError: pass 270 271 for pk in pks_to_lock: 272 if not lock_praxis_branch(pk_praxis_branch = pk, exclusive = True): 273 return False 274 275 args = {} 276 where_parts = [] 277 278 if pk_praxis_branches is not None: 279 args['pks'] = tuple(pk_praxis_branches) 280 where_parts.append('pk IN %(pks)s') 281 282 if except_pk_praxis_branches is not None: 283 args['except'] = tuple(except_pk_praxis_branches) 284 where_parts.append('pk NOT IN %(except)s') 285 286 if len(where_parts) == 0: 287 cmd = "DELETE FROM dem.praxis_branch" 288 else: 289 cmd = "DELETE FROM dem.praxis_branch WHERE %s" % ' AND '.join(where_parts) 290 291 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 292 for pk in pks_to_lock: 293 unlock_praxis_branch(pk_praxis_branch = pk, exclusive = True) 294 return True
295 296 #============================================================
297 -class gmCurrentPraxisBranch(gmBorg.cBorg):
298
299 - def __init__(self, branch=None):
300 try: 301 self.has_been_initialized 302 except AttributeError: 303 self.branch = None 304 self.has_been_initialized = True 305 self.__helpdesk = None 306 self.__active_workplace = None 307 308 # user wants copy of current branch 309 if branch is None: 310 return None 311 312 # must be cPraxisBranch instance, then 313 if not isinstance(branch, cPraxisBranch): 314 _log.error('cannot set current praxis branch to [%s], must be a cPraxisBranch instance' % str(branch)) 315 raise TypeError('gmPraxis.gmCurrentPraxisBranch.__init__(): <branch> must be a cPraxisBranch instance but is: %s' % str(branch)) 316 317 if self.branch is not None: 318 self.branch.unlock() 319 320 branch.lock() 321 self.branch = branch 322 _log.debug('current praxis branch now: %s', self.branch) 323 324 return None
325 326 #-------------------------------------------------------- 327 # __getattr__ handling 328 #--------------------------------------------------------
329 - def __getattr__(self, attribute):
330 if attribute == 'has_been_initialized': 331 raise AttributeError 332 if attribute in ['branch', 'waiting_list_patients', 'help_desk', 'db_logon_banner', 'active_workplace', 'workplaces', 'user_email']: 333 return getattr(self, attribute) 334 return getattr(self.branch, attribute)
335 336 #-------------------------------------------------------- 337 # __get/setitem__ handling 338 #--------------------------------------------------------
339 - def __getitem__(self, attribute = None):
340 """Return any attribute if known how to retrieve it by proxy.""" 341 return self.branch[attribute]
342 343 #--------------------------------------------------------
344 - def __setitem__(self, attribute, value):
345 self.branch[attribute] = value
346 347 #-------------------------------------------------------- 348 # waiting list handling 349 #--------------------------------------------------------
350 - def remove_from_waiting_list(self, pk=None):
351 cmd = 'DELETE FROM clin.waiting_list WHERE pk = %(pk)s' 352 args = {'pk': pk} 353 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 354 gmHooks.run_hook_script(hook = 'after_waiting_list_modified')
355 356 #--------------------------------------------------------
357 - def update_in_waiting_list(self, pk = None, urgency = 0, comment = None, zone = None):
358 cmd = """ 359 update clin.waiting_list 360 set 361 urgency = %(urg)s, 362 comment = %(cmt)s, 363 area = %(zone)s 364 where 365 pk = %(pk)s""" 366 args = { 367 'pk': pk, 368 'urg': urgency, 369 'cmt': gmTools.none_if(comment, ''), 370 'zone': gmTools.none_if(zone, '') 371 } 372 373 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 374 gmHooks.run_hook_script(hook = 'after_waiting_list_modified')
375 376 #--------------------------------------------------------
377 - def raise_in_waiting_list(self, current_position=None):
378 if current_position == 1: 379 return 380 381 cmd = 'select clin.move_waiting_list_entry(%(pos)s, (%(pos)s - 1))' 382 args = {'pos': current_position} 383 384 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
385 386 #--------------------------------------------------------
387 - def lower_in_waiting_list(self, current_position=None):
388 cmd = 'select clin.move_waiting_list_entry(%(pos)s, (%(pos)s+1))' 389 args = {'pos': current_position} 390 391 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
392 393 #-------------------------------------------------------- 394 # properties 395 #--------------------------------------------------------
397 cmd = """ 398 SELECT * FROM clin.v_waiting_list 399 ORDER BY 400 list_position 401 """ 402 rows, idx = gmPG2.run_ro_queries ( 403 queries = [{'cmd': cmd}], 404 get_col_idx = False 405 ) 406 return rows
407 408 waiting_list_patients = property (_get_waiting_list_patients, lambda x:x) 409 410 #--------------------------------------------------------
411 - def _set_helpdesk(self, helpdesk):
412 return
413
414 - def _get_helpdesk(self):
415 416 if self.__helpdesk is not None: 417 return self.__helpdesk 418 419 self.__helpdesk = gmTools.coalesce ( 420 _cfg.get ( 421 group = 'workplace', 422 option = 'help desk', 423 source_order = [ 424 ('explicit', 'return'), 425 ('workbase', 'return'), 426 ('local', 'return'), 427 ('user', 'return'), 428 ('system', 'return') 429 ] 430 ), 431 'http://wiki.gnumed.de' 432 ) 433 434 return self.__helpdesk
435 436 helpdesk = property(_get_helpdesk, _set_helpdesk) 437 438 #--------------------------------------------------------
439 - def _get_db_logon_banner(self):
440 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': 'select _(message) from cfg.db_logon_banner'}]) 441 if len(rows) == 0: 442 return '' 443 return gmTools.coalesce(rows[0][0], '').strip()
444
445 - def _set_db_logon_banner(self, banner):
446 queries = [ 447 {'cmd': 'delete from cfg.db_logon_banner'} 448 ] 449 if banner.strip() != '': 450 queries.append ({ 451 'cmd': 'insert into cfg.db_logon_banner (message) values (%(msg)s)', 452 'args': {'msg': banner.strip()} 453 }) 454 rows, idx = gmPG2.run_rw_queries(queries = queries, end_tx = True)
455 456 db_logon_banner = property(_get_db_logon_banner, _set_db_logon_banner) 457 458 #--------------------------------------------------------
459 - def _set_workplace(self, workplace):
460 # maybe later allow switching workplaces on the fly 461 return True
462
463 - def _get_workplace(self):
464 """Return the current workplace (client profile) definition. 465 466 The first occurrence counts. 467 """ 468 if self.__active_workplace is not None: 469 return self.__active_workplace 470 471 self.__active_workplace = gmTools.coalesce ( 472 _cfg.get ( 473 group = 'workplace', 474 option = 'name', 475 source_order = [ 476 ('explicit', 'return'), 477 ('workbase', 'return'), 478 ('local', 'return'), 479 ('user', 'return'), 480 ('system', 'return'), 481 ] 482 ), 483 'Local Default' 484 ) 485 486 return self.__active_workplace
487 488 active_workplace = property(_get_workplace, _set_workplace) 489 490 #--------------------------------------------------------
491 - def _set_workplaces(self, val):
492 pass
493
494 - def _get_workplaces(self):
495 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': 'SELECT DISTINCT workplace FROM cfg.cfg_item ORDER BY workplace'}]) 496 return [ r[0] for r in rows ]
497 498 workplaces = property(_get_workplaces, _set_workplaces) 499 500 #--------------------------------------------------------
501 - def _get_user_email(self):
502 # FIXME: get this from the current users staff record in the database 503 return _cfg.get ( 504 group = 'preferences', 505 option = 'user email', 506 source_order = [ 507 ('explicit', 'return'), 508 ('user', 'return'), 509 ('local', 'return'), 510 ('workbase', 'return'), 511 ('system', 'return') 512 ] 513 )
514
515 - def _set_user_email(self, val):
516 prefs_file = _cfg.get(option = 'user_preferences_file') 517 gmCfg2.set_option_in_INI_file ( 518 filename = prefs_file, 519 group = 'preferences', 520 option = 'user email', 521 value = val 522 ) 523 _cfg.reload_file_source(file = prefs_file)
524 525 user_email = property(_get_user_email, _set_user_email)
526 527 #============================================================ 528 if __name__ == '__main__': 529 530 if len(sys.argv) < 2: 531 sys.exit() 532 533 if sys.argv[1] != 'test': 534 sys.exit() 535 536 from Gnumed.pycommon import gmI18N 537 gmI18N.install_domain() 538
539 - def run_tests():
540 prac = gmCurrentPraxisBranch() 541 # print "help desk:", prac.helpdesk 542 # print "active workplace:", prac.active_workplace 543 544 old_banner = prac.db_logon_banner 545 test_banner = 'a test banner' 546 prac.db_logon_banner = test_banner 547 if prac.db_logon_banner != test_banner: 548 print(('Cannot set logon banner to', test_banner)) 549 return False 550 prac.db_logon_banner = '' 551 if prac.db_logon_banner != '': 552 print('Cannot set logon banner to ""') 553 return False 554 prac.db_logon_banner = old_banner 555 556 return True
557 558 # if not run_tests(): 559 # print "regression tests failed" 560 # print "regression tests succeeded" 561 562 for b in get_praxis_branches(): 563 print((b.format())) 564 565 #============================================================ 566