| Home | Trees | Indices | Help |
|
|---|
|
|
1 """GNUmed praxis related widgets.
2
3 Praxis:
4
5 Each database belongs to ONE praxis only. A praxis can
6 have several branches. A praxis is at the same level
7 as an organization, except that it is not explicitely
8 defined. Rather, that ONE organization of which at least
9 one unit is defined as a praxis branch IS the praxis.
10
11 Praxis branch
12
13 Branches are the sites/locations of a praxis. There
14 can be several branches. Each branch must link to
15 units of ONE AND THE SAME organization (because
16 it is not considered good data protection practice
17 to mix charts of *different* organizations within
18 one database). However, that organization which
19 has units that are praxis branches can also have
20 other units which are not branches :-)
21
22 copyright: authors
23 """
24 #============================================================
25 __author__ = "K.Hilbert"
26 __license__ = "GPL v2 or later (details at http://www.gnu.org)"
27
28 import logging
29 import sys
30 #import datetime as pydt
31
32
33 import wx
34
35
36 if __name__ == '__main__':
37 sys.path.insert(0, '../../')
38 from Gnumed.pycommon import gmCfg
39 from Gnumed.pycommon import gmDispatcher
40 from Gnumed.pycommon import gmTools
41 from Gnumed.pycommon import gmPG2
42 from Gnumed.pycommon import gmMatchProvider
43
44 from Gnumed.business import gmPraxis
45 from Gnumed.business import gmStaff
46 from Gnumed.business import gmOrganization
47
48 from Gnumed.wxpython import gmOrganizationWidgets
49 from Gnumed.wxpython import gmGuiHelpers
50 from Gnumed.wxpython import gmAuthWidgets
51 from Gnumed.wxpython import gmListWidgets
52 from Gnumed.wxpython import gmPlugin
53 from Gnumed.wxpython import gmCfgWidgets
54 from Gnumed.wxpython import gmPhraseWheel
55
56
57 _log = logging.getLogger('gm.praxis')
58
59 #=========================================================================
61
62 if parent is None:
63 parent = wx.GetApp().GetTopWindow()
64
65 conn = gmAuthWidgets.get_dbowner_connection(procedure = _('showing audit trail'))
66 if conn is None:
67 return False
68
69 #-----------------------------------
70 def refresh(lctrl):
71 cmd = 'SELECT * FROM audit.v_audit_trail ORDER BY audit_when_ts'
72 rows, idx = gmPG2.run_ro_queries(link_obj = conn, queries = [{'cmd': cmd}], get_col_idx = False)
73 lctrl.set_string_items (
74 [ [
75 r['event_when'],
76 r['event_by'],
77 '%s %s %s' % (
78 gmTools.coalesce(r['row_version_before'], gmTools.u_diameter),
79 gmTools.u_arrow2right,
80 gmTools.coalesce(r['row_version_after'], gmTools.u_diameter)
81 ),
82 r['event_table'],
83 r['event'],
84 r['pk_audit']
85 ] for r in rows ]
86 )
87 #-----------------------------------
88 gmListWidgets.get_choices_from_list (
89 parent = parent,
90 msg = '',
91 caption = _('GNUmed database audit log ...'),
92 columns = [ _('When'), _('Who'), _('Revisions'), _('Table'), _('Event'), '#' ],
93 single_selection = True,
94 refresh_callback = refresh
95 )
96
97 #============================================================
99
100 if parent is None:
101 parent = wx.GetApp().GetTopWindow()
102
103 staff = gmStaff.get_staff_list()
104 choices = [ [
105 s['short_alias'],
106 '%s%s %s' % (
107 gmTools.coalesce(s['title'], '', '%s '),
108 s['firstnames'],
109 s['lastnames']
110 ),
111 s['l10n_role'],
112 gmTools.coalesce(s['comment'], '')
113 ]
114 for s in staff
115 if s['is_active'] is True
116 ]
117 data = [ s['pk_staff'] for s in staff if s['is_active'] is True ]
118
119 gmCfgWidgets.configure_string_from_list_option (
120 parent = parent,
121 message = _(
122 '\n'
123 'Please select the provider to fall back to in case\n'
124 'no primary provider is configured for a patient.\n'
125 ),
126 option = 'patient.fallback_primary_provider',
127 bias = 'user',
128 default_value = None,
129 choices = choices,
130 columns = [_('Alias'), _('Provider'), _('Role'), _('Comment')],
131 data = data,
132 caption = _('Configuring fallback primary provider')
133 )
134
135 #============================================================
136 # workplace plugin configuration widgets
137 #------------------------------------------------------------
139
140 if parent is None:
141 parent = wx.GetApp().GetTopWindow()
142
143 #-----------------------------------
144 def delete(workplace):
145
146 curr_workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace
147 if workplace == curr_workplace:
148 gmDispatcher.send(signal = 'statustext', msg = _('Cannot delete the active workplace.'), beep = True)
149 return False
150
151 dlg = gmGuiHelpers.c2ButtonQuestionDlg (
152 parent,
153 -1,
154 caption = _('Deleting workplace ...'),
155 question = _('Are you sure you want to delete this workplace ?\n\n "%s"\n') % workplace,
156 show_checkbox = True,
157 checkbox_msg = _('delete configuration, too'),
158 checkbox_tooltip = _(
159 'Check this if you want to delete all configuration items\n'
160 'for this workplace along with the workplace itself.'
161 ),
162 button_defs = [
163 {'label': _('Delete'), 'tooltip': _('Yes, delete this workplace.'), 'default': True},
164 {'label': _('Do NOT delete'), 'tooltip': _('No, do NOT delete this workplace'), 'default': False}
165 ]
166 )
167
168 decision = dlg.ShowModal()
169 if decision != wx.ID_YES:
170 dlg.DestroyLater()
171 return False
172
173 include_cfg = dlg.checkbox_is_checked()
174 dlg.DestroyLater()
175
176 dbo_conn = gmAuthWidgets.get_dbowner_connection(procedure = _('delete workplace'))
177 if not dbo_conn:
178 return False
179
180 gmPraxis.delete_workplace(workplace = workplace, conn = dbo_conn, delete_config = include_cfg)
181 return True
182 #-----------------------------------
183 def edit(workplace=None):
184
185 dbcfg = gmCfg.cCfgSQL()
186
187 if workplace is None:
188 dlg = wx.TextEntryDialog (
189 parent,
190 _('Enter a descriptive name for the new workplace:'),
191 caption = _('Configuring GNUmed workplaces ...'),
192 value = '',
193 style = wx.OK | wx.CENTRE
194 )
195 dlg.ShowModal()
196 workplace = dlg.GetValue().strip()
197 if workplace == '':
198 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...'))
199 return False
200 curr_plugins = []
201 else:
202 curr_plugins = gmTools.coalesce(dbcfg.get2 (
203 option = 'horstspace.notebook.plugin_load_order',
204 workplace = workplace,
205 bias = 'workplace'
206 ), []
207 )
208
209 msg = _(
210 'Pick the plugin(s) to be loaded the next time the client is restarted under the workplace:\n'
211 '\n'
212 ' [%s]\n'
213 ) % workplace
214
215 picker = gmListWidgets.cItemPickerDlg (
216 parent,
217 -1,
218 title = _('Configuring workplace plugins ...'),
219 msg = msg
220 )
221 picker.set_columns(['Available plugins'], ['Active plugins'])
222 available_plugins = gmPlugin.get_installed_plugins(plugin_dir = 'gui')
223 picker.set_choices(available_plugins)
224 picker.set_picks(picks = curr_plugins[:])
225 btn_pressed = picker.ShowModal()
226 if btn_pressed != wx.ID_OK:
227 picker.DestroyLater()
228 return False
229
230 new_plugins = picker.get_picks()
231 picker.DestroyLater()
232 if new_plugins == curr_plugins:
233 return True
234
235 if new_plugins is None:
236 return True
237
238 dbcfg.set (
239 option = 'horstspace.notebook.plugin_load_order',
240 value = new_plugins,
241 workplace = workplace
242 )
243
244 return True
245 #-----------------------------------
246 def edit_old(workplace=None):
247
248 available_plugins = gmPlugin.get_installed_plugins(plugin_dir='gui')
249
250 dbcfg = gmCfg.cCfgSQL()
251
252 if workplace is None:
253 dlg = wx.TextEntryDialog (
254 parent,
255 _('Enter a descriptive name for the new workplace:'),
256 caption = _('Configuring GNUmed workplaces ...'),
257 value = '',
258 style = wx.OK | wx.CENTRE
259 )
260 dlg.ShowModal()
261 workplace = dlg.GetValue().strip()
262 if workplace == '':
263 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...'))
264 return False
265 curr_plugins = []
266 choices = available_plugins
267 else:
268 curr_plugins = gmTools.coalesce(dbcfg.get2 (
269 option = 'horstspace.notebook.plugin_load_order',
270 workplace = workplace,
271 bias = 'workplace'
272 ), []
273 )
274 choices = curr_plugins[:]
275 for p in available_plugins:
276 if p not in choices:
277 choices.append(p)
278
279 sels = range(len(curr_plugins))
280 new_plugins = gmListWidgets.get_choices_from_list (
281 parent = parent,
282 msg = _(
283 '\n'
284 'Select the plugin(s) to be loaded the next time\n'
285 'the client is restarted under the workplace:\n'
286 '\n'
287 ' [%s]'
288 '\n'
289 ) % workplace,
290 caption = _('Configuring GNUmed workplaces ...'),
291 choices = choices,
292 selections = sels,
293 columns = [_('Plugins')],
294 single_selection = False
295 )
296
297 if new_plugins == curr_plugins:
298 return True
299
300 if new_plugins is None:
301 return True
302
303 dbcfg.set (
304 option = 'horstspace.notebook.plugin_load_order',
305 value = new_plugins,
306 workplace = workplace
307 )
308
309 return True
310 #-----------------------------------
311 def clone(workplace=None):
312 if workplace is None:
313 return False
314
315 new_name = wx.GetTextFromUser (
316 message = _('Enter a name for the new workplace !'),
317 caption = _('Cloning workplace'),
318 default_value = '%s-2' % workplace,
319 parent = parent
320 ).strip()
321
322 if new_name == '':
323 return False
324
325 dbcfg = gmCfg.cCfgSQL()
326 opt = 'horstspace.notebook.plugin_load_order'
327
328 plugins = dbcfg.get2 (
329 option = opt,
330 workplace = workplace,
331 bias = 'workplace'
332 )
333
334 dbcfg.set (
335 option = opt,
336 value = plugins,
337 workplace = new_name
338 )
339
340 # FIXME: clone cfg, too
341
342 return True
343 #-----------------------------------
344 def refresh(lctrl):
345 workplaces = gmPraxis.gmCurrentPraxisBranch().workplaces
346 curr_workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace
347 try:
348 sels = [workplaces.index(curr_workplace)]
349 except ValueError:
350 sels = []
351
352 lctrl.set_string_items(workplaces)
353 lctrl.set_selections(selections = sels)
354 #-----------------------------------
355 gmListWidgets.get_choices_from_list (
356 parent = parent,
357 msg = _(
358 '\nSelect the workplace to configure below.\n'
359 '\n'
360 'The currently active workplace is preselected.\n'
361 ),
362 caption = _('Configuring GNUmed workplaces ...'),
363 columns = [_('Workplace')],
364 single_selection = True,
365 refresh_callback = refresh,
366 edit_callback = edit,
367 new_callback = edit,
368 delete_callback = delete,
369 left_extra_button = (_('Clone'), _('Clone the selected workplace'), clone)
370 )
371
372 #============================================================
373 from Gnumed.wxGladeWidgets import wxgGreetingEditorDlg
374
376
378 wxgGreetingEditorDlg.wxgGreetingEditorDlg.__init__(self, *args, **kwargs)
379
380 self.praxis = gmPraxis.gmCurrentPraxisBranch()
381 self._TCTRL_message.SetValue(self.praxis.db_logon_banner)
382 #--------------------------------------------------------
383 # event handlers
384 #--------------------------------------------------------
391
392 #============================================================
394
395 branches = gmPraxis.get_praxis_branches()
396
397 if len(branches) == 0:
398 if not set_active_praxis_branch(parent = parent, no_parent = False):
399 return None
400
401 # FIXME: needs implementation
402
403 #============================================================
405
406 if no_parent:
407 parent = None
408 else:
409 if parent is None:
410 parent = wx.GetApp().GetTopWindow()
411
412 branches = gmPraxis.get_praxis_branches()
413
414 if len(branches) == 1:
415 _log.debug('only one praxis branch configured')
416 gmPraxis.gmCurrentPraxisBranch(branches[0])
417 _log.debug('activated branch')
418 return True
419
420 if len(branches) == 0:
421 orgs = gmOrganization.get_orgs()
422 if len(orgs) == 0:
423 pk_cat = gmOrganization.create_org_category(category = 'Praxis')
424 org = gmOrganization.create_org(_('Your praxis'), pk_cat)
425 unit = org.add_unit(_('Your branch'))
426 branch = gmPraxis.create_praxis_branch(pk_org_unit = unit['pk_org_unit'])
427 _log.debug('auto-created praxis branch because no organizations existed: %s', branch)
428 gmPraxis.gmCurrentPraxisBranch(branch)
429 gmGuiHelpers.gm_show_info (
430 title = _('Praxis configuration ...'),
431 info = _(
432 'GNUmed has auto-created the following\n'
433 'praxis branch for you (which you can\n'
434 'later configure as needed):\n'
435 '\n'
436 '%s'
437 ) % branch.format()
438 )
439 return True
440
441 if len(orgs) == 1:
442 units = orgs[0].units
443 if len(units) == 1:
444 branch = gmPraxis.create_praxis_branch(pk_org_unit = units[0]['pk_org_unit'])
445 _log.debug('auto-selected praxis branch because only one organization with only one unit existed: %s', branch)
446 gmPraxis.gmCurrentPraxisBranch(branch)
447 gmGuiHelpers.gm_show_info (
448 title = _('Praxis configuration ...'),
449 info = _(
450 'GNUmed has auto-selected the following\n'
451 'praxis branch for you (which you can\n'
452 'later configure as needed):\n'
453 '\n'
454 '%s'
455 ) % branch.format()
456 )
457 return True
458
459 _log.debug('no praxis branches configured, selecting from organization units')
460 msg = _(
461 'No praxis branches configured currently.\n'
462 '\n'
463 'You MUST select one unit of an organization to be the initial\n'
464 'branch (site, office) which you are logging in from.'
465 )
466 unit = gmOrganizationWidgets.select_org_unit(msg = msg, no_parent = True)
467 if unit is None:
468 _log.warning('no organization unit selected, aborting')
469 return False
470 _log.debug('org unit selected as praxis branch: %s', unit)
471 branch = gmPraxis.create_praxis_branch(pk_org_unit = unit['pk_org_unit'])
472 _log.debug('created praxis branch: %s', branch)
473 gmPraxis.gmCurrentPraxisBranch(branch)
474 return True
475
476 #--------------------
477 def refresh(lctrl):
478 branches = gmPraxis.get_praxis_branches()
479 items = [
480 [ b['branch'],
481 gmTools.coalesce(b['l10n_unit_category'], '')
482 ] for b in branches
483 ]
484 lctrl.set_string_items(items = items)
485 lctrl.set_data(data = branches)
486 #--------------------
487 branch = gmListWidgets.get_choices_from_list (
488 parent = parent,
489 msg = _("Select the branch of praxis [%s] which you are logging in from.\n") % branches[0]['praxis'],
490 caption = _('Praxis branch selection ...'),
491 columns = [_('Branch'), _('Branch type')],
492 can_return_empty = False,
493 single_selection = True,
494 refresh_callback = refresh
495 )
496 if branch is None:
497 _log.warning('no praxis branch selected, aborting')
498 return False
499 gmPraxis.gmCurrentPraxisBranch(branch)
500 return True
501
502 #============================================================
504
505 if parent is None:
506 parent = wx.GetApp().GetTopWindow()
507
508 #---------------------------
509 def get_unit_tooltip(unit):
510 if unit is None:
511 return None
512 return '\n'.join(unit.format(with_address = True, with_org = True, with_comms = True))
513 #---------------------------
514 def manage_orgs():
515 gmOrganizationWidgets.manage_orgs(parent = parent)
516 #---------------------------
517
518 branches = gmPraxis.get_praxis_branches()
519 org = branches[0].organization
520 praxis = branches[0]['praxis']
521
522 msg = _(
523 'Pick those units of "%s" which are branches of your praxis !\n'
524 '\n'
525 'Note that no other client should be connected at this time.\n'
526 '\n'
527 'If you want to select another organization entirely\n'
528 'first remove all existing branches.\n'
529 ) % praxis
530
531 picker = gmListWidgets.cItemPickerDlg(parent, -1, msg = msg)
532 picker.extra_button = (
533 _('Manage units'),
534 _('Manage organizations and their units'),
535 manage_orgs
536 )
537 picker.left_item_tooltip_callback = get_unit_tooltip
538 picker.right_item_tooltip_callback = get_unit_tooltip
539 picker.set_columns(columns = [_('Units of "%s"') % praxis], columns_right = [_('Branches of your praxis')])
540 units = org.units
541 branch_unit_pks = [b['pk_org_unit'] for b in branches]
542 branch_units = []
543 for unit in units:
544 if unit['pk_org_unit'] in branch_unit_pks:
545 branch_units.append(unit)
546 items = [ '%s%s' % (u['unit'], gmTools.coalesce(u['l10n_unit_category'], '', ' (%s)')) for u in units ]
547 picker.set_choices(choices = items, data = units)
548 items = [ '%s%s' % (u['unit'], gmTools.coalesce(u['l10n_unit_category'], '', ' (%s)')) for u in branch_units ]
549 picker.set_picks(picks = items, data = branch_units)
550 del units
551 del branch_unit_pks
552 del branch_units
553 del items
554
555 result = picker.ShowModal()
556
557 if result == wx.ID_CANCEL:
558 picker.DestroyLater()
559 return None
560
561 picks = picker.picks
562 picker.DestroyLater()
563
564 failed_delete_msg = _(
565 'Cannot delete praxis branch(es).\n'
566 '\n'
567 'There are probably clients logged in\n'
568 'from other locations. You need to log out\n'
569 'all but this client before the praxis can\n'
570 'be reconfigured.'
571 )
572
573 if len(picks) == 0:
574 if not gmPraxis.delete_praxis_branches():
575 gmGuiHelpers.gm_show_error (
576 error = failed_delete_msg,
577 title = _('Configuring praxis ...')
578 )
579 return False
580 while not set_active_praxis_branch(parent = parent):
581 pass
582 return
583
584 pk_picked_units = [p['pk_org_unit'] for p in picks]
585 pk_branches_to_keep = [
586 b['pk_praxis_branch'] for b in gmPraxis.get_praxis_branches()
587 if b['pk_org_unit'] in pk_picked_units
588 ]
589 if len(pk_branches_to_keep) == 0:
590 if not gmPraxis.delete_praxis_branches():
591 gmGuiHelpers.gm_show_error (
592 error = failed_delete_msg,
593 title = _('Configuring praxis ...')
594 )
595 return False
596 else:
597 if not gmPraxis.delete_praxis_branches(except_pk_praxis_branches = pk_branches_to_keep):
598 gmGuiHelpers.gm_show_error (
599 error = failed_delete_msg,
600 title = _('Configuring praxis ...')
601 )
602 return False
603 gmPraxis.create_praxis_branches(pk_org_units = pk_picked_units)
604
605 # detect whether active branch in kept branches
606 if gmPraxis.gmCurrentPraxisBranch()['pk_praxis_branch'] in pk_branches_to_keep:
607 return
608
609 while not set_active_praxis_branch(parent = parent):
610 pass
611
612 #============================================================
614
616 query = """(
617 SELECT
618 pk_praxis_branch AS data,
619 branch || ' (' || praxis || ')' AS field_label,
620 branch || coalesce(' (' || l10n_unit_category || ')', '') || ' of ' || l10n_organization_category || ' "' || praxis || '"' AS list_label
621 FROM
622 dem.v_praxis_branches
623 WHERE
624 branch %(fragment_condition)s
625
626 ) UNION (
627
628 SELECT
629 pk_praxis_branch AS data,
630 branch || ' (' || praxis || ')' AS field_label,
631 branch || coalesce(' (' || l10n_unit_category || ')', '') || ' of ' || l10n_organization_category || ' "' || praxis || '"' AS list_label
632 FROM
633 dem.v_praxis_branches
634 WHERE
635 praxis %(fragment_condition)s
636
637 ) UNION (
638
639 SELECT
640 pk_praxis_branch AS data,
641 branch || ' (' || praxis || ')' AS field_label,
642 branch || coalesce(' (' || l10n_unit_category || ')', '') || ' of ' || l10n_organization_category || ' "' || praxis || '"' AS list_label
643 FROM
644 dem.v_praxis_branches
645 WHERE
646 l10n_unit_category %(fragment_condition)s
647
648 )
649 ORDER BY
650 list_label
651 LIMIT 50"""
652 mp = gmMatchProvider.cMatchProvider_SQL2(queries=query)
653 mp.setThresholds(1, 2, 4)
654 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
655 self.SetToolTip(_("Select a praxis branch."))
656 self.matcher = mp
657 self.selection_only = True
658 self.picklist_delay = 300
659 #--------------------------------------------------------
661 if self.GetData() is None:
662 return None
663 branch = self._data2instance()
664 if branch is None:
665 return None
666 return branch.format()
667 #--------------------------------------------------------
669 if self.GetData() is None:
670 return None
671 return gmPraxis.cPraxisBranch(aPK_obj = self.GetData())
672
673 #============================================================
674 # main
675 #------------------------------------------------------------
676 if __name__ == "__main__":
677
678 if len(sys.argv) < 2:
679 sys.exit()
680
681 if sys.argv[1] != 'test':
682 sys.exit()
683
684 # from Gnumed.pycommon import gmPG2
685 # from Gnumed.pycommon import gmI18N
686 # gmI18N.activate_locale()
687 # gmI18N.install_domain()
688
692
693 #--------------------------------------------------------
694 #test_org_unit_prw()
695 #test_configure_wp_plugins()
696
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Thu Jul 23 01:55:31 2020 | http://epydoc.sourceforge.net |