1 """GNUmed patient overview widgets.
2
3 copyright: authors
4 """
5
6 __author__ = "K.Hilbert"
7 __license__ = "GPL v2 or later (details at http://www.gnu.org)"
8
9 import logging, sys
10
11
12 import wx
13
14
15 if __name__ == '__main__':
16 sys.path.insert(0, '../../')
17 from Gnumed.pycommon import gmTools
18 from Gnumed.pycommon import gmDispatcher
19 from Gnumed.pycommon import gmDateTime
20
21 from Gnumed.business import gmPerson
22 from Gnumed.business import gmStaff
23 from Gnumed.business import gmDemographicRecord
24 from Gnumed.business import gmEMRStructItems
25 from Gnumed.business import gmFamilyHistory
26 from Gnumed.business import gmVaccination
27 from Gnumed.business import gmDocuments
28 from Gnumed.business import gmProviderInbox
29
30 from Gnumed.wxpython import gmRegetMixin
31 from Gnumed.wxpython import gmDemographicsWidgets
32 from Gnumed.wxpython import gmContactWidgets
33 from Gnumed.wxpython import gmMedicationWidgets
34 from Gnumed.wxpython import gmEditArea
35 from Gnumed.wxpython import gmEMRStructWidgets
36 from Gnumed.wxpython import gmFamilyHistoryWidgets
37 from Gnumed.wxpython import gmVaccWidgets
38 from Gnumed.wxpython import gmDocumentWidgets
39
40
41 _log = logging.getLogger('gm.patient')
42
43 from Gnumed.wxGladeWidgets import wxgPatientOverviewPnl
44
45 -class cPatientOverviewPnl(wxgPatientOverviewPnl.wxgPatientOverviewPnl, gmRegetMixin.cRegetOnPaintMixin):
46
53
54
55
91
93 self._LCTRL_identity.set_string_items()
94 self._LCTRL_contacts.set_string_items()
95 self._LCTRL_encounters.set_string_items()
96 self._PRW_encounter_range.SetText(value = u'', data = None)
97
98 self._LCTRL_problems.set_string_items()
99 self._LCTRL_meds.set_string_items()
100 self._LCTRL_history.set_string_items()
101
102 self._LCTRL_inbox.set_string_items()
103 self._LCTRL_documents.set_string_items()
104
105
106
107
108
109
110
112
113 gmDispatcher.connect(signal = u'pre_patient_selection', receiver = self._on_pre_patient_selection)
114 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection)
115
116
117
118 gmDispatcher.connect(signal = u'identity_mod_db', receiver = self._on_post_patient_selection)
119 gmDispatcher.connect(signal = u'name_mod_db', receiver = self._on_post_patient_selection)
120 gmDispatcher.connect(signal = u'comm_channel_mod_db', receiver = self._on_post_patient_selection)
121 gmDispatcher.connect(signal = u'job_mod_db', receiver = self._on_post_patient_selection)
122
123
124
125
126
127
128
129
130 gmDispatcher.connect(signal = u'episode_mod_db', receiver = self._on_episode_issue_mod_db)
131
132 gmDispatcher.connect(signal = u'health_issue_mod_db', receiver = self._on_episode_issue_mod_db)
133
134 gmDispatcher.connect(signal = u'substance_intake_mod_db', receiver = self._on_post_patient_selection)
135
136 gmDispatcher.connect(signal = u'hospital_stay_mod_db', receiver = self._on_post_patient_selection)
137 gmDispatcher.connect(signal = u'family_history_mod_db', receiver = self._on_post_patient_selection)
138 gmDispatcher.connect(signal = u'procedure_mod_db', receiver = self._on_post_patient_selection)
139 gmDispatcher.connect(signal = u'vacc_mod_db', receiver = self._on_post_patient_selection)
140
141 gmDispatcher.connect(signal = u'message_inbox_mod_db', receiver = self._on_post_patient_selection)
142 gmDispatcher.connect(signal = u'doc_mod_db', receiver = self._on_post_patient_selection)
143
144
145
146
147
148 self._PRW_encounter_range.add_callback_on_selection(callback = self._on_encounter_range_selected)
149
152
154 wx.CallAfter(self._schedule_data_reget)
155
157 wx.CallAfter(self._schedule_data_reget)
158
160 wx.CallAfter(self._schedule_data_reget)
161
162
163
165 pat = gmPerson.gmCurrentPatient()
166 if not pat.connected:
167 self.__reset_ui_content()
168 return True
169
170 self.__refresh_identity(patient = pat)
171 self.__refresh_contacts(patient = pat)
172 self.__refresh_encounters(patient = pat)
173
174 self.__refresh_problems(patient = pat)
175 self.__refresh_meds(patient = pat)
176 self.__refresh_history(patient = pat)
177
178 self.__refresh_inbox(patient = pat)
179 self.__refresh_documents(patient = pat)
180
181 return True
182
183
184
186 list_items = []
187 list_data = []
188
189 for msg in patient.messages:
190 list_items.append(u'%s%s' % (
191 msg['l10n_type'],
192 gmTools.coalesce(msg['comment'], u'', u': %s')
193 ))
194 list_data.append(msg)
195
196 self._LCTRL_inbox.set_string_items(items = list_items)
197 self._LCTRL_inbox.set_data(data = list_data)
198
204
206
207
208
209
210
211
212
213 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmProviderInboxPlugin')
214 return
215
216
218 doc_folder = patient.get_document_folder()
219
220 list_items = []
221 list_data = []
222
223 docs = doc_folder.get_unsigned_documents()
224 no_of_unsigned = len(docs)
225 for doc in docs:
226 list_items.append(u'%s %s (%s)' % (
227 gmDateTime.pydt_strftime(doc['clin_when'], format = '%m/%Y', accuracy = gmDateTime.acc_months),
228 doc['l10n_type'],
229 gmTools.u_writing_hand
230 ))
231 list_data.append(doc)
232
233 docs = doc_folder.get_documents(order_by = u'ORDER BY clin_when DESC', exclude_unsigned = True)
234 for doc in docs[:5]:
235 list_items.append(u'%s %s' % (
236 gmDateTime.pydt_strftime(doc['clin_when'], format = '%m/%Y', accuracy = gmDateTime.acc_months),
237 doc['l10n_type']
238 ))
239 list_data.append(doc)
240 if len(docs) > 5:
241 list_items.append(_('%s %s more not shown %s') % (
242 gmTools.u_ellipsis,
243 len(docs) - 5,
244 gmTools.u_ellipsis
245 ))
246 list_data.append(u'')
247
248 self._LCTRL_documents.set_string_items(items = list_items)
249 self._LCTRL_documents.set_data(data = list_data)
250
251 if no_of_unsigned > 0:
252 for idx in range(no_of_unsigned):
253 self._LCTRL_documents.SetItemTextColour(idx, wx.NamedColour('RED'))
254
262
278
279
281
282 cover_period = self._PRW_encounter_range.GetData()
283 if cover_period is None:
284 if self._PRW_encounter_range.GetValue().strip() != u'':
285 return
286
287 emr = patient.get_emr()
288
289 list_items = []
290 list_data = []
291
292 is_waiting = False
293 wlist = patient.get_waiting_list_entry()
294 if len(wlist) > 0:
295 is_waiting = True
296 w = wlist[0]
297 list_items.append(_('Currently in waiting list [%s]') % w['waiting_zone'])
298 list_data.append({'wlist': gmTools.coalesce(w['comment'], None)})
299
300 first = emr.get_first_encounter()
301 if first is not None:
302 list_items.append (
303 _('first: %s, %s') % (
304 gmDateTime.pydt_strftime (
305 first['started'],
306 format = '%Y %b %d',
307 accuracy = gmDateTime.acc_days
308 ),
309 first['l10n_type']
310 )
311 )
312 list_data.append(first)
313
314 last = emr.get_last_encounter()
315 if last is not None:
316 list_items.append (
317 _('last: %s, %s') % (
318 gmDateTime.pydt_strftime (
319 first['started'],
320 format = '%Y %b %d',
321 accuracy = gmDateTime.acc_days
322 ),
323 first['l10n_type']
324 )
325 )
326 list_data.append(last)
327
328 encs = emr.get_encounter_stats_by_type(cover_period = cover_period)
329 for enc in encs:
330 item = u'%s x %s' % (enc['frequency'], enc['l10n_type'])
331 list_items.append(item)
332 list_data.append(item)
333
334 stays = emr.get_hospital_stay_stats_by_hospital(cover_period = cover_period)
335 for stay in stays:
336 item = u'%s x %s' % (
337 stay['frequency'],
338 stay['hospital']
339 )
340 list_items.append(item)
341 list_data.append({'stay': item})
342
343 self._LCTRL_encounters.set_string_items(items = list_items)
344 self._LCTRL_encounters.set_data(data = list_data)
345 if is_waiting:
346 self._LCTRL_encounters.SetItemTextColour(0, wx.NamedColour('RED'))
347
368
388
389
390 - def __refresh_history(self, patient=None):
391 emr = patient.get_emr()
392
393 list_items = []
394 list_data = []
395
396 issues = [
397 i for i in emr.get_health_issues()
398 if ((i['clinically_relevant'] is False) or (i['is_active'] is False))
399 ]
400 for issue in issues:
401 last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue'])
402 if last_encounter is None:
403 last = issue['modified_when'].strftime('%m/%Y')
404 else:
405 last = last_encounter['last_affirmed'].strftime('%m/%Y')
406 list_items.append(u'%s %s' % (last, issue['description']))
407 list_data.append(issue)
408 del issues
409
410 fhxs = emr.get_family_history()
411 for fhx in fhxs:
412 list_items.append(u'%s: %s%s' % (
413 fhx['l10n_relation'],
414 fhx['condition'],
415 gmTools.coalesce(fhx['age_noted'], u'', u' (@ %s)')
416 ))
417 list_data.append(fhx)
418 del fhxs
419
420 stays = emr.get_hospital_stays()
421 for stay in stays:
422 if stay['discharge'] is not None:
423 discharge = u''
424 else:
425 discharge = gmTools.u_ellipsis
426 list_items.append(u'%s%s %s: %s' % (
427 gmDateTime.pydt_strftime(stay['admission'], format = '%Y %b %d'),
428 discharge,
429 stay['hospital'],
430 stay['episode']
431 ))
432 list_data.append(stay)
433 del stays
434
435 procs = emr.get_performed_procedures()
436 for proc in procs:
437 list_items.append(u'%s%s %s' % (
438 gmDateTime.pydt_strftime(proc['clin_when'], format = '%Y %b %d'),
439 gmTools.bool2subst(proc['is_ongoing'], gmTools.u_ellipsis, u'', u''),
440 proc['performed_procedure']
441 ))
442 list_data.append(proc)
443 del procs
444
445 vaccs = emr.get_latest_vaccinations()
446 for ind, tmp in vaccs.items():
447 tmp, vacc = tmp
448 list_items.append(u'%s %s' % (
449 gmDateTime.pydt_strftime(vacc['date_given'], format = '%Y %b %d'),
450 ind
451 ))
452 list_data.append(vacc)
453 del vaccs
454
455 self._LCTRL_history.set_string_items(items = list_items)
456 self._LCTRL_history.set_data(data = list_data)
457
459
460 if isinstance(data, gmEMRStructItems.cHealthIssue):
461 return data.format (
462 patient = gmPerson.gmCurrentPatient(),
463 with_medications = False,
464 with_hospital_stays = False,
465 with_procedures = False,
466 with_family_history = False,
467 with_documents = False,
468 with_tests = False,
469 with_vaccinations = False
470 ).strip(u'\n')
471
472 if isinstance(data, gmFamilyHistory.cFamilyHistory):
473 return data.format(include_episode = True, include_comment = True)
474
475 if isinstance(data, gmEMRStructItems.cHospitalStay):
476 return data.format()
477
478 if isinstance(data, gmEMRStructItems.cPerformedProcedure):
479 return data.format(include_episode = True)
480
481 if isinstance(data, gmVaccination.cVaccination):
482 return u'\n'.join(data.format (
483 with_indications = True,
484 with_comment = True,
485 with_reaction = True,
486 date_format = '%Y %b %d'
487 ))
488
489 return None
490
492 data = self._LCTRL_history.get_selected_item_data(only_one = True)
493 if data is None:
494 return
495
496
497 if wx.GetKeyState(wx.WXK_CONTROL):
498 if isinstance(data, gmEMRStructItems.cHealthIssue):
499 gmEMRStructWidgets.edit_health_issue(parent = self, issue = data)
500 return
501 if isinstance(data, gmFamilyHistory.cFamilyHistory):
502 FamilyHistoryWidgets.edit_family_history(parent = self, family_history = data)
503 return
504 if isinstance(data, gmEMRStructItems.cHospitalStay):
505 gmEMRStructWidgets.edit_hospital_stay(parent = self, hospital_stay = data)
506 return
507 if isinstance(data, gmEMRStructItems.cPerformedProcedure):
508 gmEMRStructWidgets.edit_procedure(parent = self, procedure = data)
509 return
510 if isinstance(data, gmVaccination.cVaccination):
511 gmVaccWidgets.edit_vaccination(parent = self, vaccination = data, single_entry = True)
512 return
513 return
514
515 if isinstance(data, gmEMRStructItems.cHealthIssue):
516 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmEMRBrowserPlugin')
517 return
518 if isinstance(data, gmFamilyHistory.cFamilyHistory):
519 FamilyHistoryWidgets.manage_family_history(parent = self)
520 return
521 if isinstance(data, gmEMRStructItems.cHospitalStay):
522 gmEMRStructWidgets.manage_hospital_stays(parent = self)
523 return
524 if isinstance(data, gmEMRStructItems.cPerformedProcedure):
525 gmEMRStructWidgets.manage_performed_procedures(parent = self)
526 return
527 if isinstance(data, gmVaccination.cVaccination):
528 gmVaccWidgets.manage_vaccinations(parent = self)
529 return
530
531 return
532
533
535 emr = patient.get_emr()
536 list_items = []
537 meds = emr.get_current_substance_intake(include_inactive = False, include_unapproved = True, order_by = u'substance')
538 for med in meds:
539 list_items.append(_('%s %s %s%s') % (
540 med['substance'],
541 med['amount'],
542 med['unit'],
543 gmTools.coalesce (
544 med['schedule'],
545 u'',
546 u': %s'
547 )
548 ))
549 self._LCTRL_meds.set_string_items(items = list_items)
550 self._LCTRL_meds.set_data(data = meds)
551
564
574
575
629
678
698
699
701 emr = patient.get_emr()
702
703 problems = [
704 p for p in emr.get_problems(include_closed_episodes = False, include_irrelevant_issues = False)
705 if p['problem_active']
706 ]
707
708 list_items = []
709 for problem in problems:
710 if problem['type'] == 'issue':
711 issue = emr.problem2issue(problem)
712 last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue'])
713 if last_encounter is None:
714 last = issue['modified_when'].strftime('%m/%Y')
715 else:
716 last = last_encounter['last_affirmed'].strftime('%m/%Y')
717 list_items.append(u'%s: %s' % (problem['problem'], last))
718
719 elif problem['type'] == 'episode':
720 epi = emr.problem2episode(problem)
721 last_encounter = emr.get_last_encounter(episode_id = epi['pk_episode'])
722 if last_encounter is None:
723 last = epi['episode_modified_when'].strftime('%m/%Y')
724 else:
725 last = last_encounter['last_affirmed'].strftime('%m/%Y')
726 list_items.append(u'%s: %s' % (problem['problem'], last))
727
728 self._LCTRL_problems.set_string_items(items = list_items)
729 self._LCTRL_problems.set_data(data = problems)
730
764
779
780
782
783 names = patient.get_names(exclude_active = True)
784 items = [
785 _('aka: %(last)s, %(first)s%(nick)s') % {
786 'last': n['lastnames'],
787 'first': n['firstnames'],
788 'nick': gmTools.coalesce(n['preferred'], u'', u" '%s'")
789 } for n in names
790 ]
791 data = names
792
793
794 ids = patient.external_ids
795 for i in ids:
796 items.append(u'%(name)s: %(value)s' % i)
797 data.append({'id': i})
798
799
800 jobs = patient.get_occupations()
801 for j in jobs:
802 items.append(_('job: %s') % j['l10n_occupation'])
803 data.append({'job': j})
804
805 self._LCTRL_identity.set_string_items(items = items)
806 self._LCTRL_identity.set_data(data = data)
807
825
827 data = self._LCTRL_identity.get_selected_item_data(only_one = True)
828 if data is not None:
829
830 if wx.GetKeyState(wx.WXK_CONTROL):
831 if isinstance(data, gmPerson.cPersonName):
832 ea = gmDemographicsWidgets.cPersonNameEAPnl(self, -1, name = data)
833 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True)
834 dlg.SetTitle(_('Cloning name'))
835 dlg.ShowModal()
836 return
837 if isinstance(data, type({})):
838 key = data.keys()[0]
839 val = data[key]
840 if key == 'id':
841 ea = gmDemographicsWidgets.cExternalIDEditAreaPnl(self, -1, external_id = val)
842 ea.identity = gmPerson.gmCurrentPatient()
843 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True)
844 dlg.SetTitle(_('Editing external ID'))
845 dlg.ShowModal()
846 return
847 if key == 'job':
848 gmDemographicsWidgets.edit_occupation()
849 return
850
851 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
852
853
854
855 if __name__ == "__main__":
856
857 if len(sys.argv) < 2:
858 sys.exit()
859
860 if sys.argv[1] != u'test':
861 sys.exit()
862
863
864
865
866
867
868
869
870