1 """GNUmed EMR structure editors
2
3 This module contains widgets to create and edit EMR structural
4 elements (issues, enconters, episodes).
5
6 This is based on initial work and ideas by Syan <kittylitter@swiftdsl.com.au>
7 and Karsten <Karsten.Hilbert@gmx.net>.
8 """
9
10 __version__ = "$Revision: 1.114 $"
11 __author__ = "cfmoro1976@yahoo.es, karsten.hilbert@gmx.net"
12 __license__ = "GPL"
13
14
15 import sys, re, datetime as pydt, logging, time
16
17
18
19 import wx
20 import wx.lib.pubsub as wxps
21
22
23
24 if __name__ == '__main__':
25 sys.path.insert(0, '../../')
26 from Gnumed.pycommon import gmI18N, gmMatchProvider, gmDispatcher, gmTools, gmDateTime, gmCfg, gmExceptions
27 from Gnumed.business import gmEMRStructItems, gmPerson, gmSOAPimporter, gmSurgery, gmPersonSearch
28 from Gnumed.wxpython import gmPhraseWheel, gmGuiHelpers, gmListWidgets, gmEditArea, gmPatSearchWidgets
29 from Gnumed.wxGladeWidgets import wxgIssueSelectionDlg, wxgMoveNarrativeDlg
30 from Gnumed.wxGladeWidgets import wxgEncounterTypeEditAreaPnl
31
32
33 _log = logging.getLogger('gm.ui')
34 _log.info(__version__)
35
36
37
48
49 def delete(procedure=None):
50 if gmEMRStructItems.delete_performed_procedure(procedure = procedure['pk_procedure']):
51 return True
52
53 gmDispatcher.send (
54 signal = u'statustext',
55 msg = _('Cannot delete performed procedure.'),
56 beep = True
57 )
58 return False
59
60 def refresh(lctrl):
61 procs = emr.get_performed_procedures()
62
63 items = [
64 [
65 u'%s%s' % (
66 p['clin_when'].strftime('%Y-%m-%d'),
67 gmTools.bool2subst (
68 p['is_ongoing'],
69 _(' (ongoing)'),
70 gmTools.coalesce (
71 initial = p['clin_end'],
72 instead = u'',
73 template_initial = u' - %s',
74 function_initial = ('strftime', u'%Y-%m-%d')
75 )
76 )
77 ),
78 p['clin_where'],
79 p['episode'],
80 p['performed_procedure']
81 ] for p in procs
82 ]
83 lctrl.set_string_items(items = items)
84 lctrl.set_data(data = procs)
85
86 gmListWidgets.get_choices_from_list (
87 parent = parent,
88 msg = _('\nSelect the procedure you want to edit !\n'),
89 caption = _('Editing performed procedures ...'),
90 columns = [_('When'), _('Where'), _('Episode'), _('Procedure')],
91 single_selection = True,
92 edit_callback = edit,
93 new_callback = edit,
94 delete_callback = delete,
95 refresh_callback = refresh
96 )
97
109
110 from Gnumed.wxGladeWidgets import wxgProcedureEAPnl
111
112 -class cProcedureEAPnl(wxgProcedureEAPnl.wxgProcedureEAPnl, gmEditArea.cGenericEditAreaMixin):
113
122
157
159 stay = self._PRW_hospital_stay.GetData()
160 if stay is None:
161 self._PRW_hospital_stay.SetText()
162 self._PRW_location.Enable(True)
163 self._PRW_episode.Enable(True)
164 self._LBL_hospital_details.SetLabel(u'')
165 else:
166 self._PRW_location.SetText()
167 self._PRW_location.Enable(False)
168 self._PRW_episode.SetText()
169 self._PRW_episode.Enable(False)
170 self._LBL_hospital_details.SetLabel(gmEMRStructItems.cHospitalStay(aPK_obj = stay).format())
171
173 if self._PRW_location.GetValue().strip() == u'':
174 self._PRW_hospital_stay.Enable(True)
175
176 else:
177 self._PRW_hospital_stay.SetText()
178 self._PRW_hospital_stay.Enable(False)
179 self._PRW_hospital_stay.display_as_valid(True)
180
181
193
216
217
218
220
221 has_errors = False
222
223 if not self._DPRW_date.is_valid_timestamp():
224 self._DPRW_date.display_as_valid(False)
225 has_errors = True
226 else:
227 self._DPRW_date.display_as_valid(True)
228
229 end = self._DPRW_end.GetData()
230 self._DPRW_end.display_as_valid(True)
231 if end is not None:
232 end = end.get_pydt()
233 start = self._DPRW_end.GetData()
234 if start is not None:
235 start = start.get_pydt()
236 if end < start:
237 has_errors = True
238 self._DPRW_end.display_as_valid(False)
239 if self._CHBOX_ongoing.IsChecked():
240 now = gmDateTime.pydt_now_here()
241 if end < now:
242 has_errors = True
243 self._DPRW_end.display_as_valid(False)
244
245 if self._PRW_hospital_stay.GetData() is None:
246 if self._PRW_episode.GetData() is None:
247 self._PRW_episode.display_as_valid(False)
248 has_errors = True
249 else:
250 self._PRW_episode.display_as_valid(True)
251 else:
252 self._PRW_episode.display_as_valid(True)
253
254 if (self._PRW_procedure.GetValue() is None) or (self._PRW_procedure.GetValue().strip() == u''):
255 self._PRW_procedure.display_as_valid(False)
256 has_errors = True
257 else:
258 self._PRW_procedure.display_as_valid(True)
259
260 invalid_location = (
261 (self._PRW_hospital_stay.GetData() is None) and (self._PRW_location.GetValue().strip() == u'')
262 or
263 (self._PRW_hospital_stay.GetData() is not None) and (self._PRW_location.GetValue().strip() != u'')
264 )
265 if invalid_location:
266 self._PRW_hospital_stay.display_as_valid(False)
267 self._PRW_location.display_as_valid(False)
268 has_errors = True
269 else:
270 self._PRW_hospital_stay.display_as_valid(True)
271 self._PRW_location.display_as_valid(True)
272
273 wxps.Publisher().sendMessage (
274 topic = 'statustext',
275 data = {'msg': _('Cannot save procedure.'), 'beep': True}
276 )
277
278 return (has_errors is False)
279
281
282 pat = gmPerson.gmCurrentPatient()
283 emr = pat.get_emr()
284
285 if self._PRW_hospital_stay.GetData() is None:
286 stay = None
287 epi = self._PRW_episode.GetData()
288 loc = self._PRW_location.GetValue().strip()
289 else:
290 stay = self._PRW_hospital_stay.GetData()
291 epi = gmEMRStructItems.cHospitalStay(aPK_obj = stay)['pk_episode']
292 loc = None
293
294 proc = emr.add_performed_procedure (
295 episode = epi,
296 location = loc,
297 hospital_stay = stay,
298 procedure = self._PRW_procedure.GetValue().strip()
299 )
300
301 proc['clin_when'] = self._DPRW_date.data.get_pydt()
302 if self._DPRW_end.GetData() is None:
303 proc['clin_end'] = None
304 else:
305 proc['clin_end'] = self._DPRW_end.GetData().get_pydt()
306 proc['is_ongoing'] = self._CHBOX_ongoing.IsChecked()
307 proc.save()
308
309 self.data = proc
310
311 return True
312
314 self.data['clin_when'] = self._DPRW_date.data.get_pydt()
315
316 if self._DPRW_end.GetData() is None:
317 self.data['clin_end'] = None
318 else:
319 self.data['clin_end'] = self._DPRW_end.GetData().get_pydt()
320
321 self.data['is_ongoing'] = self._CHBOX_ongoing.IsChecked()
322
323 if self._PRW_hospital_stay.GetData() is None:
324 self.data['pk_hospital_stay'] = None
325 self.data['clin_where'] = self._PRW_location.GetValue().strip()
326 self.data['pk_episode'] = self._PRW_episode.GetData()
327 else:
328 self.data['pk_hospital_stay'] = self._PRW_hospital_stay.GetData()
329 self.data['clin_where'] = None
330 stay = gmEMRStructItems.cHospitalStay(aPK_obj = self._PRW_hospital_stay.GetData())
331 self.data['pk_episode'] = stay['pk_episode']
332
333 self.data['performed_procedure'] = self._PRW_procedure.GetValue().strip()
334
335 self.data.save()
336 return True
337
339 self._DPRW_date.SetText()
340 self._DPRW_end.SetText()
341 self._CHBOX_ongoing.SetValue(False)
342 self._CHBOX_ongoing.Enable(True)
343 self._PRW_hospital_stay.SetText()
344 self._PRW_location.SetText()
345 self._PRW_episode.SetText()
346 self._PRW_procedure.SetText()
347
348 self._PRW_procedure.SetFocus()
349
377
389
390
391
396
412
413
414
425
426 def delete(stay=None):
427 if gmEMRStructItems.delete_hospital_stay(stay = stay['pk_hospital_stay']):
428 return True
429 gmDispatcher.send (
430 signal = u'statustext',
431 msg = _('Cannot delete hospital stay.'),
432 beep = True
433 )
434 return False
435
436 def refresh(lctrl):
437 stays = emr.get_hospital_stays()
438 items = [
439 [
440 s['admission'].strftime('%Y-%m-%d'),
441 gmTools.coalesce(s['discharge'], u''),
442 s['episode'],
443 gmTools.coalesce(s['hospital'], u'')
444 ] for s in stays
445 ]
446 lctrl.set_string_items(items = items)
447 lctrl.set_data(data = stays)
448
449 gmListWidgets.get_choices_from_list (
450 parent = parent,
451 msg = _('\nSelect the hospital stay you want to edit !\n'),
452 caption = _('Editing hospital stays ...'),
453 columns = [_('Admission'), _('Discharge'), _('Reason'), _('Hospital')],
454 single_selection = True,
455 edit_callback = edit,
456 new_callback = edit,
457 delete_callback = delete,
458 refresh_callback = refresh
459 )
460
461
473
475 """Phrasewheel to allow selection of a hospital stay.
476 """
478
479 gmPhraseWheel.cPhraseWheel.__init__ (self, *args, **kwargs)
480
481 ctxt = {'ctxt_pat': {'where_part': u'pk_patient = %(pat)s and', 'placeholder': u'pat'}}
482
483 mp = gmMatchProvider.cMatchProvider_SQL2 (
484 queries = [
485 u"""
486 select
487 pk_hospital_stay,
488 descr
489 from (
490 select distinct on (pk_hospital_stay)
491 pk_hospital_stay,
492 descr
493 from
494 (select
495 pk_hospital_stay,
496 (
497 to_char(admission, 'YYYY-Mon-DD')
498 || coalesce((' (' || hospital || '):'), ': ')
499 || episode
500 || coalesce((' (' || health_issue || ')'), '')
501 ) as descr
502 from
503 clin.v_pat_hospital_stays
504 where
505 %(ctxt_pat)s
506
507 hospital %(fragment_condition)s
508 or
509 episode %(fragment_condition)s
510 or
511 health_issue %(fragment_condition)s
512 ) as the_stays
513 ) as distinct_stays
514 order by descr
515 limit 25
516 """ ],
517 context = ctxt
518 )
519 mp.setThresholds(3, 4, 6)
520 mp.set_context('pat', gmPerson.gmCurrentPatient().ID)
521
522 self.matcher = mp
523 self.selection_only = True
524
525 from Gnumed.wxGladeWidgets import wxgHospitalStayEditAreaPnl
526
527 -class cHospitalStayEditAreaPnl(wxgHospitalStayEditAreaPnl.wxgHospitalStayEditAreaPnl, gmEditArea.cGenericEditAreaMixin):
528
532
533
534
536 if not self._DP_admission.GetValue().IsValid():
537 self._DP_admission.SetBackgroundColour(gmPhraseWheel.color_prw_invalid)
538 wxps.Publisher().sendMessage (
539 topic = 'statustext',
540 data = {'msg': _('Missing admission data. Cannot save hospital stay.'), 'beep': True}
541 )
542 return False
543 else:
544 self._DP_admission.SetBackgroundColour(gmPhraseWheel.color_prw_valid)
545
546 if self._DP_discharge.GetValue().IsValid():
547 if not self._DP_discharge.GetValue().IsLaterThan(self._DP_admission.GetValue()):
548 self._DP_discharge.SetBackgroundColour(gmPhraseWheel.color_prw_invalid)
549 wxps.Publisher().sendMessage (
550 topic = 'statustext',
551 data = {'msg': _('Discharge date must be empty or later than admission. Cannot save hospital stay.'), 'beep': True}
552 )
553 return False
554
555 if self._PRW_episode.GetValue().strip() == u'':
556 self._PRW_episode.display_as_valid(False)
557 wxps.Publisher().sendMessage (
558 topic = 'statustext',
559 data = {'msg': _('Must select an episode or enter a name for a new one. Cannot save hospital stay.'), 'beep': True}
560 )
561 return False
562
563 return True
564
578
589
594
595
607
609 print "this was not expected to be used in this edit area"
610
611
612
621
622 from Gnumed.wxGladeWidgets import wxgEncounterEditAreaDlg
623
625 if parent is None:
626 parent = wx.GetApp().GetTopWindow()
627
628
629 dlg = cEncounterEditAreaDlg(parent = parent, encounter = encounter)
630 if dlg.ShowModal() == wx.ID_OK:
631 dlg.Destroy()
632 return True
633 dlg.Destroy()
634 return False
635
636 -def select_encounters(parent=None, patient=None, single_selection=True, encounters=None):
637
638 if patient is None:
639 patient = gmPerson.gmCurrentPatient()
640
641 if not patient.connected:
642 gmDispatcher.send(signal = 'statustext', msg = _('Cannot list encounters. No active patient.'))
643 return False
644
645 if parent is None:
646 parent = wx.GetApp().GetTopWindow()
647
648 emr = patient.get_emr()
649
650
651 def refresh(lctrl):
652 if encounters is not None:
653 encs = encounters
654 else:
655 encs = emr.get_encounters()
656
657 items = [
658 [
659 e['started'].strftime('%x %H:%M'),
660 e['last_affirmed'].strftime('%H:%M'),
661 e['l10n_type'],
662 gmTools.coalesce(e['reason_for_encounter'], u''),
663 gmTools.coalesce(e['assessment_of_encounter'], u''),
664 gmTools.bool2subst(e.has_clinical_data(), u'', gmTools.u_checkmark_thin),
665 e['pk_encounter']
666 ] for e in encs
667 ]
668
669 lctrl.set_string_items(items = items)
670 lctrl.set_data(data = encs)
671
672 def edit(enc = None):
673 return edit_encounter(parent = parent, encounter = enc)
674
675 return gmListWidgets.get_choices_from_list (
676 parent = parent,
677 msg = _('\nBelow find the relevant encounters of the patient.\n'),
678 caption = _('Encounters ...'),
679 columns = [_('Started'), _('Ended'), _('Type'), _('Reason for Encounter'), _('Assessment of Encounter'), _('Empty'), '#'],
680 can_return_empty = True,
681 single_selection = single_selection,
682 refresh_callback = refresh,
683 edit_callback = edit
684 )
685
687 """This is used as the callback when the EMR detects that the
688 patient was here rather recently and wants to ask the
689 provider whether to continue the recent encounter.
690 """
691 if parent is None:
692 parent = wx.GetApp().GetTopWindow()
693
694 dlg = gmGuiHelpers.c2ButtonQuestionDlg (
695 parent = None,
696 id = -1,
697 caption = caption,
698 question = msg,
699 button_defs = [
700 {'label': _('Continue'), 'tooltip': _('Continue the existing recent encounter.'), 'default': False},
701 {'label': _('Start new'), 'tooltip': _('Start a new encounter. The existing one will be closed.'), 'default': True}
702 ],
703 show_checkbox = False
704 )
705
706 result = dlg.ShowModal()
707 dlg.Destroy()
708
709 if result == wx.ID_YES:
710 return True
711
712 return False
713
715
716 if parent is None:
717 parent = wx.GetApp().GetTopWindow()
718
719
720 def edit(enc_type=None):
721 return edit_encounter_type(parent = parent, encounter_type = enc_type)
722
723 def delete(enc_type=None):
724 if gmEMRStructItems.delete_encounter_type(description = enc_type['description']):
725 return True
726 gmDispatcher.send (
727 signal = u'statustext',
728 msg = _('Cannot delete encounter type [%s]. It is in use.') % enc_type['l10n_description'],
729 beep = True
730 )
731 return False
732
733 def refresh(lctrl):
734 enc_types = gmEMRStructItems.get_encounter_types()
735 lctrl.set_string_items(items = enc_types)
736
737 gmListWidgets.get_choices_from_list (
738 parent = parent,
739 msg = _('\nSelect the encounter type you want to edit !\n'),
740 caption = _('Managing encounter types ...'),
741 columns = [_('Local name'), _('Encounter type')],
742 single_selection = True,
743 edit_callback = edit,
744 new_callback = edit,
745 delete_callback = delete,
746 refresh_callback = refresh
747 )
748
758
760 """Phrasewheel to allow selection of encounter type.
761
762 - user input interpreted as encounter type in English or local language
763 - data returned is pk of corresponding encounter type or None
764 """
766
767 gmPhraseWheel.cPhraseWheel.__init__ (self, *args, **kwargs)
768
769 mp = gmMatchProvider.cMatchProvider_SQL2 (
770 queries = [
771 u"""
772 select pk, l10n_description from (
773 select distinct on (pk) * from (
774 (select
775 pk,
776 _(description) as l10n_description,
777 1 as rank
778 from
779 clin.encounter_type
780 where
781 _(description) %(fragment_condition)s
782
783 ) union all (
784
785 select
786 pk,
787 _(description) as l10n_description,
788 2 as rank
789 from
790 clin.encounter_type
791 where
792 description %(fragment_condition)s
793 )
794 ) as q_distinct_pk
795 ) as q_ordered order by rank, l10n_description
796 """ ]
797 )
798 mp.setThresholds(2, 4, 6)
799
800 self.matcher = mp
801 self.selection_only = True
802 self.picklist_delay = 50
803
805
810
811
812
813
814
844
857
867
869 self._TCTRL_l10n_name.SetValue(u'')
870 self._TCTRL_name.SetValue(u'')
871 self._TCTRL_name.Enable(True)
872
874 self._TCTRL_l10n_name.SetValue(self.data['l10n_description'])
875 self._TCTRL_name.SetValue(self.data['description'])
876
877 self._TCTRL_name.Enable(False)
878
880 self._TCTRL_l10n_name.SetValue(self.data['l10n_description'])
881 self._TCTRL_name.SetValue(self.data['description'])
882 self._TCTRL_name.Enable(True)
883
884
885
886
887
888
889 from Gnumed.wxGladeWidgets import wxgEncounterEditAreaPnl
890
892
894 try:
895 self.__encounter = kwargs['encounter']
896 del kwargs['encounter']
897 except KeyError:
898 self.__encounter = None
899
900 try:
901 msg = kwargs['msg']
902 del kwargs['msg']
903 except KeyError:
904 msg = None
905
906 wxgEncounterEditAreaPnl.wxgEncounterEditAreaPnl.__init__(self, *args, **kwargs)
907
908 self.refresh(msg = msg)
909
910
911
912 - def refresh(self, encounter=None, msg=None):
951
953
954 if self._PRW_encounter_type.GetData() is None:
955 self._PRW_encounter_type.SetBackgroundColour('pink')
956 self._PRW_encounter_type.Refresh()
957 self._PRW_encounter_type.SetFocus()
958 return False
959 self._PRW_encounter_type.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
960 self._PRW_encounter_type.Refresh()
961
962 if not self._PRW_start.is_valid_timestamp():
963 self._PRW_start.SetFocus()
964 return False
965
966 if not self._PRW_end.is_valid_timestamp():
967 self._PRW_end.SetFocus()
968 return False
969
970 return True
971
973 if not self.__is_valid_for_save():
974 return False
975
976 self.__encounter['pk_type'] = self._PRW_encounter_type.GetData()
977 self.__encounter['started'] = self._PRW_start.GetData().get_pydt()
978 self.__encounter['last_affirmed'] = self._PRW_end.GetData().get_pydt()
979 self.__encounter['reason_for_encounter'] = gmTools.none_if(self._TCTRL_rfe.GetValue().strip(), u'')
980 self.__encounter['assessment_of_encounter'] = gmTools.none_if(self._TCTRL_aoe.GetValue().strip(), u'')
981 self.__encounter.save_payload()
982
983 return True
984
985
987
989 encounter = kwargs['encounter']
990 del kwargs['encounter']
991
992 try:
993 button_defs = kwargs['button_defs']
994 del kwargs['button_defs']
995 except KeyError:
996 button_defs = None
997
998 try:
999 msg = kwargs['msg']
1000 del kwargs['msg']
1001 except KeyError:
1002 msg = None
1003
1004 wxgEncounterEditAreaDlg.wxgEncounterEditAreaDlg.__init__(self, *args, **kwargs)
1005 self.SetSize((450, 280))
1006 self.SetMinSize((450, 280))
1007
1008 if button_defs is not None:
1009 self._BTN_save.SetLabel(button_defs[0][0])
1010 self._BTN_save.SetToolTipString(button_defs[0][1])
1011 self._BTN_close.SetLabel(button_defs[1][0])
1012 self._BTN_close.SetToolTipString(button_defs[1][1])
1013 self.Refresh()
1014
1015 self._PNL_edit_area.refresh(encounter = encounter, msg = msg)
1016
1017 self.Fit()
1018
1025
1026
1027
1037
1107
1109 """Prepare changing health issue for an episode.
1110
1111 Checks for two-open-episodes conflict. When this
1112 function succeeds, the pk_health_issue has been set
1113 on the episode instance and the episode should - for
1114 all practical purposes - be ready for save_payload().
1115 """
1116
1117 if not episode['episode_open']:
1118 episode['pk_health_issue'] = target_issue['pk_health_issue']
1119 if save_to_backend:
1120 episode.save_payload()
1121 return True
1122
1123
1124 if target_issue is None:
1125 episode['pk_health_issue'] = None
1126 if save_to_backend:
1127 episode.save_payload()
1128 return True
1129
1130
1131 db_cfg = gmCfg.cCfgSQL()
1132 epi_ttl = int(db_cfg.get2 (
1133 option = u'episode.ttl',
1134 workplace = gmSurgery.gmCurrentPractice().active_workplace,
1135 bias = 'user',
1136 default = 60
1137 ))
1138 if target_issue.close_expired_episode(ttl=epi_ttl) is True:
1139 gmDispatcher.send(signal='statustext', msg=_('Closed episodes older than %s days on health issue [%s]') % (epi_ttl, target_issue['description']))
1140 existing_epi = target_issue.get_open_episode()
1141
1142
1143 if existing_epi is None:
1144 episode['pk_health_issue'] = target_issue['pk_health_issue']
1145 if save_to_backend:
1146 episode.save_payload()
1147 return True
1148
1149
1150 if existing_epi['pk_episode'] == episode['pk_episode']:
1151 episode['pk_health_issue'] = target_issue['pk_health_issue']
1152 if save_to_backend:
1153 episode.save_payload()
1154 return True
1155
1156
1157 move_range = episode.get_access_range()
1158 exist_range = existing_epi.get_access_range()
1159 question = _(
1160 'You want to associate the running episode:\n\n'
1161 ' "%(new_epi_name)s" (%(new_epi_start)s - %(new_epi_end)s)\n\n'
1162 'with the health issue:\n\n'
1163 ' "%(issue_name)s"\n\n'
1164 'There already is another episode running\n'
1165 'for this health issue:\n\n'
1166 ' "%(old_epi_name)s" (%(old_epi_start)s - %(old_epi_end)s)\n\n'
1167 'However, there can only be one running\n'
1168 'episode per health issue.\n\n'
1169 'Which episode do you want to close ?'
1170 ) % {
1171 'new_epi_name': episode['description'],
1172 'new_epi_start': move_range[0].strftime('%m/%y'),
1173 'new_epi_end': move_range[1].strftime('%m/%y'),
1174 'issue_name': target_issue['description'],
1175 'old_epi_name': existing_epi['description'],
1176 'old_epi_start': exist_range[0].strftime('%m/%y'),
1177 'old_epi_end': exist_range[1].strftime('%m/%y')
1178 }
1179 dlg = gmGuiHelpers.c3ButtonQuestionDlg (
1180 parent = None,
1181 id = -1,
1182 caption = _('Resolving two-running-episodes conflict'),
1183 question = question,
1184 button_defs = [
1185 {'label': _('old episode'), 'default': True, 'tooltip': _('close existing episode "%s"') % existing_epi['description']},
1186 {'label': _('new episode'), 'default': False, 'tooltip': _('close moving (new) episode "%s"') % episode['description']}
1187 ]
1188 )
1189 decision = dlg.ShowModal()
1190
1191 if decision == wx.ID_CANCEL:
1192
1193 return False
1194
1195 elif decision == wx.ID_YES:
1196
1197 existing_epi['episode_open'] = False
1198 existing_epi.save_payload()
1199
1200 elif decision == wx.ID_NO:
1201
1202 episode['episode_open'] = False
1203
1204 else:
1205 raise ValueError('invalid result from c3ButtonQuestionDlg: [%s]' % decision)
1206
1207 episode['pk_health_issue'] = target_issue['pk_health_issue']
1208 if save_to_backend:
1209 episode.save_payload()
1210 return True
1211
1235
1237 """Let user select an episode *description*.
1238
1239 The user can select an episode description from the previously
1240 used descriptions across all episodes across all patients.
1241
1242 Selection is done with a phrasewheel so the user can
1243 type the episode name and matches will be shown. Typing
1244 "*" will show the entire list of episodes.
1245
1246 If the user types a description not existing yet a
1247 new episode description will be returned.
1248 """
1250
1251 mp = gmMatchProvider.cMatchProvider_SQL2 (
1252 queries = [u"""
1253 select distinct on (description) description, description, 1
1254 from clin.episode
1255 where description %(fragment_condition)s
1256 order by description
1257 limit 30"""
1258 ]
1259 )
1260 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
1261 self.matcher = mp
1262
1264 """Let user select an episode.
1265
1266 The user can select an episode from the existing episodes of a
1267 patient. Selection is done with a phrasewheel so the user
1268 can type the episode name and matches will be shown. Typing
1269 "*" will show the entire list of episodes. Closed episodes
1270 will be marked as such. If the user types an episode name not
1271 in the list of existing episodes a new episode can be created
1272 from it if the programmer activated that feature.
1273
1274 If keyword <patient_id> is set to None or left out the control
1275 will listen to patient change signals and therefore act on
1276 gmPerson.gmCurrentPatient() changes.
1277 """
1279
1280 ctxt = {'ctxt_pat': {'where_part': u'and pk_patient = %(pat)s', 'placeholder': u'pat'}}
1281
1282 mp = gmMatchProvider.cMatchProvider_SQL2 (
1283 queries = [
1284 u"""(
1285
1286 select
1287 pk_episode,
1288 coalesce (
1289 description || ' - ' || health_issue,
1290 description
1291 ) as description,
1292 1 as rank
1293 from
1294 clin.v_pat_episodes
1295 where
1296 episode_open is true and
1297 description %(fragment_condition)s
1298 %(ctxt_pat)s
1299
1300 ) union all (
1301
1302 select
1303 pk_episode,
1304 coalesce (
1305 description || _(' (closed)') || ' - ' || health_issue,
1306 description || _(' (closed)')
1307 ) as description,
1308 2 as rank
1309 from
1310 clin.v_pat_episodes
1311 where
1312 description %(fragment_condition)s and
1313 episode_open is false
1314 %(ctxt_pat)s
1315
1316 )
1317 order by rank, description
1318 limit 30"""
1319 ],
1320 context = ctxt
1321 )
1322
1323 try:
1324 kwargs['patient_id']
1325 except KeyError:
1326 kwargs['patient_id'] = None
1327
1328 if kwargs['patient_id'] is None:
1329 self.use_current_patient = True
1330 self.__register_patient_change_signals()
1331 pat = gmPerson.gmCurrentPatient()
1332 if pat.connected:
1333 mp.set_context('pat', pat.ID)
1334 else:
1335 self.use_current_patient = False
1336 self.__patient_id = int(kwargs['patient_id'])
1337 mp.set_context('pat', self.__patient_id)
1338
1339 del kwargs['patient_id']
1340
1341 gmPhraseWheel.cPhraseWheel.__init__ (
1342 self,
1343 *args,
1344 **kwargs
1345 )
1346 self.matcher = mp
1347
1348
1349
1351 if self.use_current_patient:
1352 return False
1353 self.__patient_id = int(patient_id)
1354 self.set_context('pat', self.__patient_id)
1355 return True
1356
1357 - def GetData(self, can_create=False, as_instance=False, is_open=False):
1361
1363
1364 epi_name = self.GetValue().strip()
1365 if epi_name == u'':
1366 gmDispatcher.send(signal = u'statustext', msg = _('Cannot create episode without name.'), beep = True)
1367 _log.debug('cannot create episode without name')
1368 return
1369
1370 if self.use_current_patient:
1371 pat = gmPerson.gmCurrentPatient()
1372 else:
1373 pat = gmPerson.cPatient(aPK_obj = self.__patient_id)
1374
1375 emr = pat.get_emr()
1376 epi = emr.add_episode(episode_name = epi_name, is_open = self.__is_open_for_create_data)
1377 if epi is None:
1378 self.data = None
1379 else:
1380 self.data = epi['pk_episode']
1381
1384
1385
1386
1390
1393
1395 if self.use_current_patient:
1396 patient = gmPerson.gmCurrentPatient()
1397 self.set_context('pat', patient.ID)
1398 return True
1399
1400 from Gnumed.wxGladeWidgets import wxgEpisodeEditAreaPnl
1401
1402 -class cEpisodeEditAreaPnl(gmEditArea.cGenericEditAreaMixin, wxgEpisodeEditAreaPnl.wxgEpisodeEditAreaPnl):
1403
1416
1417
1418
1420
1421 errors = False
1422
1423 if len(self._PRW_description.GetValue().strip()) == 0:
1424 errors = True
1425 self._PRW_description.display_as_valid(False)
1426 self._PRW_description.SetFocus()
1427 else:
1428 self._PRW_description.display_as_valid(True)
1429 self._PRW_description.Refresh()
1430
1431 return not errors
1432
1434
1435 pat = gmPerson.gmCurrentPatient()
1436 emr = pat.get_emr()
1437
1438 epi = emr.add_episode(episode_name = self._PRW_description.GetValue().strip())
1439 epi['summary'] = self._TCTRL_summary.GetValue().strip()
1440 epi['episode_open'] = not self._CHBOX_closed.IsChecked()
1441 epi['diagnostic_certainty_classification'] = self._PRW_classification.GetData()
1442
1443 issue_name = self._PRW_issue.GetValue().strip()
1444 if len(issue_name) != 0:
1445 epi['pk_health_issue'] = self._PRW_issue.GetData(can_create = True)
1446 issue = gmEMRStructItems.cHealthIssue(aPK_obj = epi['pk_health_issue'])
1447
1448 if not move_episode_to_issue(episode = epi, target_issue = issue, save_to_backend = False):
1449 gmDispatcher.send (
1450 signal = 'statustext',
1451 msg = _('Cannot attach episode [%s] to health issue [%s] because it already has a running episode.') % (
1452 epi['description'],
1453 issue['description']
1454 )
1455 )
1456 gmEMRStructItems.delete_episode(episode = epi)
1457 return False
1458
1459 epi.save()
1460
1461 self.data = epi
1462 return True
1463
1465
1466 self.data['description'] = self._PRW_description.GetValue().strip()
1467 self.data['summary'] = self._TCTRL_summary.GetValue().strip()
1468 self.data['episode_open'] = not self._CHBOX_closed.IsChecked()
1469 self.data['diagnostic_certainty_classification'] = self._PRW_classification.GetData()
1470
1471 issue_name = self._PRW_issue.GetValue().strip()
1472 if len(issue_name) != 0:
1473 self.data['pk_health_issue'] = self._PRW_issue.GetData(can_create = True)
1474 issue = gmEMRStructItems.cHealthIssue(aPK_obj = self.data['pk_health_issue'])
1475
1476 if not move_episode_to_issue(episode = self.data, target_issue = issue, save_to_backend = False):
1477 gmDispatcher.send (
1478 signal = 'statustext',
1479 msg = _('Cannot attach episode [%s] to health issue [%s] because it already has a running episode.') % (
1480 self.data['description'],
1481 issue['description']
1482 )
1483 )
1484 return False
1485
1486 self.data.save()
1487 return True
1488
1500
1516
1518 self._refresh_as_new()
1519
1520
1521
1531
1533
1534
1535
1537
1538 issues = kwargs['issues']
1539 del kwargs['issues']
1540
1541 gmListWidgets.cGenericListSelectorDlg.__init__(self, *args, **kwargs)
1542
1543 self.SetTitle(_('Select the health issues you are interested in ...'))
1544 self._LCTRL_items.set_columns([u'', _('Health Issue'), u'', u'', u''])
1545
1546 for issue in issues:
1547 if issue['is_confidential']:
1548 row_num = self._LCTRL_items.InsertStringItem(sys.maxint, label = _('confidential'))
1549 self._LCTRL_items.SetItemTextColour(row_num, col=wx.NamedColour('RED'))
1550 else:
1551 row_num = self._LCTRL_items.InsertStringItem(sys.maxint, label = u'')
1552
1553 self._LCTRL_items.SetStringItem(index = row_num, col = 1, label = issue['description'])
1554 if issue['clinically_relevant']:
1555 self._LCTRL_items.SetStringItem(index = row_num, col = 2, label = _('relevant'))
1556 if issue['is_active']:
1557 self._LCTRL_items.SetStringItem(index = row_num, col = 3, label = _('active'))
1558 if issue['is_cause_of_death']:
1559 self._LCTRL_items.SetStringItem(index = row_num, col = 4, label = _('fatal'))
1560
1561 self._LCTRL_items.set_column_widths()
1562 self._LCTRL_items.set_data(data = issues)
1563
1565 """Let the user select a health issue.
1566
1567 The user can select a health issue from the existing issues
1568 of a patient. Selection is done with a phrasewheel so the user
1569 can type the issue name and matches will be shown. Typing
1570 "*" will show the entire list of issues. Inactive issues
1571 will be marked as such. If the user types an issue name not
1572 in the list of existing issues a new issue can be created
1573 from it if the programmer activated that feature.
1574
1575 If keyword <patient_id> is set to None or left out the control
1576 will listen to patient change signals and therefore act on
1577 gmPerson.gmCurrentPatient() changes.
1578 """
1580
1581 ctxt = {'ctxt_pat': {'where_part': u'pk_patient=%(pat)s', 'placeholder': u'pat'}}
1582
1583 mp = gmMatchProvider.cMatchProvider_SQL2 (
1584
1585 queries = [u"""
1586 (select pk_health_issue, description, 1
1587 from clin.v_health_issues where
1588 is_active is true and
1589 description %(fragment_condition)s and
1590 %(ctxt_pat)s
1591 order by description)
1592
1593 union
1594
1595 (select pk_health_issue, description || _(' (inactive)'), 2
1596 from clin.v_health_issues where
1597 is_active is false and
1598 description %(fragment_condition)s and
1599 %(ctxt_pat)s
1600 order by description)"""
1601 ],
1602 context = ctxt
1603 )
1604
1605 try: kwargs['patient_id']
1606 except KeyError: kwargs['patient_id'] = None
1607
1608 if kwargs['patient_id'] is None:
1609 self.use_current_patient = True
1610 self.__register_patient_change_signals()
1611 pat = gmPerson.gmCurrentPatient()
1612 if pat.connected:
1613 mp.set_context('pat', pat.ID)
1614 else:
1615 self.use_current_patient = False
1616 self.__patient_id = int(kwargs['patient_id'])
1617 mp.set_context('pat', self.__patient_id)
1618
1619 del kwargs['patient_id']
1620
1621 gmPhraseWheel.cPhraseWheel.__init__ (
1622 self,
1623 *args,
1624 **kwargs
1625 )
1626 self.matcher = mp
1627
1628
1629
1631 if self.use_current_patient:
1632 return False
1633 self.__patient_id = int(patient_id)
1634 self.set_context('pat', self.__patient_id)
1635 return True
1636
1637 - def GetData(self, can_create=False, is_open=False):
1655
1656
1657
1661
1664
1666 if self.use_current_patient:
1667 patient = gmPerson.gmCurrentPatient()
1668 self.set_context('pat', patient.ID)
1669 return True
1670
1672
1674 try:
1675 msg = kwargs['message']
1676 except KeyError:
1677 msg = None
1678 del kwargs['message']
1679 wxgIssueSelectionDlg.wxgIssueSelectionDlg.__init__(self, *args, **kwargs)
1680 if msg is not None:
1681 self._lbl_message.SetLabel(label=msg)
1682
1693
1694 from Gnumed.wxGladeWidgets import wxgHealthIssueEditAreaPnl
1695
1696 -class cHealthIssueEditAreaPnl(gmEditArea.cGenericEditAreaMixin, wxgHealthIssueEditAreaPnl.wxgHealthIssueEditAreaPnl):
1697 """Panel encapsulating health issue edit area functionality."""
1698
1700
1701 try:
1702 issue = kwargs['issue']
1703 except KeyError:
1704 issue = None
1705
1706 wxgHealthIssueEditAreaPnl.wxgHealthIssueEditAreaPnl.__init__(self, *args, **kwargs)
1707
1708 gmEditArea.cGenericEditAreaMixin.__init__(self)
1709
1710
1711 mp = gmMatchProvider.cMatchProvider_SQL2 (
1712 queries = [u"SELECT DISTINCT ON (description) description, description FROM clin.health_issue WHERE description %(fragment_condition)s LIMIT 50"]
1713 )
1714 mp.setThresholds(1, 3, 5)
1715 self._PRW_condition.matcher = mp
1716
1717 mp = gmMatchProvider.cMatchProvider_SQL2 (
1718 queries = [u"""
1719 select distinct on (grouping) grouping, grouping from (
1720
1721 select rank, grouping from ((
1722
1723 select
1724 grouping,
1725 1 as rank
1726 from
1727 clin.health_issue
1728 where
1729 grouping %%(fragment_condition)s
1730 and
1731 (select True from clin.encounter where fk_patient = %s and pk = clin.health_issue.fk_encounter)
1732
1733 ) union (
1734
1735 select
1736 grouping,
1737 2 as rank
1738 from
1739 clin.health_issue
1740 where
1741 grouping %%(fragment_condition)s
1742
1743 )) as union_result
1744
1745 order by rank
1746
1747 ) as order_result
1748
1749 limit 50""" % gmPerson.gmCurrentPatient().ID
1750 ]
1751 )
1752 mp.setThresholds(1, 3, 5)
1753 self._PRW_grouping.matcher = mp
1754
1755 self._PRW_age_noted.add_callback_on_lose_focus(self._on_leave_age_noted)
1756 self._PRW_year_noted.add_callback_on_lose_focus(self._on_leave_year_noted)
1757
1758 self._PRW_age_noted.add_callback_on_modified(self._on_modified_age_noted)
1759 self._PRW_year_noted.add_callback_on_modified(self._on_modified_year_noted)
1760
1761 self._PRW_year_noted.Enable(True)
1762
1763 self.data = issue
1764
1765
1766
1786
1788 pat = gmPerson.gmCurrentPatient()
1789 emr = pat.get_emr()
1790
1791 issue = emr.add_health_issue(issue_name = self._PRW_condition.GetValue().strip())
1792
1793 side = u''
1794 if self._ChBOX_left.GetValue():
1795 side += u's'
1796 if self._ChBOX_right.GetValue():
1797 side += u'd'
1798 issue['laterality'] = side
1799
1800 issue['summary'] = self._TCTRL_summary.GetValue().strip()
1801 issue['diagnostic_certainty_classification'] = self._PRW_classification.GetData()
1802 issue['grouping'] = self._PRW_grouping.GetValue().strip()
1803 issue['is_active'] = self._ChBOX_active.GetValue()
1804 issue['clinically_relevant'] = self._ChBOX_relevant.GetValue()
1805 issue['is_confidential'] = self._ChBOX_confidential.GetValue()
1806 issue['is_cause_of_death'] = self._ChBOX_caused_death.GetValue()
1807
1808 age_noted = self._PRW_age_noted.GetData()
1809 if age_noted is not None:
1810 issue['age_noted'] = age_noted
1811
1812 issue.save()
1813
1814 self.data = issue
1815 return True
1816
1818
1819 self.data['description'] = self._PRW_condition.GetValue().strip()
1820
1821 side = u''
1822 if self._ChBOX_left.GetValue():
1823 side += u's'
1824 if self._ChBOX_right.GetValue():
1825 side += u'd'
1826 self.data['laterality'] = side
1827
1828 self.data['summary'] = self._TCTRL_summary.GetValue().strip()
1829 self.data['diagnostic_certainty_classification'] = self._PRW_classification.GetData()
1830 self.data['grouping'] = self._PRW_grouping.GetValue().strip()
1831 self.data['is_active'] = bool(self._ChBOX_active.GetValue())
1832 self.data['clinically_relevant'] = bool(self._ChBOX_relevant.GetValue())
1833 self.data['is_confidential'] = bool(self._ChBOX_confidential.GetValue())
1834 self.data['is_cause_of_death'] = bool(self._ChBOX_caused_death.GetValue())
1835
1836 age_noted = self._PRW_age_noted.GetData()
1837 if age_noted is not None:
1838 self.data['age_noted'] = age_noted
1839
1840 self.data.save()
1841
1842
1843 return True
1844
1846 self._PRW_condition.SetText()
1847 self._ChBOX_left.SetValue(0)
1848 self._ChBOX_right.SetValue(0)
1849 self._PRW_classification.SetText()
1850 self._PRW_grouping.SetText()
1851 self._TCTRL_summary.SetValue(u'')
1852 self._PRW_age_noted.SetText()
1853 self._PRW_year_noted.SetText()
1854 self._ChBOX_active.SetValue(0)
1855 self._ChBOX_relevant.SetValue(1)
1856 self._ChBOX_is_operation.SetValue(0)
1857 self._ChBOX_confidential.SetValue(0)
1858 self._ChBOX_caused_death.SetValue(0)
1859
1860 return True
1861
1863 self._PRW_condition.SetText(self.data['description'])
1864
1865 lat = gmTools.coalesce(self.data['laterality'], '')
1866 if lat.find('s') == -1:
1867 self._ChBOX_left.SetValue(0)
1868 else:
1869 self._ChBOX_left.SetValue(1)
1870 if lat.find('d') == -1:
1871 self._ChBOX_right.SetValue(0)
1872 else:
1873 self._ChBOX_right.SetValue(1)
1874
1875 self._PRW_classification.SetData(data = self.data['diagnostic_certainty_classification'])
1876 self._PRW_grouping.SetText(gmTools.coalesce(self.data['grouping'], u''))
1877 self._TCTRL_summary.SetValue(gmTools.coalesce(self.data['summary'], u''))
1878
1879 if self.data['age_noted'] is None:
1880 self._PRW_age_noted.SetText()
1881 else:
1882 self._PRW_age_noted.SetText (
1883 value = '%sd' % self.data['age_noted'].days,
1884 data = self.data['age_noted']
1885 )
1886
1887 self._ChBOX_active.SetValue(self.data['is_active'])
1888 self._ChBOX_relevant.SetValue(self.data['clinically_relevant'])
1889 self._ChBOX_is_operation.SetValue(0)
1890 self._ChBOX_confidential.SetValue(self.data['is_confidential'])
1891 self._ChBOX_caused_death.SetValue(self.data['is_cause_of_death'])
1892
1893
1894
1895
1896
1897 return True
1898
1900 return self._refresh_as_new()
1901
1902
1903
1905
1906 if not self._PRW_age_noted.IsModified():
1907 return True
1908
1909 str_age = self._PRW_age_noted.GetValue().strip()
1910
1911 if str_age == u'':
1912 wx.CallAfter(self._PRW_year_noted.SetText, u'', None, True)
1913 return True
1914
1915 age = gmDateTime.str2interval(str_interval = str_age)
1916
1917 if age is None:
1918 gmDispatcher.send(signal='statustext', msg=_('Cannot parse [%s] into valid interval.') % str_age)
1919 self._PRW_age_noted.SetBackgroundColour('pink')
1920 self._PRW_age_noted.Refresh()
1921 wx.CallAfter(self._PRW_year_noted.SetText, u'', None, True)
1922 return True
1923
1924 pat = gmPerson.gmCurrentPatient()
1925 if pat['dob'] is not None:
1926 max_age = pydt.datetime.now(tz=pat['dob'].tzinfo) - pat['dob']
1927
1928 if age >= max_age:
1929 gmDispatcher.send (
1930 signal = 'statustext',
1931 msg = _(
1932 'Health issue cannot have been noted at age %s. Patient is only %s old.'
1933 ) % (age, pat.get_medical_age())
1934 )
1935 self._PRW_age_noted.SetBackgroundColour('pink')
1936 self._PRW_age_noted.Refresh()
1937 wx.CallAfter(self._PRW_year_noted.SetText, u'', None, True)
1938 return True
1939
1940 self._PRW_age_noted.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
1941 self._PRW_age_noted.Refresh()
1942 self._PRW_age_noted.SetData(data=age)
1943
1944 if pat['dob'] is not None:
1945 fts = gmDateTime.cFuzzyTimestamp (
1946 timestamp = pat['dob'] + age,
1947 accuracy = gmDateTime.acc_months
1948 )
1949 wx.CallAfter(self._PRW_year_noted.SetText, str(fts), fts)
1950
1951
1952
1953
1954
1955 return True
1956
1958
1959 if not self._PRW_year_noted.IsModified():
1960 return True
1961
1962 year_noted = self._PRW_year_noted.GetData()
1963
1964 if year_noted is None:
1965 if self._PRW_year_noted.GetValue().strip() == u'':
1966 wx.CallAfter(self._PRW_age_noted.SetText, u'', None, True)
1967 return True
1968 self._PRW_year_noted.SetBackgroundColour('pink')
1969 self._PRW_year_noted.Refresh()
1970 wx.CallAfter(self._PRW_age_noted.SetText, u'', None, True)
1971 return True
1972
1973 year_noted = year_noted.get_pydt()
1974
1975 if year_noted >= pydt.datetime.now(tz=year_noted.tzinfo):
1976 gmDispatcher.send(signal='statustext', msg=_('Condition diagnosed in the future.'))
1977 self._PRW_year_noted.SetBackgroundColour('pink')
1978 self._PRW_year_noted.Refresh()
1979 wx.CallAfter(self._PRW_age_noted.SetText, u'', None, True)
1980 return True
1981
1982 self._PRW_year_noted.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
1983 self._PRW_year_noted.Refresh()
1984
1985 pat = gmPerson.gmCurrentPatient()
1986 if pat['dob'] is not None:
1987 issue_age = year_noted - pat['dob']
1988 str_age = gmDateTime.format_interval_medically(interval = issue_age)
1989 wx.CallAfter(self._PRW_age_noted.SetText, str_age, issue_age)
1990
1991 return True
1992
1994 wx.CallAfter(self._PRW_year_noted.SetText, u'', None, True)
1995 return True
1996
1998 wx.CallAfter(self._PRW_age_noted.SetText, u'', None, True)
1999 return True
2000
2001
2002
2004
2006
2007 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
2008
2009 self.selection_only = False
2010
2011 mp = gmMatchProvider.cMatchProvider_FixedList (
2012 aSeq = [
2013 {'data': u'A', 'label': gmEMRStructItems.diagnostic_certainty_classification2str(u'A'), 'weight': 1},
2014 {'data': u'B', 'label': gmEMRStructItems.diagnostic_certainty_classification2str(u'B'), 'weight': 1},
2015 {'data': u'C', 'label': gmEMRStructItems.diagnostic_certainty_classification2str(u'C'), 'weight': 1},
2016 {'data': u'D', 'label': gmEMRStructItems.diagnostic_certainty_classification2str(u'D'), 'weight': 1}
2017 ]
2018 )
2019 mp.setThresholds(1, 2, 4)
2020 self.matcher = mp
2021
2022 self.SetToolTipString(_(
2023 "The diagnostic classification or grading of this assessment.\n"
2024 "\n"
2025 "This documents how certain one is about this being a true diagnosis."
2026 ))
2027
2028
2029
2030 if __name__ == '__main__':
2031
2032
2034 """
2035 Test application for testing EMR struct widgets
2036 """
2037
2039 """
2040 Create test application UI
2041 """
2042 frame = wx.Frame (
2043 None,
2044 -4,
2045 'Testing EMR struct widgets',
2046 size=wx.Size(600, 400),
2047 style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE
2048 )
2049 filemenu= wx.Menu()
2050 filemenu.AppendSeparator()
2051 filemenu.Append(ID_EXIT,"E&xit"," Terminate test application")
2052
2053
2054 menuBar = wx.MenuBar()
2055 menuBar.Append(filemenu,"&File")
2056
2057 frame.SetMenuBar(menuBar)
2058
2059 txt = wx.StaticText( frame, -1, _("Select desired test option from the 'File' menu"),
2060 wx.DefaultPosition, wx.DefaultSize, 0 )
2061
2062
2063 wx.EVT_MENU(frame, ID_EXIT, self.OnCloseWindow)
2064
2065
2066 self.__pat = gmPerson.gmCurrentPatient()
2067
2068 frame.Show(1)
2069 return 1
2070
2072 """
2073 Close test aplication
2074 """
2075 self.ExitMainLoop ()
2076
2078 app = wx.PyWidgetTester(size = (200, 300))
2079 emr = pat.get_emr()
2080 enc = emr.active_encounter
2081
2082 pnl = cEncounterEditAreaPnl(app.frame, -1, encounter=enc)
2083 app.frame.Show(True)
2084 app.MainLoop()
2085 return
2086
2088 app = wx.PyWidgetTester(size = (200, 300))
2089 emr = pat.get_emr()
2090 enc = emr.active_encounter
2091
2092
2093 dlg = cEncounterEditAreaDlg(parent=app.frame, id=-1, size = (400,400), encounter=enc)
2094 dlg.ShowModal()
2095
2096
2097
2098
2099
2101 app = wx.PyWidgetTester(size = (200, 300))
2102 emr = pat.get_emr()
2103 epi = emr.get_episodes()[0]
2104 pnl = cEpisodeEditAreaPnl(app.frame, -1, episode=epi)
2105 app.frame.Show(True)
2106 app.MainLoop()
2107
2113
2115 app = wx.PyWidgetTester(size = (400, 40))
2116 app.SetWidget(cHospitalStayPhraseWheel, id=-1, size=(180,20), pos=(10,20))
2117 app.MainLoop()
2118
2120 app = wx.PyWidgetTester(size = (400, 40))
2121 app.SetWidget(cEpisodeSelectionPhraseWheel, id=-1, size=(180,20), pos=(10,20))
2122
2123 app.MainLoop()
2124
2126 app = wx.PyWidgetTester(size = (200, 300))
2127 edit_health_issue(parent=app.frame, issue=None)
2128
2130 app = wx.PyWidgetTester(size = (200, 300))
2131 app.SetWidget(cHealthIssueEditAreaPnl, id=-1, size = (400,400))
2132 app.MainLoop()
2133
2135 app = wx.PyWidgetTester(size = (200, 300))
2136 edit_procedure(parent=app.frame)
2137
2138
2139 if (len(sys.argv) > 1) and (sys.argv[1] == 'test'):
2140
2141 gmI18N.activate_locale()
2142 gmI18N.install_domain()
2143 gmDateTime.init()
2144
2145
2146 pat = gmPersonSearch.ask_for_patient()
2147 if pat is None:
2148 print "No patient. Exiting gracefully..."
2149 sys.exit(0)
2150 gmPatSearchWidgets.set_active_patient(patient=pat)
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168 test_edit_procedure()
2169
2170
2171