| Home | Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding: utf-8 -*-
2
3 #from __future__ import print_function
4
5 __doc__ = """GNUmed drug / substance reference widgets."""
6
7 #================================================================
8 __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>"
9 __license__ = "GPL v2 or later"
10
11 import logging
12 import sys
13 import os.path
14 import decimal
15
16
17 import wx
18
19
20 if __name__ == '__main__':
21 sys.path.insert(0, '../../')
22 from Gnumed.pycommon import gmI18N
23 gmI18N.activate_locale()
24 gmI18N.install_domain(domain = 'gnumed')
25
26 from Gnumed.pycommon import gmDispatcher
27 from Gnumed.pycommon import gmCfg
28 from Gnumed.pycommon import gmShellAPI
29 from Gnumed.pycommon import gmTools
30 from Gnumed.pycommon import gmMatchProvider
31
32 from Gnumed.business import gmPerson
33 from Gnumed.business import gmPraxis
34 from Gnumed.business import gmMedication
35 from Gnumed.business import gmDrugDataSources
36 from Gnumed.business import gmATC
37
38 from Gnumed.wxpython import gmGuiHelpers
39 from Gnumed.wxpython import gmEditArea
40 from Gnumed.wxpython import gmCfgWidgets
41 from Gnumed.wxpython import gmListWidgets
42 from Gnumed.wxpython import gmPhraseWheel
43
44
45 _log = logging.getLogger('gm.ui')
46
47 #============================================================
48 # generic drug database access
49 #------------------------------------------------------------
51 gmCfgWidgets.configure_string_from_list_option (
52 parent = parent,
53 message = _(
54 '\n'
55 'Please select the default drug data source from the list below.\n'
56 '\n'
57 'Note that to actually use it you need to have the database installed, too.'
58 ),
59 option = 'external.drug_data.default_source',
60 bias = 'user',
61 default_value = None,
62 choices = gmDrugDataSources.drug_data_source_interfaces.keys(),
63 columns = [_('Drug data source')],
64 data = gmDrugDataSources.drug_data_source_interfaces.keys(),
65 caption = _('Configuring default drug data source')
66 )
67
68 #============================================================
70 dbcfg = gmCfg.cCfgSQL()
71
72 # load from option
73 default_db = dbcfg.get2 (
74 option = 'external.drug_data.default_source',
75 workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace,
76 bias = 'workplace'
77 )
78
79 # not configured -> try to configure
80 if default_db is None:
81 gmDispatcher.send('statustext', msg = _('No default drug database configured.'), beep = True)
82 configure_drug_data_source(parent = parent)
83 default_db = dbcfg.get2 (
84 option = 'external.drug_data.default_source',
85 workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace,
86 bias = 'workplace'
87 )
88 # still not configured -> return
89 if default_db is None:
90 gmGuiHelpers.gm_show_error (
91 aMessage = _('There is no default drug database configured.'),
92 aTitle = _('Jumping to drug database')
93 )
94 return None
95
96 # now it MUST be configured (either newly or previously)
97 # but also *validly* ?
98 try:
99 drug_db = gmDrugDataSources.drug_data_source_interfaces[default_db]()
100 except KeyError:
101 # not valid
102 _log.error('faulty default drug data source configuration: %s', default_db)
103 # try to configure
104 configure_drug_data_source(parent = parent)
105 default_db = dbcfg.get2 (
106 option = 'external.drug_data.default_source',
107 workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace,
108 bias = 'workplace'
109 )
110 # deconfigured or aborted (and thusly still misconfigured) ?
111 try:
112 drug_db = gmDrugDataSources.drug_data_source_interfaces[default_db]()
113 except KeyError:
114 _log.error('still faulty default drug data source configuration: %s', default_db)
115 return None
116
117 if patient is not None:
118 drug_db.patient = patient
119
120 return drug_db
121
122 #============================================================
124 drug_db = get_drug_database(patient = patient)
125 if drug_db is None:
126 return
127 drug_db.switch_to_frontend(blocking = False)
128
129 #============================================================
131
132 if import_drugs and (emr is None):
133 gmDispatcher.send('statustext', msg = _('Cannot import drugs from IFAP into chart without chart.'))
134 return False
135
136 dbcfg = gmCfg.cCfgSQL()
137
138 ifap_cmd = dbcfg.get2 (
139 option = 'external.ifap-win.shell_command',
140 workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace,
141 bias = 'workplace',
142 default = 'wine "C:\Ifapwin\WIAMDB.EXE"'
143 )
144 found, binary = gmShellAPI.detect_external_binary(ifap_cmd)
145 if not found:
146 gmDispatcher.send('statustext', msg = _('Cannot call IFAP via [%s].') % ifap_cmd)
147 return False
148 ifap_cmd = binary
149
150 if import_drugs:
151 transfer_file = os.path.expanduser(dbcfg.get2 (
152 option = 'external.ifap-win.transfer_file',
153 workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace,
154 bias = 'workplace',
155 default = '~/.wine/drive_c/Ifapwin/ifap2gnumed.csv'
156 ))
157 # file must exist for Ifap to write into it
158 try:
159 f = io.open(transfer_file, mode = 'wt').close()
160 except IOError:
161 _log.exception('Cannot create IFAP <-> GNUmed transfer file [%s]', transfer_file)
162 gmDispatcher.send('statustext', msg = _('Cannot create IFAP <-> GNUmed transfer file [%s].') % transfer_file)
163 return False
164
165 wx.BeginBusyCursor()
166 gmShellAPI.run_command_in_shell(command = ifap_cmd, blocking = import_drugs)
167 wx.EndBusyCursor()
168
169 if import_drugs:
170 # COMMENT: this file must exist PRIOR to invoking IFAP
171 # COMMENT: or else IFAP will not write data into it ...
172 try:
173 csv_file = io.open(transfer_file, mode = 'rt', encoding = 'latin1') # FIXME: encoding unknown
174 except Exception:
175 _log.exception('cannot access [%s]', fname)
176 csv_file = None
177
178 if csv_file is not None:
179 import csv
180 csv_lines = csv.DictReader (
181 csv_file,
182 fieldnames = 'PZN Handelsname Form Abpackungsmenge Einheit Preis1 Hersteller Preis2 rezeptpflichtig Festbetrag Packungszahl Packungsgr\xf6\xdfe'.split(),
183 delimiter = ';'
184 )
185 # dummy episode for now
186 epi = emr.add_episode(episode_name = _('Current medication'))
187 for line in csv_lines:
188 narr = '%sx %s %s %s (\u2258 %s %s) von %s (%s)' % (
189 line['Packungszahl'].strip(),
190 line['Handelsname'].strip(),
191 line['Form'].strip(),
192 line['Packungsgr\xf6\xdfe'].strip(),
193 line['Abpackungsmenge'].strip(),
194 line['Einheit'].strip(),
195 line['Hersteller'].strip(),
196 line['PZN'].strip()
197 )
198 emr.add_clin_narrative(note = narr, soap_cat = 's', episode = epi)
199 csv_file.close()
200
201 return True
202
203 #============================================================
204 # substances widgets
205 #------------------------------------------------------------
207
208 if substance is not None:
209 if substance.is_in_use_by_patients:
210 gmDispatcher.send(signal = 'statustext', msg = _('Cannot edit this substance. It is in use.'), beep = True)
211 return False
212
213 ea = cSubstanceEAPnl(parent, -1)
214 ea.data = substance
215 ea.mode = gmTools.coalesce(substance, 'new', 'edit')
216 dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea, single_entry = single_entry)
217 dlg.SetTitle(gmTools.coalesce(substance, _('Adding new substance'), _('Editing substance')))
218 if dlg.ShowModal() == wx.ID_OK:
219 dlg.DestroyLater()
220 return True
221 dlg.DestroyLater()
222 return False
223
224 #------------------------------------------------------------
226
227 if parent is None:
228 parent = wx.GetApp().GetTopWindow()
229
230 #------------------------------------------------------------
231 def add_from_db(substance):
232 drug_db = get_drug_database(parent = parent)
233 if drug_db is None:
234 return False
235 drug_db.import_drugs()
236 return True
237
238 #------------------------------------------------------------
239 def edit(substance=None):
240 return edit_substance(parent = parent, substance = substance, single_entry = (substance is not None))
241
242 #------------------------------------------------------------
243 def delete(substance):
244 if substance.is_in_use_by_patients:
245 gmDispatcher.send(signal = 'statustext', msg = _('Cannot delete this substance. It is in use.'), beep = True)
246 return False
247 return gmMedication.delete_substance(pk_substance = substance['pk_substance'])
248
249 #------------------------------------------------------------
250 def get_item_tooltip(substance):
251 if not isinstance(substance, gmMedication.cSubstance):
252 return None
253 return substance.format()
254
255 #------------------------------------------------------------
256 def refresh(lctrl):
257 substs = gmMedication.get_substances(order_by = 'substance')
258 items = [ [
259 s['substance'],
260 gmTools.coalesce(s['atc'], ''),
261 gmTools.coalesce(s['intake_instructions'], ''),
262 s['pk_substance']
263 ] for s in substs ]
264 lctrl.set_string_items(items)
265 lctrl.set_data(substs)
266
267 #------------------------------------------------------------
268 gmListWidgets.get_choices_from_list (
269 parent = parent,
270 caption = _('Substances registered with GNUmed.'),
271 columns = [_('Substance'), 'ATC', _('Instructions'), '#'],
272 single_selection = True,
273 new_callback = edit,
274 edit_callback = edit,
275 delete_callback = delete,
276 refresh_callback = refresh,
277 left_extra_button = (_('Import'), _('Import substances from a drug database.'), add_from_db),
278 list_tooltip_callback = get_item_tooltip
279 )
280
281 #------------------------------------------------------------
282 from Gnumed.wxGladeWidgets import wxgSubstanceEAPnl
283
285
287
288 try:
289 data = kwargs['substance']
290 del kwargs['substance']
291 except KeyError:
292 data = None
293
294 wxgSubstanceEAPnl.wxgSubstanceEAPnl.__init__(self, *args, **kwargs)
295 gmEditArea.cGenericEditAreaMixin.__init__(self)
296
297 # Code using this mixin should set mode and data
298 # after instantiating the class:
299 self.mode = 'new'
300 self.data = data
301 if data is not None:
302 self.mode = 'edit'
303
304 self.__init_ui()
305
306 #----------------------------------------------------------------
308 self._LCTRL_loincs.set_columns([_('LOINC'), _('Interval'), _('Comment')])
309
310 #----------------------------------------------------------------
311 # generic Edit Area mixin API
312 #----------------------------------------------------------------
314
315 validity = True
316
317 if self._TCTRL_substance.GetValue().strip() == '':
318 validity = False
319 self.display_tctrl_as_valid(tctrl = self._TCTRL_substance, valid = False)
320 self._TCTRL_substance.SetFocus()
321 else:
322 self.display_tctrl_as_valid(tctrl = self._TCTRL_substance, valid = True)
323
324 if validity is False:
325 self.StatusText = _('Cannot save: Substance name missing.')
326
327 return validity
328
329 #----------------------------------------------------------------
331 subst = gmMedication.create_substance (
332 substance = self._TCTRL_substance.GetValue().strip(),
333 atc = self._PRW_atc.GetData()
334 )
335 subst['intake_instructions'] = self._TCTRL_instructions.GetValue().strip()
336 success, data = subst.save()
337 if not success:
338 err, msg = data
339 _log.error(err)
340 _log.error(msg)
341 self.StatusText = _('Error saving substance. %s') % msg
342 return False
343
344 loincs = self._LCTRL_loincs.item_data
345 if loincs is not None:
346 if len(loincs) > 0:
347 subst.loincs = loincs
348
349 self.data = subst
350 return True
351
352 #----------------------------------------------------------------
354 self.data['substance'] = self._TCTRL_substance.GetValue().strip()
355 self.data['atc'] = self._PRW_atc.GetData()
356 self.data['intake_instructions'] = self._TCTRL_instructions.GetValue().strip()
357 success, data = self.data.save()
358 if not success:
359 err, msg = data
360 _log.error(err)
361 _log.error(msg)
362 self.StatusText = _('Error saving substance. %s') % msg
363 return False
364
365 loincs = self._LCTRL_loincs.item_data
366 if loincs is not None:
367 if len(loincs) > 0:
368 self.data.loincs = loincs
369
370 return True
371
372 #----------------------------------------------------------------
374 self._TCTRL_substance.SetValue('')
375 self._PRW_atc.SetText('', None)
376 self._TCTRL_instructions.SetValue('')
377 self._PRW_loinc.SetText('', None)
378 self._LCTRL_loincs.set_string_items()
379
380 self._TCTRL_substance.SetFocus()
381
382 #----------------------------------------------------------------
384 self._TCTRL_substance.SetValue(self.data['substance'])
385 self._PRW_atc.SetText(gmTools.coalesce(self.data['atc'], ''), self.data['atc'])
386 self._TCTRL_instructions.SetValue(gmTools.coalesce(self.data['intake_instructions'], ''))
387 self._PRW_loinc.SetText('', None)
388 if len(self.data['loincs']) == 0:
389 self._LCTRL_loincs.set_string_items()
390 else:
391 self._LCTRL_loincs.set_string_items([ [l['loinc'], gmTools.coalesce(l['max_age_str'], ''), gmTools.coalesce(l['comment'], '')] for l in self.data['loincs' ]])
392 self._LCTRL_loincs.set_data([ l['loinc'] for l in self.data['loincs'] ])
393
394 self._TCTRL_substance.SetFocus()
395
396 #----------------------------------------------------------------
399
400 #----------------------------------------------------------------
401 # event handlers
402 #----------------------------------------------------------------
415
416 #----------------------------------------------------------------
419
420 #------------------------------------------------------------
422
424
425 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
426 query = """
427 SELECT DISTINCT ON (list_label)
428 list_label,
429 field_label,
430 data
431 FROM (
432 SELECT
433 description AS list_label,
434 description AS field_label,
435 pk AS data
436 FROM ref.substance
437 WHERE
438 description %(fragment_condition)s
439
440 UNION ALL
441
442 SELECT
443 term AS list_label,
444 term AS field_label,
445 NULL::integer AS data
446 FROM ref.atc
447 WHERE
448 term %(fragment_condition)s
449
450 ) AS candidates
451 ORDER BY list_label
452 LIMIT 50
453 """
454 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query)
455 mp.setThresholds(1, 2, 4)
456 # mp.word_separators = '[ \t=+&:@]+'
457 self.SetToolTip(_('The substance name.'))
458 self.matcher = mp
459 self.selection_only = False
460 self.phrase_separators = None
461
462 #--------------------------------------------------------
465
466 #============================================================
467 # substance dose widgets
468 #------------------------------------------------------------
470
471 if substance_dose is not None:
472 if substance_dose.is_in_use_by_patients:
473 gmDispatcher.send(signal = 'statustext', msg = _('Cannot edit this substance. It is in use.'), beep = True)
474 return False
475
476 ea = cSubstanceDoseEAPnl(parent, -1)
477 ea.data = substance_dose
478 ea.mode = gmTools.coalesce(substance_dose, 'new', 'edit')
479 dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea, single_entry = single_entry)
480 dlg.SetTitle(gmTools.coalesce(substance_dose, _('Adding new substance dose'), _('Editing substance dose')))
481 if dlg.ShowModal() == wx.ID_OK:
482 dlg.DestroyLater()
483 return True
484 dlg.DestroyLater()
485 return False
486
487 #------------------------------------------------------------
489
490 if parent is None:
491 parent = wx.GetApp().GetTopWindow()
492
493 #------------------------------------------------------------
494 def add_from_db(substance):
495 drug_db = get_drug_database(parent = parent)
496 if drug_db is None:
497 return False
498 drug_db.import_drugs()
499 return True
500
501 #------------------------------------------------------------
502 def edit(substance_dose=None):
503 return edit_substance_dose(parent = parent, substance_dose = substance_dose, single_entry = (substance_dose is not None))
504
505 #------------------------------------------------------------
506 def delete(substance_dose):
507 if substance_dose.is_in_use_by_patients:
508 gmDispatcher.send(signal = 'statustext', msg = _('Cannot delete this substance. It is in use.'), beep = True)
509 return False
510 return gmMedication.delete_substance_dose(pk_dose = substance_dose['pk_dose'])
511
512 #------------------------------------------------------------
513 def refresh(lctrl):
514 if vaccine_indications_only:
515 substs = [ s for s in gmMedication.get_substance_doses(order_by = 'substance') if gmTools.coalesce(s['atc_substance'], '').startswith('J07') ]
516 else:
517 substs = gmMedication.get_substance_doses(order_by = 'substance')
518 items = [ [
519 s['substance'],
520 s['amount'],
521 s.formatted_units,
522 gmTools.coalesce(s['atc_substance'], ''),
523 gmTools.coalesce(s['intake_instructions'], ''),
524 s['pk_dose']
525 ] for s in substs ]
526 lctrl.set_string_items(items)
527 lctrl.set_data(substs)
528
529 #------------------------------------------------------------
530 def get_item_tooltip(substance_dose):
531 if not isinstance(substance_dose, gmMedication.cSubstanceDose):
532 return None
533 return substance_dose.format(include_loincs = True)
534
535 #------------------------------------------------------------
536 return gmListWidgets.get_choices_from_list (
537 parent = parent,
538 caption = _('Substance doses registered with GNUmed.'),
539 columns = [_('Substance'), _('Amount'), _('Unit'), 'ATC', _('Instructions'), '#'],
540 single_selection = False,
541 can_return_empty = False,
542 new_callback = edit,
543 edit_callback = edit,
544 delete_callback = delete,
545 refresh_callback = refresh,
546 left_extra_button = (_('Import'), _('Import substance doses from a drug database.'), add_from_db),
547 list_tooltip_callback = get_item_tooltip
548 )
549
550 #------------------------------------------------------------
551 from Gnumed.wxGladeWidgets import wxgSubstanceDoseEAPnl
552
553 -class cSubstanceDoseEAPnl(wxgSubstanceDoseEAPnl.wxgSubstanceDoseEAPnl, gmEditArea.cGenericEditAreaMixin):
554
556
557 try:
558 data = kwargs['substance']
559 del kwargs['substance']
560 except KeyError:
561 data = None
562
563 wxgSubstanceDoseEAPnl.wxgSubstanceDoseEAPnl.__init__(self, *args, **kwargs)
564 gmEditArea.cGenericEditAreaMixin.__init__(self)
565
566 # Code using this mixin should set mode and data
567 # after instantiating the class:
568 self.mode = 'new'
569 self.data = data
570 if data is not None:
571 self.mode = 'edit'
572
573 self.__init_ui()
574
575 #----------------------------------------------------------------
577 self._PRW_substance.add_callback_on_modified(callback = self.__refresh_info)
578 self._PRW_substance.add_callback_on_selection(callback = self.__refresh_info)
579 self._TCTRL_amount.add_callback_on_modified(callback = self.__refresh_info)
580 self._PRW_unit.add_callback_on_modified(callback = self.__refresh_info)
581 self._PRW_unit.add_callback_on_selection(callback = self.__refresh_info)
582 self._PRW_dose_unit.add_callback_on_modified(callback = self.__refresh_info)
583 self._PRW_dose_unit.add_callback_on_selection(callback = self.__refresh_info)
584
585 #----------------------------------------------------------------
587 subst = self._PRW_substance.GetValue().strip()
588 if subst == '':
589 subst = '?'
590 amount = self._TCTRL_amount.GetValue().strip()
591 if amount == '':
592 amount = '?'
593 unit = self._PRW_unit.GetValue().strip()
594 if unit == '':
595 unit = '?'
596 dose_unit = self._PRW_dose_unit.GetValue().strip()
597 if dose_unit == '':
598 dose_unit = _('<delivery unit>')
599 self._LBL_info.SetLabel('%s %s %s / %s' % (subst, amount, unit, dose_unit))
600 self.Refresh()
601
602 #----------------------------------------------------------------
603 # generic Edit Area mixin API
604 #----------------------------------------------------------------
606
607 validity = True
608
609 if self._PRW_substance.GetValue().strip() == '':
610 validity = False
611 self._PRW_substance.display_as_valid(valid = False)
612 self._PRW_substance.SetFocus()
613 else:
614 self._PRW_substance.display_as_valid(valid = True)
615
616 try:
617 decimal.Decimal(self._TCTRL_amount.GetValue().strip().replace(',', '.'))
618 self.display_tctrl_as_valid(tctrl = self._TCTRL_amount, valid = True)
619 except (TypeError, decimal.InvalidOperation):
620 validity = False
621 self.display_tctrl_as_valid(tctrl = self._TCTRL_amount, valid = False)
622 self._TCTRL_amount.SetFocus()
623
624 if self._PRW_unit.GetValue().strip() == '':
625 validity = False
626 self._PRW_unit.display_as_valid(valid = False)
627 self._PRW_unit.SetFocus()
628 else:
629 self._PRW_unit.display_as_valid(valid = True)
630
631 if validity is False:
632 self.StatusText = _('Cannot save substance dose. Missing essential input.')
633
634 return validity
635
636 #----------------------------------------------------------------
638 pk_subst = self._PRW_substance.GetData()
639 dose = gmMedication.create_substance_dose (
640 pk_substance = pk_subst,
641 substance = self._PRW_substance.GetValue().strip() if (pk_subst is None) else None,
642 amount = decimal.Decimal(self._TCTRL_amount.GetValue().strip().replace(',', '.')),
643 unit = gmTools.coalesce(self._PRW_unit.GetData(), self._PRW_unit.GetValue().strip(), function4value = ('strip', None)),
644 dose_unit = gmTools.coalesce(self._PRW_dose_unit.GetData(), self._PRW_dose_unit.GetValue().strip(), function4value = ('strip', None))
645 )
646 success, data = dose.save()
647 if not success:
648 err, msg = data
649 _log.error(err)
650 _log.error(msg)
651 self.StatusText = _('Cannot create substance dose. %s') % msg
652 return False
653
654 self.data = dose
655 return True
656
657 #----------------------------------------------------------------
659 #self.data['pk_substance'] = self._PRW_substance.GetData()
660 self.data['amount'] = decimal.Decimal(self._TCTRL_amount.GetValue().strip().replace(',', '.'))
661 self.data['unit'] = gmTools.coalesce(self._PRW_unit.GetData(), self._PRW_unit.GetValue().strip(), function4value = ('strip', None))
662 self.data['dose_unit'] = gmTools.coalesce(self._PRW_dose_unit.GetData(), self._PRW_dose_unit.GetValue().strip(), function4value = ('strip', None))
663 success, data = self.data.save()
664
665 if not success:
666 err, msg = data
667 _log.error(err)
668 _log.error(msg)
669 self.StatusText = _('Cannot save substance dose. %s') % msg
670 return False
671
672 return True
673
674 #----------------------------------------------------------------
676 self._PRW_substance.SetText('', None)
677 self._TCTRL_amount.SetValue('')
678 self._PRW_unit.SetText('', None)
679 self._PRW_dose_unit.SetText('', None)
680 self._LBL_info.SetLabel('')
681
682 self._PRW_substance.SetFocus()
683
684 #----------------------------------------------------------------
686 self._PRW_substance.SetText(self.data['substance'], self.data['pk_substance'])
687 self._PRW_substance.Disable()
688 self._TCTRL_amount.SetValue('%s' % self.data['amount'])
689 self._PRW_unit.SetText(self.data['unit'], self.data['unit'])
690 self._PRW_dose_unit.SetText(gmTools.coalesce(self.data['dose_unit'], ''), self.data['dose_unit'])
691
692 self._PRW_substance.SetFocus()
693
694 #----------------------------------------------------------------
697
698 #============================================================
699 # drug component widgets
700 #------------------------------------------------------------
702
703 if parent is None:
704 parent = wx.GetApp().GetTopWindow()
705
706 #------------------------------------------------------------
707 def edit(component=None):
708 substance_dose = gmMedication.cSubstanceDose(aPK_obj = component['pk_dose'])
709 return edit_substance_dose(parent = parent, substance_dose = substance_dose, single_entry = True)
710
711 #------------------------------------------------------------
712 def delete(component):
713 if component.is_in_use_by_patients:
714 gmDispatcher.send(signal = 'statustext', msg = _('Cannot remove this component from the drug. It is in use.'), beep = True)
715 return False
716 return component.containing_drug.remove_component(pk_component = component['pk_component'])
717
718 #------------------------------------------------------------
719 def refresh(lctrl):
720 comps = gmMedication.get_drug_components()
721 items = [ [
722 '%s%s' % (c['substance'], gmTools.coalesce(c['atc_substance'], '', ' [%s]')),
723 '%s %s' % (c['amount'], c.formatted_units),
724 '%s%s' % (c['product'], gmTools.coalesce(c['atc_drug'], '', ' [%s]')),
725 c['l10n_preparation'],
726 gmTools.coalesce(c['external_code'], '', '%%s [%s]' % c['external_code_type']),
727 c['pk_component']
728 ] for c in comps ]
729 lctrl.set_string_items(items)
730 lctrl.set_data(comps)
731
732 #------------------------------------------------------------
733 def get_item_tooltip(component):
734 if not isinstance(component, gmMedication.cDrugComponent):
735 return None
736 return component.format(include_loincs = True)
737
738 #------------------------------------------------------------
739 gmListWidgets.get_choices_from_list (
740 parent = parent,
741 caption = _('Drug components currently known to GNUmed'),
742 columns = [_('Component'), _('Strength'), _('Product name'), _('Preparation'), _('Code'), '#'],
743 single_selection = True,
744 #new_callback = edit,
745 edit_callback = edit,
746 delete_callback = delete,
747 refresh_callback = refresh,
748 list_tooltip_callback = get_item_tooltip
749 )
750
751 #------------------------------------------------------------
753 ea = cDrugComponentEAPnl(parent, -1)
754 ea.data = drug_component
755 ea.mode = gmTools.coalesce(drug_component, 'new', 'edit')
756 dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea, single_entry = single_entry)
757 dlg.SetTitle(gmTools.coalesce(drug_component, _('Adding new drug component'), _('Editing drug component')))
758 if dlg.ShowModal() == wx.ID_OK:
759 dlg.DestroyLater()
760 return True
761 dlg.DestroyLater()
762 return False
763
764 #------------------------------------------------------------
765 from Gnumed.wxGladeWidgets import wxgDrugComponentEAPnl
766
767 -class cDrugComponentEAPnl(wxgDrugComponentEAPnl.wxgDrugComponentEAPnl, gmEditArea.cGenericEditAreaMixin):
768
770
771 try:
772 data = kwargs['component']
773 del kwargs['component']
774 except KeyError:
775 data = None
776
777 wxgDrugComponentEAPnl.wxgDrugComponentEAPnl.__init__(self, *args, **kwargs)
778 gmEditArea.cGenericEditAreaMixin.__init__(self)
779
780 # Code using this mixin should set mode and data
781 # after instantiating the class:
782 self.mode = 'new'
783 self.data = data
784 if data is not None:
785 self.mode = 'edit'
786
787 #self.__init_ui()
788 #----------------------------------------------------------------
789 # def __init_ui(self):
790 # # adjust phrasewheels etc
791 #----------------------------------------------------------------
792 # generic Edit Area mixin API
793 #----------------------------------------------------------------
795 if self.data is not None:
796 if self.data['is_in_use']:
797 self.StatusText = _('Cannot edit drug component. It is in use.')
798 return False
799
800 validity = True
801
802 if self._PRW_substance.GetData() is None:
803 validity = False
804 self._PRW_substance.display_as_valid(False)
805 else:
806 self._PRW_substance.display_as_valid(True)
807
808 val = self._TCTRL_amount.GetValue().strip().replace(',', '.', 1)
809 try:
810 decimal.Decimal(val)
811 self.display_tctrl_as_valid(tctrl = self._TCTRL_amount, valid = True)
812 except Exception:
813 validity = False
814 self.display_tctrl_as_valid(tctrl = self._TCTRL_amount, valid = False)
815
816 if self._PRW_unit.GetValue().strip() == '':
817 validity = False
818 self._PRW_unit.display_as_valid(False)
819 else:
820 self._PRW_unit.display_as_valid(True)
821
822 if validity is False:
823 self.StatusText = _('Cannot save drug component. Invalid or missing essential input.')
824
825 return validity
826 #----------------------------------------------------------------
828 # save the data as a new instance
829 data = 1
830 data[''] = 1
831 data[''] = 1
832 # data.save()
833
834 # must be done very late or else the property access
835 # will refresh the display such that later field
836 # access will return empty values
837 # self.data = data
838 return False
839 return True
840 #----------------------------------------------------------------
842 self.data['pk_dose'] = self._PRW_substance.GetData()
843 self.data['amount'] = decimal.Decimal(self._TCTRL_amount.GetValue().strip().replace(',', '.', 1))
844 self.data['unit'] = self._PRW_unit.GetValue().strip()
845 return self.data.save()
846
847 #----------------------------------------------------------------
849 self._TCTRL_product_name.SetValue('')
850 self._TCTRL_components.SetValue('')
851 self._TCTRL_codes.SetValue('')
852 self._PRW_substance.SetText('', None)
853 self._TCTRL_amount.SetValue('')
854 self._PRW_unit.SetText('', None)
855
856 self._PRW_substance.SetFocus()
857
858 #----------------------------------------------------------------
860 self._TCTRL_product_name.SetValue('%s (%s)' % (self.data['product'], self.data['l10n_preparation']))
861 self._TCTRL_components.SetValue(' / '.join(self.data.containing_drug['components']))
862 details = []
863 if self.data['atc_drug'] is not None:
864 details.append('ATC: %s' % self.data['atc_drug'])
865 if self.data['external_code_product'] is not None:
866 details.append('%s: %s' % (self.data['external_code_type_product'], self.data['external_code_product']))
867 self._TCTRL_codes.SetValue('; '.join(details))
868
869 self._PRW_substance.SetText(self.data['substance'], self.data['pk_dose'])
870 self._TCTRL_amount.SetValue('%s' % self.data['amount'])
871 self._PRW_unit.SetText(self.data['unit'], self.data['unit'])
872
873 self._PRW_substance.SetFocus()
874
875 #----------------------------------------------------------------
885
886 #------------------------------------------------------------
888
890
891 mp = gmMedication.cDrugComponentMatchProvider()
892 mp.setThresholds(2, 3, 4)
893 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
894 self.SetToolTip(_('A drug component with optional strength.'))
895 self.matcher = mp
896 self.selection_only = False
897 #--------------------------------------------------------
899 return gmMedication.cDrugComponent(aPK_obj = self.GetData(as_instance = False, can_create = False))
900
901 #============================================================
902 # drug products widgets
903 #------------------------------------------------------------
905
906 if drug_product is not None:
907 if drug_product.is_in_use_by_patients:
908 gmGuiHelpers.gm_show_info (
909 aTitle = _('Editing drug'),
910 aMessage = _(
911 'Cannot edit the drug product\n'
912 '\n'
913 ' "%s" (%s)\n'
914 '\n'
915 'because it is currently taken by patients.\n'
916 ) % (drug_product['product'], drug_product['l10n_preparation'])
917 )
918 return False
919
920 if parent is None:
921 parent = wx.GetApp().GetTopWindow()
922
923 #--------------------------------------------
924 def manage_substances(drug):
925 manage_substance_doses(parent = parent)
926
927 #--------------------------------------------
928 ea = cDrugProductEAPnl(parent, -1)
929 ea.data = drug_product
930 ea.mode = gmTools.coalesce(drug_product, 'new', 'edit')
931 dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea, single_entry = single_entry)
932 dlg.SetTitle(gmTools.coalesce(drug_product, _('Adding new drug product'), _('Editing drug product')))
933 dlg.left_extra_button = (
934 _('Substances'),
935 _('Manage substances'),
936 manage_substances
937 )
938 if dlg.ShowModal() == wx.ID_OK:
939 dlg.DestroyLater()
940 return True
941 dlg.DestroyLater()
942 return False
943
944 #------------------------------------------------------------
946
947 if parent is None:
948 parent = wx.GetApp().GetTopWindow()
949
950 #------------------------------------------------------------
951 def add_from_db(drug):
952 drug_db = get_drug_database(parent = parent)
953 if drug_db is None:
954 return False
955 drug_db.import_drugs()
956 return True
957
958 #------------------------------------------------------------
959 def get_tooltip(product=None):
960 return product.format(include_component_details = True)
961
962 #------------------------------------------------------------
963 def edit(product):
964 if product is not None:
965 if product.is_in_use_as_vaccine:
966 gmGuiHelpers.gm_show_info (
967 aTitle = _('Editing medication'),
968 aMessage = _(
969 'Cannot edit the vaccine product\n'
970 '\n'
971 ' "%s" (%s)\n'
972 '\n'
973 'because it is in use.'
974 ) % (product['product'], product['l10n_preparation'])
975 )
976 return False
977
978 return edit_drug_product(parent = parent, drug_product = product, single_entry = True)
979
980 #------------------------------------------------------------
981 def delete(product):
982 if not product.delete_associated_vaccine():
983 gmGuiHelpers.gm_show_info (
984 aTitle = _('Deleting vaccine'),
985 aMessage = _(
986 'Cannot delete the vaccine product\n'
987 '\n'
988 ' "%s" (%s)\n'
989 '\n'
990 'because it is in use.'
991 ) % (product['product'], product['l10n_preparation'])
992 )
993 return False
994
995 gmMedication.delete_drug_product(pk_drug_product = product['pk_drug_product'])
996 return True
997
998 #------------------------------------------------------------
999 def new():
1000 return edit_drug_product(parent = parent, drug_product = None, single_entry = False)
1001
1002 #------------------------------------------------------------
1003 def refresh(lctrl):
1004 drugs = gmMedication.get_drug_products()
1005 items = [ [
1006 '%s%s' % (
1007 d['product'],
1008 gmTools.bool2subst(d['is_fake_product'], ' (%s)' % _('fake'), '')
1009 ),
1010 d['l10n_preparation'],
1011 gmTools.coalesce(d['atc'], ''),
1012 '; '.join([ '%s %s%s' % (
1013 c['substance'],
1014 c['amount'],
1015 gmMedication.format_units(c['unit'], c['dose_unit'])
1016 ) for c in d['components']]),
1017 gmTools.coalesce(d['external_code'], '', '%%s [%s]' % d['external_code_type']),
1018 d['pk_drug_product']
1019 ] for d in drugs ]
1020 lctrl.set_string_items(items)
1021 lctrl.set_data(drugs)
1022
1023 #------------------------------------------------------------
1024 gmListWidgets.get_choices_from_list (
1025 parent = parent,
1026 caption = _('Drug products currently known to GNUmed.'),
1027 columns = [_('Name'), _('Preparation'), _('ATC'), _('Components'), _('Code'), '#'],
1028 single_selection = True,
1029 ignore_OK_button = ignore_OK_button,
1030 refresh_callback = refresh,
1031 new_callback = new,
1032 edit_callback = edit,
1033 delete_callback = delete,
1034 list_tooltip_callback = get_tooltip,
1035 left_extra_button = (_('Import'), _('Import substances and products from a drug database.'), add_from_db)
1036 #, middle_extra_button = (_('Clone'), _('Clone selected drug into a new entry for editing.'), clone_from_existing)
1037 #, right_extra_button = (_('Reassign'), _('Reassign all patients taking the selected drug to another drug.'), reassign_patients)
1038 )
1039
1040 #------------------------------------------------------------
1042
1043 if product is not None:
1044 if product.is_in_use_by_patients:
1045 gmGuiHelpers.gm_show_info (
1046 aTitle = _('Managing components of a drug'),
1047 aMessage = _(
1048 'Cannot manage the components of the drug product\n'
1049 '\n'
1050 ' "%s" (%s)\n'
1051 '\n'
1052 'because it is currently taken by patients.\n'
1053 ) % (product['product'], product['l10n_preparation'])
1054 )
1055 return False
1056
1057 #--------------------------------------------------------
1058 if parent is None:
1059 parent = wx.GetApp().GetTopWindow()
1060
1061 #--------------------------------------------------------
1062 # def manage_substances():
1063 # pass
1064
1065 #--------------------------------------------------------
1066 if product is None:
1067 msg = _('Pick the substance doses which are components of this drug.')
1068 right_col = _('Components of drug')
1069 comp_doses = []
1070 else:
1071 right_col = '%s (%s)' % (product['product'], product['l10n_preparation'])
1072 msg = _(
1073 'Adjust the components of "%s"\n'
1074 '\n'
1075 'The drug must contain at least one component. Any given\n'
1076 'substance can only be included once per drug.'
1077 ) % right_col
1078 comp_doses = [ comp.substance_dose for comp in product.components ]
1079
1080 doses = gmMedication.get_substance_doses(order_by = 'substance')
1081 choices = [ '%s %s %s' % (d['substance'], d['amount'], d.formatted_units) for d in doses ]
1082 picks = [ '%s %s %s' % (d['substance'], d['amount'], d.formatted_units) for d in comp_doses ]
1083
1084 picker = gmListWidgets.cItemPickerDlg (
1085 parent,
1086 -1,
1087 title = _('Managing components of a drug ...'),
1088 msg = msg
1089 )
1090 picker.set_columns(['Substance doses'], [right_col])
1091 picker.set_choices(choices = choices, data = doses)
1092 picker.set_picks(picks = picks, data = comp_doses)
1093 # picker.extra_button = (
1094 # _('Substances'),
1095 # _('Manage list of substances'),
1096 # manage_substances
1097 # )
1098
1099 btn_pressed = picker.ShowModal()
1100 doses2set = picker.get_picks()
1101 picker.DestroyLater()
1102
1103 if btn_pressed != wx.ID_OK:
1104 return (False, None)
1105
1106 if product is not None:
1107 product.set_substance_doses_as_components(substance_doses = doses2set)
1108
1109 return (True, doses2set)
1110
1111 #------------------------------------------------------------
1112 from Gnumed.wxGladeWidgets import wxgDrugProductEAPnl
1113
1114 -class cDrugProductEAPnl(wxgDrugProductEAPnl.wxgDrugProductEAPnl, gmEditArea.cGenericEditAreaMixin):
1115
1117 try:
1118 data = kwargs['drug']
1119 del kwargs['drug']
1120 except KeyError:
1121 data = None
1122
1123 wxgDrugProductEAPnl.wxgDrugProductEAPnl.__init__(self, *args, **kwargs)
1124 gmEditArea.cGenericEditAreaMixin.__init__(self)
1125
1126 self.__component_doses = []
1127
1128 self.mode = 'new'
1129 self.data = data
1130 if data is not None:
1131 self.mode = 'edit'
1132 self.__component_doses = data.components_as_doses
1133
1134 #self.__init_ui()
1135 #----------------------------------------------------------------
1136 # def __init_ui(self):
1137 # adjust external type PRW
1138 #----------------------------------------------------------------
1139 # generic Edit Area mixin API
1140 #----------------------------------------------------------------
1142
1143 if self.data is not None:
1144 if self.data.is_in_use_by_patients:
1145 self.StatusText = _('Cannot edit drug product. It is in use.')
1146 return False
1147
1148 validity = True
1149
1150 product_name = self._PRW_product_name.GetValue().strip()
1151 if product_name == '':
1152 validity = False
1153 self._PRW_product_name.display_as_valid(False)
1154 else:
1155 self._PRW_product_name.display_as_valid(True)
1156
1157 preparation = self._PRW_preparation.GetValue().strip()
1158 if preparation == '':
1159 validity = False
1160 self._PRW_preparation.display_as_valid(False)
1161 else:
1162 self._PRW_preparation.display_as_valid(True)
1163
1164 if validity is True:
1165 # dupe ?
1166 drug = gmMedication.get_drug_by_name(product_name = product_name, preparation = preparation)
1167 if drug is not None:
1168 if self.mode != 'edit':
1169 validity = False
1170 self._PRW_product_name.display_as_valid(False)
1171 self._PRW_preparation.display_as_valid(False)
1172 gmGuiHelpers.gm_show_error (
1173 title = _('Checking product data'),
1174 error = _(
1175 'The information you entered:\n'
1176 '\n'
1177 ' [%s %s]\n'
1178 '\n'
1179 'already exists as a drug product.'
1180 ) % (product_name, preparation)
1181 )
1182 else:
1183 # lacking components ?
1184 self._TCTRL_components.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND))
1185 if len(self.__component_doses) == 0:
1186 wants_empty = gmGuiHelpers.gm_show_question (
1187 title = _('Checking product data'),
1188 question = _(
1189 'You have not selected any substances\n'
1190 'as drug components.\n'
1191 '\n'
1192 'Without components you will not be able to\n'
1193 'use this drug for documenting patient care.\n'
1194 '\n'
1195 'Are you sure you want to save\n'
1196 'it without components ?'
1197 )
1198 )
1199 if not wants_empty:
1200 validity = False
1201 self.display_ctrl_as_valid(ctrl = self._TCTRL_components, valid = False)
1202
1203 if validity is False:
1204 self.StatusText = _('Cannot save drug product. Invalid or missing essential input.')
1205
1206 return validity
1207
1208 #----------------------------------------------------------------
1210 drug = gmMedication.create_drug_product (
1211 product_name = self._PRW_product_name.GetValue().strip(),
1212 preparation = gmTools.coalesce (
1213 self._PRW_preparation.GetData(),
1214 self._PRW_preparation.GetValue()
1215 ).strip(),
1216 doses = self.__component_doses if (len(self.__component_doses) > 0) else None,
1217 return_existing = True
1218 )
1219 drug['is_fake_product'] = self._CHBOX_is_fake.GetValue()
1220 drug['atc'] = self._PRW_atc.GetData()
1221 code = self._TCTRL_external_code.GetValue().strip()
1222 if code != '':
1223 drug['external_code'] = code
1224 drug['external_code_type'] = self._PRW_external_code_type.GetData().strip()
1225 drug.save()
1226 self.data = drug
1227 return True
1228
1229 #----------------------------------------------------------------
1231 self.data['product'] = self._PRW_product_name.GetValue().strip()
1232 self.data['preparation'] = gmTools.coalesce (
1233 self._PRW_preparation.GetData(),
1234 self._PRW_preparation.GetValue()
1235 ).strip()
1236 self.data['is_fake_product'] = self._CHBOX_is_fake.GetValue()
1237 self.data['atc'] = self._PRW_atc.GetData()
1238 code = self._TCTRL_external_code.GetValue().strip()
1239 if code != '':
1240 self.data['external_code'] = code
1241 self.data['external_code_type'] = self._PRW_external_code_type.GetData().strip()
1242 success, data = self.data.save()
1243 if not success:
1244 err, msg = data
1245 _log.error('problem saving')
1246 _log.error('%s', err)
1247 _log.error('%s', msg)
1248 return (success is True)
1249
1250 #----------------------------------------------------------------
1252 self._PRW_product_name.SetText('', None)
1253 self._PRW_preparation.SetText('', None)
1254 self._CHBOX_is_fake.SetValue(False)
1255 self._TCTRL_components.SetValue('')
1256 self._PRW_atc.SetText('', None)
1257 self._TCTRL_external_code.SetValue('')
1258 self._PRW_external_code_type.SetText('', None)
1259
1260 self._PRW_product_name.SetFocus()
1261
1262 self.__component_doses = []
1263
1264 #----------------------------------------------------------------
1267
1268 #----------------------------------------------------------------
1270 self._PRW_product_name.SetText(self.data['product'], self.data['pk_drug_product'])
1271 self._PRW_preparation.SetText(self.data['preparation'], self.data['preparation'])
1272 self._CHBOX_is_fake.SetValue(self.data['is_fake_product'])
1273 comp_str = ''
1274 if len(self.data['components']) > 0:
1275 comp_str = '- %s' % '\n- '.join([ '%s %s%s' % (c['substance'], c['amount'], gmMedication.format_units(c['unit'], c['dose_unit'])) for c in self.data['components'] ])
1276 self._TCTRL_components.SetValue(comp_str)
1277 self._PRW_atc.SetText(gmTools.coalesce(self.data['atc'], ''), self.data['atc'])
1278 self._TCTRL_external_code.SetValue(gmTools.coalesce(self.data['external_code'], ''))
1279 t = gmTools.coalesce(self.data['external_code_type'], '')
1280 self._PRW_external_code_type.SetText(t, t)
1281
1282 self._PRW_product_name.SetFocus()
1283
1284 self.__component_doses = self.data.components_as_doses
1285
1286 #----------------------------------------------------------------
1287 # event handler
1288 #----------------------------------------------------------------
1302
1303 #------------------------------------------------------------
1305
1307
1308 query = """
1309 SELECT
1310 pk
1311 AS data,
1312 (description || ' (' || preparation || ')' || coalesce(' [' || atc_code || ']', ''))
1313 AS list_label,
1314 (description || ' (' || preparation || ')' || coalesce(' [' || atc_code || ']', ''))
1315 AS field_label
1316 FROM ref.drug_product
1317 WHERE description %(fragment_condition)s
1318 ORDER BY list_label
1319 LIMIT 50"""
1320
1321 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query)
1322 mp.setThresholds(2, 3, 4)
1323 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
1324 self.SetToolTip(_(
1325 'The product name of the drug.\n'
1326 '\n'
1327 'Note: a product name will need to be linked to\n'
1328 'one or more components before it can be used,\n'
1329 'except in the case of fake (generic) vaccines.'
1330 ))
1331 self.matcher = mp
1332 self.selection_only = False
1333
1334 #============================================================
1335 # single-component generic drugs
1336 # drug name is forced to substance + amount + unit + dose_unit
1337 #------------------------------------------------------------
1338 -def edit_single_component_generic_drug(parent=None, drug=None, single_entry=False, fields=None, return_drug=False):
1339
1340 # if drug is not None:
1341 # if drug.is_in_use_by_patients:
1342 # gmGuiHelpers.gm_show_info (
1343 # aTitle = _('Editing single-component generic drug'),
1344 # aMessage = _(
1345 # 'Cannot edit the single-component generic drug\n'
1346 # '\n'
1347 # ' "%s" (%s)\n'
1348 # '\n'
1349 # 'because it is currently taken by patients.\n'
1350 # ) % (drug['product'], drug['l10n_preparation'])
1351 # )
1352 # return False
1353
1354 if parent is None:
1355 parent = wx.GetApp().GetTopWindow()
1356
1357 # #--------------------------------------------
1358 # def manage_substances(drug):
1359 # manage_substance_doses(parent = parent)
1360
1361 #--------------------------------------------
1362 ea = cSingleComponentGenericDrugEAPnl(parent, -1)
1363 ea.data = drug
1364 ea.mode = gmTools.coalesce(drug, 'new', 'edit')
1365 dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea, single_entry = single_entry)
1366 if fields is not None:
1367 ea.set_fields(fields)
1368 dlg.SetTitle(gmTools.coalesce(drug, _('Adding new single-component generic drug'), _('Editing single-component generic drug')))
1369 # dlg.left_extra_button = (
1370 # _('Substances'),
1371 # _('Manage substances'),
1372 # manage_substances
1373 # )
1374 if dlg.ShowModal() == wx.ID_OK:
1375 drug = ea.data
1376 dlg.DestroyLater()
1377 if return_drug:
1378 return drug
1379 return True
1380 dlg.DestroyLater()
1381 if return_drug:
1382 return None
1383 return False
1384
1385 #------------------------------------------------------------
1387
1388 if parent is None:
1389 parent = wx.GetApp().GetTopWindow()
1390
1391 #------------------------------------------------------------
1392 def add_from_db(drug):
1393 drug_db = get_drug_database(parent = parent)
1394 if drug_db is None:
1395 return False
1396 drug_db.import_drugs()
1397 return True
1398
1399 #------------------------------------------------------------
1400 def get_tooltip(product=None):
1401 return product.format(include_component_details = True)
1402
1403 #------------------------------------------------------------
1404 def edit(product):
1405 if product is not None:
1406 if product.is_vaccine:
1407 gmGuiHelpers.gm_show_info (
1408 aTitle = _('Editing medication'),
1409 aMessage = _(
1410 'Cannot edit the medication\n'
1411 '\n'
1412 ' "%s" (%s)\n'
1413 '\n'
1414 'because it is a vaccine. Please edit it\n'
1415 'from the vaccine management section !\n'
1416 ) % (product['product'], product['l10n_preparation'])
1417 )
1418 return False
1419
1420 return edit_drug_product(parent = parent, drug_product = product, single_entry = True)
1421
1422 #------------------------------------------------------------
1423 def delete(product):
1424 if product.is_vaccine:
1425 gmGuiHelpers.gm_show_info (
1426 aTitle = _('Deleting medication'),
1427 aMessage = _(
1428 'Cannot delete the medication\n'
1429 '\n'
1430 ' "%s" (%s)\n'
1431 '\n'
1432 'because it is a vaccine. Please delete it\n'
1433 'from the vaccine management section !\n'
1434 ) % (product['product'], product['l10n_preparation'])
1435 )
1436 return False
1437 gmMedication.delete_drug_product(pk_drug_product = product['pk_drug_product'])
1438 return True
1439
1440 #------------------------------------------------------------
1441 def new():
1442 return edit_drug_product(parent = parent, drug_product = None, single_entry = False)
1443
1444 #------------------------------------------------------------
1445 def refresh(lctrl):
1446 drugs = gmMedication.get_drug_products()
1447 items = [ [
1448 '%s%s' % (
1449 d['product'],
1450 gmTools.bool2subst(d['is_fake_product'], ' (%s)' % _('fake'), '')
1451 ),
1452 d['l10n_preparation'],
1453 gmTools.coalesce(d['atc'], ''),
1454 '; '.join([ '%s %s%s' % (
1455 c['substance'],
1456 c['amount'],
1457 gmMedication.format_units(c['unit'], c['dose_unit'])
1458 ) for c in d['components']]),
1459 gmTools.coalesce(d['external_code'], '', '%%s [%s]' % d['external_code_type']),
1460 d['pk_drug_product']
1461 ] for d in drugs ]
1462 lctrl.set_string_items(items)
1463 lctrl.set_data(drugs)
1464
1465 #------------------------------------------------------------
1466 gmListWidgets.get_choices_from_list (
1467 parent = parent,
1468 caption = _('Drug products currently known to GNUmed.'),
1469 columns = [_('Name'), _('Preparation'), _('ATC'), _('Components'), _('Code'), '#'],
1470 single_selection = True,
1471 ignore_OK_button = ignore_OK_button,
1472 refresh_callback = refresh,
1473 new_callback = new,
1474 edit_callback = edit,
1475 delete_callback = delete,
1476 list_tooltip_callback = get_tooltip,
1477 #left_extra_button = (_('Import'), _('Import substances and products from a drug database.'), add_from_db)
1478 #, middle_extra_button = (_('Clone'), _('Clone selected drug into a new entry for editing.'), clone_from_existing)
1479 #, right_extra_button = (_('Reassign'), _('Reassign all patients taking the selected drug to another drug.'), reassign_patients)
1480 )
1481
1482 #------------------------------------------------------------
1483 from Gnumed.wxGladeWidgets import wxgSingleComponentGenericDrugEAPnl
1484
1485 -class cSingleComponentGenericDrugEAPnl(wxgSingleComponentGenericDrugEAPnl.wxgSingleComponentGenericDrugEAPnl, gmEditArea.cGenericEditAreaMixin):
1486
1488
1489 try:
1490 data = kwargs['drug']
1491 del kwargs['drug']
1492 except KeyError:
1493 data = None
1494
1495 wxgSingleComponentGenericDrugEAPnl.wxgSingleComponentGenericDrugEAPnl.__init__(self, *args, **kwargs)
1496 gmEditArea.cGenericEditAreaMixin.__init__(self)
1497
1498 self.mode = 'new'
1499 self.data = data
1500 if data is not None:
1501 self.mode = 'edit'
1502
1503 self.__init_ui()
1504
1505 #----------------------------------------------------------------
1507 self._PRW_substance.add_callback_on_modified(callback = self._on_name_field_modified)
1508 self._PRW_substance.add_callback_on_selection(callback = self._on_name_field_modified)
1509 self._TCTRL_amount.add_callback_on_modified(callback = self._on_name_field_modified)
1510 self._PRW_unit.add_callback_on_modified(callback = self._on_name_field_modified)
1511 self._PRW_unit.add_callback_on_selection(callback = self._on_name_field_modified)
1512 self._PRW_dose_unit.add_callback_on_modified(callback = self._on_name_field_modified)
1513 self._PRW_dose_unit.add_callback_on_selection(callback = self._on_name_field_modified)
1514
1515 #----------------------------------------------------------------
1516 # generic Edit Area mixin API
1517 #----------------------------------------------------------------
1519
1520 validity = True
1521
1522 if self._PRW_preparation.Value.strip() == '':
1523 validity = False
1524 self._PRW_preparation.display_as_valid(False)
1525 self.StatusText = _('Drug form is missing.')
1526 self._PRW_preparation.SetFocus()
1527 else:
1528 self._PRW_preparation.display_as_valid(True)
1529
1530 if self._PRW_unit.GetData() is None:
1531 validity = False
1532 self._PRW_unit.display_as_valid(False)
1533 self.StatusText = _('Unit for amount is missing.')
1534 self._PRW_unit.SetFocus()
1535 else:
1536 self._PRW_unit.display_as_valid(True)
1537
1538 if self._TCTRL_amount.GetValue().strip() == '':
1539 validity = False
1540 self.display_tctrl_as_valid(tctrl = self._TCTRL_amount, valid = False)
1541 self.StatusText = _('Amount is missing.')
1542 self._TCTRL_amount.SetFocus()
1543 else:
1544 self.display_tctrl_as_valid(tctrl = self._TCTRL_amount, valid = True)
1545
1546 if self._PRW_substance.GetData() is None:
1547 val = self._PRW_substance.Value.strip()
1548 if val != '' and gmATC.exists_as_atc(val):
1549 subst = gmMedication.create_substance(substance = val)
1550 self._PRW_substance.SetText(subst['substance'], subst['pk_substance'])
1551 self._PRW_substance.display_as_valid(True)
1552 else:
1553 validity = False
1554 self._PRW_substance.display_as_valid(False)
1555 self.StatusText = _('Substance is missing.')
1556 self._PRW_substance.SetFocus()
1557 else:
1558 self._PRW_substance.display_as_valid(True)
1559
1560 return validity
1561
1562 #----------------------------------------------------------------
1564 dose = gmMedication.create_substance_dose (
1565 pk_substance = self._PRW_substance.GetData(),
1566 amount = self._TCTRL_amount.Value.strip(),
1567 unit = self._PRW_unit.GetData(),
1568 dose_unit = self._PRW_dose_unit.GetData()
1569 )
1570 dose_unit = self._PRW_dose_unit.GetValue().strip()
1571 if dose_unit != '':
1572 dose_unit = '/' + dose_unit
1573 name = '%s %s%s%s' % (
1574 self._PRW_substance.GetValue().strip(),
1575 self._TCTRL_amount.Value.strip(),
1576 self._PRW_unit.GetValue().strip(),
1577 dose_unit
1578 )
1579 drug = gmMedication.create_drug_product (
1580 product_name = name,
1581 preparation = self._PRW_preparation.GetValue().strip(),
1582 return_existing = True,
1583 doses = [dose]
1584 )
1585 drug['is_fake_product'] = True
1586 drug.save()
1587 self.data = drug
1588 return True
1589
1590 #----------------------------------------------------------------
1593 # self.data[''] = self._CHBOX_xxx.GetValue()
1594 # self.data.save()
1595 # return True
1596
1597 #----------------------------------------------------------------
1599 self._LBL_drug_name.SetLabel('')
1600 self._PRW_substance.SetText('', None)
1601 self._TCTRL_amount.SetValue('')
1602 self._PRW_unit.SetText('', None)
1603 self._PRW_dose_unit.SetText('', None)
1604 self._PRW_preparation.SetText('', None)
1605
1606 #----------------------------------------------------------------
1609
1610 #----------------------------------------------------------------
1613
1614 #----------------------------------------------------------------
1616 try:
1617 self._PRW_substance.SetText(fields['substance']['value'], fields['substance']['data'])
1618 except KeyError:
1619 _log.error('cannot set field [substance] from <%s>', fields)
1620
1621 #----------------------------------------------------------------
1623 dose_unit = self._PRW_dose_unit.GetValue().strip()
1624 if dose_unit != '':
1625 dose_unit = '/' + dose_unit
1626 name = '%s %s%s%s' % (
1627 self._PRW_substance.GetValue().strip(),
1628 self._TCTRL_amount.Value.strip(),
1629 self._PRW_unit.GetValue().strip(),
1630 dose_unit
1631 )
1632 self._LBL_drug_name.SetLabel('"%s"' % name.strip())
1633
1634 #============================================================
1635 # main
1636 #------------------------------------------------------------
1637 if __name__ == '__main__':
1638
1639 if len(sys.argv) < 2:
1640 sys.exit()
1641
1642 if sys.argv[1] != 'test':
1643 sys.exit()
1644
1645 from Gnumed.business import gmPersonSearch
1646
1647 pat = gmPersonSearch.ask_for_patient()
1648 if pat is None:
1649 sys.exit()
1650 gmPerson.set_active_patient(patient = pat)
1651
1652 #----------------------------------------
1653 app = wx.PyWidgetTester(size = (600, 300))
1654 app.SetWidget(cSubstancePhraseWheel, -1)
1655 app.MainLoop()
1656 #manage_substance_intakes()
1657 edit_single_component_generic_drug (
1658 single_entry = True,
1659 fields = {'substance': {'value': val, 'data': None}},
1660 return_drug = True
1661 )
1662
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Sat Feb 29 02:55:27 2020 | http://epydoc.sourceforge.net |