1
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 gmBusinessDBObject
21
22 from Gnumed.business import gmOrganization
23
24
25 _log = logging.getLogger('gm.praxis')
26 _cfg = gmCfg2.gmCfgData()
27
28
30
31 args = {'wp': workplace}
32
33
34 queries = [
35 {'cmd': """
36 delete from cfg.cfg_item
37 where
38 fk_template = (
39 select pk
40 from cfg.cfg_template
41 where name = 'horstspace.notebook.plugin_load_order'
42 )
43 and
44 workplace = %(wp)s""",
45 'args': args
46 }
47 ]
48
49
50 if delete_config:
51 queries.append ({
52 'cmd': """
53 delete from cfg.cfg_item
54 where
55 workplace = %(wp)s""",
56 'args': args
57 })
58
59 gmPG2.run_rw_queries(link_obj = conn, queries = queries, end_tx = True)
60
61
62
63
64 _SQL_get_praxis_branches = "SELECT * FROM dem.v_praxis_branches WHERE %s"
65
67 """Represents a praxis branch"""
68
69 _cmd_fetch_payload = _SQL_get_praxis_branches % "pk_praxis_branch = %s"
70 _cmds_store_payload = [
71 """UPDATE dem.praxis_branch SET
72 fk_org_unit = %(pk_org_unit)s
73 WHERE
74 pk = %(pk_praxis_branch)s
75 AND
76 xmin = %(xmin_praxis_branch)s
77 RETURNING
78 xmin as xmin_praxis_branch
79 """
80 ]
81 _updatable_fields = [
82 'pk_org_unit'
83 ]
84
90
91
92 - def lock(self, exclusive=False):
93 return lock_praxis_branch(pk_praxis_branch = self._payload[self._idx['pk_praxis_branch']], exclusive = exclusive)
94
95
96 - def unlock(self, exclusive=False):
97 return unlock_praxis_branch(pk_praxis_branch = self._payload[self._idx['pk_praxis_branch']], exclusive = exclusive)
98
99
102
103
106
107
109 self_adr = self.address
110 url = 'https://www.luftlinie.org/%s-%s-%s-%s-%s/%s-%s-%s-%s-%s' % (
111 urllib.parse.quote(self_adr['street'].encode('utf8')),
112 urllib.parse.quote(self_adr['number'].encode('utf8')),
113 urllib.parse.quote(self_adr['urb'].encode('utf8')),
114 urllib.parse.quote(self_adr['postcode'].encode('utf8')),
115 urllib.parse.quote(self_adr['country'].encode('utf8')),
116 urllib.parse.quote(address['street'].encode('utf8')),
117 urllib.parse.quote(address['number'].encode('utf8')),
118 urllib.parse.quote(address['urb'].encode('utf8')),
119 urllib.parse.quote(address['postcode'].encode('utf8')),
120 urllib.parse.quote(address['country'].encode('utf8'))
121 )
122 return url
123
124
125
126
129
130 org_unit = property(_get_org_unit, lambda x:x)
131
132
135
136 organization = property(_get_org, lambda x:x)
137
138
141
142 address = property(_get_address, lambda x:x)
143
144
145
146
147
148
149
151 vcf_fields = [
152 'BEGIN:VCARD',
153 'VERSION:4.0',
154 'KIND:org',
155 _('FN:%(l10n_unit_category)s %(branch)s of %(l10n_organization_category)s %(praxis)s') % self,
156 'N:%(praxis)s;%(branch)s' % self
157 ]
158 adr = self.address
159 if adr is not None:
160 vcf_fields.append('ADR:;%(subunit)s;%(street)s %(number)s;%(urb)s;%(l10n_region)s;%(postcode)s;%(l10n_country)s' % adr)
161 comms = self.get_comm_channels(comm_medium = 'workphone')
162 if len(comms) > 0:
163 vcf_fields.append('TEL;VALUE=uri;TYPE=work:tel:%(url)s' % comms[0])
164 comms = self.get_comm_channels(comm_medium = 'email')
165 if len(comms) > 0:
166 vcf_fields.append('EMAIL:%(url)s' % comms[0])
167 vcf_fields.append('END:VCARD')
168 vcf_fname = gmTools.get_unique_filename (
169 prefix = 'gm-praxis-',
170 suffix = '.vcf'
171 )
172 vcf_file = io.open(vcf_fname, mode = 'wt', encoding = 'utf8')
173 vcf_file.write('\n'.join(vcf_fields))
174 vcf_file.write('\n')
175 vcf_file.close()
176 return vcf_fname
177
178 vcf = property(_get_vcf, lambda x:x)
179
180
182 return gmPG2.lock_row(table = 'dem.praxis_branch', pk = pk_praxis_branch, exclusive = exclusive)
183
184
186 return gmPG2.unlock_row(table = 'dem.praxis_branch', pk = pk_praxis_branch, exclusive = exclusive)
187
188
190 if order_by is None:
191 order_by = 'true'
192 else:
193 order_by = 'true ORDER BY %s' % order_by
194
195 cmd = _SQL_get_praxis_branches % order_by
196 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True)
197 return [ cPraxisBranch(row = {'data': r, 'idx': idx, 'pk_field': 'pk_praxis_branch'}) for r in rows ]
198
199
201 cmd = _SQL_get_praxis_branches % 'pk_org_unit = %(pk_ou)s'
202 args = {'pk_ou': pk_org_unit}
203 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True)
204 if len(rows) == 0:
205 return None
206 return cPraxisBranch(row = {'data': rows[0], 'idx': idx, 'pk_field': 'pk_praxis_branch'})
207
208
210
211 args = {'fk_unit': pk_org_unit}
212 cmd1 = """
213 INSERT INTO dem.praxis_branch (fk_org_unit)
214 SELECT %(fk_unit)s WHERE NOT EXISTS (
215 SELECT 1 FROM dem.praxis_branch WHERE fk_org_unit = %(fk_unit)s
216 )
217 """
218 cmd2 = """SELECT * from dem.v_praxis_branches WHERE pk_org_unit = %(fk_unit)s"""
219 queries = [
220 {'cmd': cmd1, 'args': args},
221 {'cmd': cmd2, 'args': args}
222 ]
223 rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True, get_col_idx = True)
224 return cPraxisBranch(row = {'data': rows[0], 'idx': idx, 'pk_field': 'pk_praxis_branch'})
225
226
228 queries = []
229 for pk in pk_org_units:
230 args = {'fk_unit': pk}
231 cmd = """
232 INSERT INTO dem.praxis_branch (fk_org_unit)
233 SELECT %(fk_unit)s WHERE NOT EXISTS (
234 SELECT 1 FROM dem.praxis_branch WHERE fk_org_unit = %(fk_unit)s
235 )
236 """
237 queries.append({'cmd': cmd, 'args': args})
238
239 args = {'fk_units': tuple(pk_org_units)}
240 cmd = """SELECT * from dem.v_praxis_branches WHERE pk_org_unit IN %(fk_units)s"""
241 queries.append({'cmd': cmd, 'args': args})
242 rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True, get_col_idx = True)
243 return [ cPraxisBranch(row = {'data': r, 'idx': idx, 'pk_field': 'pk_praxis_branch'}) for r in rows ]
244
245
247 if not lock_praxis_branch(pk_praxis_branch = pk_praxis_branch, exclusive = True):
248 return False
249 args = {'pk': pk_praxis_branch}
250 cmd = "DELETE FROM dem.praxis_branch WHERE pk = %(pk)s"
251 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
252 unlock_praxis_branch(pk_praxis_branch = pk_praxis_branch, exclusive = True)
253 return True
254
255
257
258 if pk_praxis_branches is None:
259 cmd = 'SELECT pk from dem.praxis_branch'
260 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False)
261 pks_to_lock = [ r[0] for r in rows ]
262 else:
263 pks_to_lock = pk_praxis_branches[:]
264
265 if except_pk_praxis_branches is not None:
266 for pk in except_pk_praxis_branches:
267 try: pks_to_lock.remove(pk)
268 except ValueError: pass
269
270 for pk in pks_to_lock:
271 if not lock_praxis_branch(pk_praxis_branch = pk, exclusive = True):
272 return False
273
274 args = {}
275 where_parts = []
276
277 if pk_praxis_branches is not None:
278 args['pks'] = tuple(pk_praxis_branches)
279 where_parts.append('pk IN %(pks)s')
280
281 if except_pk_praxis_branches is not None:
282 args['except'] = tuple(except_pk_praxis_branches)
283 where_parts.append('pk NOT IN %(except)s')
284
285 if len(where_parts) == 0:
286 cmd = "DELETE FROM dem.praxis_branch"
287 else:
288 cmd = "DELETE FROM dem.praxis_branch WHERE %s" % ' AND '.join(where_parts)
289
290 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
291 for pk in pks_to_lock:
292 unlock_praxis_branch(pk_praxis_branch = pk, exclusive = True)
293 return True
294
295
297
299 try:
300 self.has_been_initialized
301 except AttributeError:
302 self.branch = None
303 self.has_been_initialized = True
304 self.__helpdesk = None
305 self.__active_workplace = None
306
307
308 if branch is None:
309 return None
310
311
312 if not isinstance(branch, cPraxisBranch):
313 _log.error('cannot set current praxis branch to [%s], must be a cPraxisBranch instance' % str(branch))
314 raise TypeError('gmPraxis.gmCurrentPraxisBranch.__init__(): <branch> must be a cPraxisBranch instance but is: %s' % str(branch))
315
316 if self.branch is not None:
317 self.branch.unlock()
318
319 branch.lock()
320 self.branch = branch
321 _log.debug('current praxis branch now: %s', self.branch)
322
323 return None
324
325
326
327
329 if attribute == 'has_been_initialized':
330 raise AttributeError
331 if attribute in ['branch', 'waiting_list_patients', 'help_desk', 'db_logon_banner', 'active_workplace', 'workplaces', 'user_email']:
332 return getattr(self, attribute)
333 return getattr(self.branch, attribute)
334
335
336
337
339 """Return any attribute if known how to retrieve it by proxy."""
340 return self.branch[attribute]
341
342
344 self.branch[attribute] = value
345
346
347
348
350 cmd = 'delete from clin.waiting_list where pk = %(pk)s'
351 args = {'pk': pk}
352 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
353
355 cmd = """
356 update clin.waiting_list
357 set
358 urgency = %(urg)s,
359 comment = %(cmt)s,
360 area = %(zone)s
361 where
362 pk = %(pk)s"""
363 args = {
364 'pk': pk,
365 'urg': urgency,
366 'cmt': gmTools.none_if(comment, ''),
367 'zone': gmTools.none_if(zone, '')
368 }
369
370 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
371
373 if current_position == 1:
374 return
375
376 cmd = 'select clin.move_waiting_list_entry(%(pos)s, (%(pos)s - 1))'
377 args = {'pos': current_position}
378
379 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
380
382 cmd = 'select clin.move_waiting_list_entry(%(pos)s, (%(pos)s+1))'
383 args = {'pos': current_position}
384
385 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
386
387
388
390 cmd = """
391 SELECT * FROM clin.v_waiting_list
392 ORDER BY
393 list_position
394 """
395 rows, idx = gmPG2.run_ro_queries (
396 queries = [{'cmd': cmd}],
397 get_col_idx = False
398 )
399 return rows
400
401 waiting_list_patients = property (_get_waiting_list_patients, lambda x:x)
402
403
406
408
409 if self.__helpdesk is not None:
410 return self.__helpdesk
411
412 self.__helpdesk = gmTools.coalesce (
413 _cfg.get (
414 group = 'workplace',
415 option = 'help desk',
416 source_order = [
417 ('explicit', 'return'),
418 ('workbase', 'return'),
419 ('local', 'return'),
420 ('user', 'return'),
421 ('system', 'return')
422 ]
423 ),
424 'http://wiki.gnumed.de'
425 )
426
427 return self.__helpdesk
428
429 helpdesk = property(_get_helpdesk, _set_helpdesk)
430
431
433 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': 'select _(message) from cfg.db_logon_banner'}])
434 if len(rows) == 0:
435 return ''
436 return gmTools.coalesce(rows[0][0], '').strip()
437
439 queries = [
440 {'cmd': 'delete from cfg.db_logon_banner'}
441 ]
442 if banner.strip() != '':
443 queries.append ({
444 'cmd': 'insert into cfg.db_logon_banner (message) values (%(msg)s)',
445 'args': {'msg': banner.strip()}
446 })
447 rows, idx = gmPG2.run_rw_queries(queries = queries, end_tx = True)
448
449 db_logon_banner = property(_get_db_logon_banner, _set_db_logon_banner)
450
451
455
457 """Return the current workplace (client profile) definition.
458
459 The first occurrence counts.
460 """
461 if self.__active_workplace is not None:
462 return self.__active_workplace
463
464 self.__active_workplace = gmTools.coalesce (
465 _cfg.get (
466 group = 'workplace',
467 option = 'name',
468 source_order = [
469 ('explicit', 'return'),
470 ('workbase', 'return'),
471 ('local', 'return'),
472 ('user', 'return'),
473 ('system', 'return'),
474 ]
475 ),
476 'Local Default'
477 )
478
479 return self.__active_workplace
480
481 active_workplace = property(_get_workplace, _set_workplace)
482
483
486
488 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': 'SELECT DISTINCT workplace FROM cfg.cfg_item ORDER BY workplace'}])
489 return [ r[0] for r in rows ]
490
491 workplaces = property(_get_workplaces, _set_workplaces)
492
493
495
496 return _cfg.get (
497 group = 'preferences',
498 option = 'user email',
499 source_order = [
500 ('explicit', 'return'),
501 ('user', 'return'),
502 ('local', 'return'),
503 ('workbase', 'return'),
504 ('system', 'return')
505 ]
506 )
507
517
518 user_email = property(_get_user_email, _set_user_email)
519
520
521 if __name__ == '__main__':
522
523 if len(sys.argv) < 2:
524 sys.exit()
525
526 if sys.argv[1] != 'test':
527 sys.exit()
528
529 from Gnumed.pycommon import gmI18N
530 gmI18N.install_domain()
531
550
551
552
553
554
555 for b in get_praxis_branches():
556 print((b.format()))
557
558
559