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 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
31
32 args = {'wp': workplace}
33
34
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
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
64
65 _SQL_get_praxis_branches = "SELECT * FROM dem.v_praxis_branches WHERE %s"
66
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
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
103
104
107
108
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
127
130
131 org_unit = property(_get_org_unit, lambda x:x)
132
133
136
137 organization = property(_get_org, lambda x:x)
138
139
142
143 address = property(_get_address, lambda x:x)
144
145
146
147
148
149
150
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
183 return gmPG2.lock_row(table = 'dem.praxis_branch', pk = pk_praxis_branch, exclusive = exclusive)
184
185
187 return gmPG2.unlock_row(table = 'dem.praxis_branch', pk = pk_praxis_branch, exclusive = exclusive)
188
189
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
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
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
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
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
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
298
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
309 if branch is None:
310 return None
311
312
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
328
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
338
340 """Return any attribute if known how to retrieve it by proxy."""
341 return self.branch[attribute]
342
343
345 self.branch[attribute] = value
346
347
348
349
355
356
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
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
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
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
413
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
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
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
462
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
493
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
502
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
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
557
558
559
560
561
562 for b in get_praxis_branches():
563 print((b.format()))
564
565
566