Package Gnumed :: Package wxpython :: Module gmPatOverviewWidgets
[frames] | no frames]

Source Code for Module Gnumed.wxpython.gmPatOverviewWidgets

   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  from Gnumed.pycommon import gmNetworkTools 
  21   
  22  from Gnumed.business import gmPerson 
  23  from Gnumed.business import gmStaff 
  24  from Gnumed.business import gmDemographicRecord 
  25  from Gnumed.business import gmEMRStructItems 
  26  from Gnumed.business import gmFamilyHistory 
  27  from Gnumed.business import gmVaccination 
  28  from Gnumed.business import gmDocuments 
  29  from Gnumed.business import gmProviderInbox 
  30   
  31  from Gnumed.wxpython import gmRegetMixin 
  32  from Gnumed.wxpython import gmDemographicsWidgets 
  33  from Gnumed.wxpython import gmContactWidgets 
  34  from Gnumed.wxpython import gmMedicationWidgets 
  35  from Gnumed.wxpython import gmEditArea 
  36  from Gnumed.wxpython import gmEMRStructWidgets 
  37  from Gnumed.wxpython import gmFamilyHistoryWidgets 
  38  from Gnumed.wxpython import gmVaccWidgets 
  39  from Gnumed.wxpython import gmDocumentWidgets 
  40  from Gnumed.wxpython import gmGuiHelpers 
  41   
  42   
  43  _log = logging.getLogger('gm.patient') 
  44  #============================================================ 
  45  from Gnumed.wxGladeWidgets import wxgPatientOverviewPnl 
  46   
47 -class cPatientOverviewPnl(wxgPatientOverviewPnl.wxgPatientOverviewPnl, gmRegetMixin.cRegetOnPaintMixin):
48
49 - def __init__(self, *args, **kwargs):
50 wxgPatientOverviewPnl.wxgPatientOverviewPnl.__init__(self, *args, **kwargs) 51 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 52 53 self.__init_ui() 54 self.__register_interests()
55 #-------------------------------------------------------- 56 # internal API 57 #--------------------------------------------------------
58 - def __init_ui(self):
59 # left 60 self._LCTRL_identity.set_columns(columns = [u'']) 61 self._LCTRL_identity.item_tooltip_callback = self._calc_identity_item_tooltip 62 self._LCTRL_identity.activate_callback = self._on_identity_item_activated 63 64 self._LCTRL_contacts.set_columns(columns = [u'']) 65 self._LCTRL_contacts.item_tooltip_callback = self._calc_contacts_list_item_tooltip 66 self._LCTRL_contacts.activate_callback = self._on_contacts_item_activated 67 68 self._LCTRL_encounters.set_columns(columns = [u'']) 69 self._LCTRL_encounters.item_tooltip_callback = self._calc_encounters_list_item_tooltip 70 self._LCTRL_encounters.activate_callback = self._on_encounter_activated 71 72 # middle 73 self._LCTRL_problems.set_columns(columns = [u'']) 74 self._LCTRL_problems.item_tooltip_callback = self._calc_problem_list_item_tooltip 75 self._LCTRL_problems.activate_callback = self._on_problem_activated 76 77 self._LCTRL_meds.set_columns(columns = [u'']) 78 self._LCTRL_meds.item_tooltip_callback = self._calc_meds_list_item_tooltip 79 self._LCTRL_meds.activate_callback = self._on_meds_item_activated 80 81 self._LCTRL_history.set_columns(columns = [u'']) 82 self._LCTRL_history.item_tooltip_callback = self._calc_history_list_item_tooltip 83 self._LCTRL_history.activate_callback = self._on_history_item_activated 84 85 # right hand side 86 self._LCTRL_inbox.set_columns(columns = [u'']) 87 self._LCTRL_inbox.item_tooltip_callback = self._calc_inbox_item_tooltip 88 self._LCTRL_inbox.activate_callback = self._on_inbox_item_activated 89 90 self._LCTRL_results.set_columns(columns = [u'']) 91 self._LCTRL_results.item_tooltip_callback = self._calc_results_list_item_tooltip 92 self._LCTRL_results.activate_callback = self._on_result_activated 93 94 self._LCTRL_documents.set_columns(columns = [u'']) 95 self._LCTRL_documents.item_tooltip_callback = self._calc_documents_list_item_tooltip 96 self._LCTRL_documents.activate_callback = self._on_document_activated
97 #--------------------------------------------------------
98 - def __reset_ui_content(self):
99 self._LCTRL_identity.set_string_items() 100 self._LCTRL_contacts.set_string_items() 101 self._LCTRL_encounters.set_string_items() 102 self._PRW_encounter_range.SetText(value = u'', data = None) 103 104 self._LCTRL_problems.set_string_items() 105 self._LCTRL_meds.set_string_items() 106 self._LCTRL_history.set_string_items() 107 108 self._LCTRL_inbox.set_string_items() 109 self._LCTRL_results.set_string_items() 110 self._LCTRL_documents.set_string_items()
111 #----------------------------------------------------- 112 # event handling 113 #----------------------------------------------------- 114 # remember to call 115 # self._schedule_data_reget() 116 # whenever you learn of data changes from database listener 117 # threads, dispatcher signals etc.
118 - def __register_interests(self):
119 # client internal signals 120 gmDispatcher.connect(signal = u'pre_patient_selection', receiver = self._on_pre_patient_selection) 121 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection) 122 123 # database change signals 124 gmDispatcher.connect(signal = u'dem.identity_mod_db', receiver = self._on_post_patient_selection) 125 gmDispatcher.connect(signal = u'dem.names_mod_db', receiver = self._on_post_patient_selection) 126 gmDispatcher.connect(signal = u'dem.comm_channel_mod_db', receiver = self._on_post_patient_selection) 127 gmDispatcher.connect(signal = u'dem.job_mod_db', receiver = self._on_post_patient_selection) 128 # no signal for external IDs yet 129 # no signal for address yet 130 #gmDispatcher.connect(signal = u'current_encounter_modified', receiver = self._on_current_encounter_modified) 131 #gmDispatcher.connect(signal = u'current_encounter_switched', receiver = self._on_current_encounter_switched) 132 133 gmDispatcher.connect(signal = u'clin.episode_mod_db', receiver = self._on_episode_issue_mod_db) 134 gmDispatcher.connect(signal = u'clin.health_issue_mod_db', receiver = self._on_episode_issue_mod_db) 135 136 gmDispatcher.connect(signal = u'clin.substance_intake_mod_db', receiver = self._on_post_patient_selection) 137 138 gmDispatcher.connect(signal = u'clin.hospital_stay_mod_db', receiver = self._on_post_patient_selection) 139 gmDispatcher.connect(signal = u'clin.family_history_mod_db', receiver = self._on_post_patient_selection) 140 gmDispatcher.connect(signal = u'clin.procedure_mod_db', receiver = self._on_post_patient_selection) 141 gmDispatcher.connect(signal = u'clin.vaccination_mod_db', receiver = self._on_post_patient_selection) 142 #gmDispatcher.connect(signal = u'gm_table_mod', receiver = self._on_post_patient_selection) 143 144 gmDispatcher.connect(signal = u'dem.message_inbox_mod_db', receiver = self._on_post_patient_selection) 145 gmDispatcher.connect(signal = u'clin.test_result_mod_db', receiver = self._on_post_patient_selection) 146 gmDispatcher.connect(signal = u'clin.reviewed_test_results_mod_db', receiver = self._on_post_patient_selection) 147 gmDispatcher.connect(signal = u'blobs.doc_med_mod_db', receiver = self._on_post_patient_selection) 148 149 # synchronous signals 150 # self.__pat.register_pre_selection_callback(callback = self._pre_selection_callback) 151 # gmDispatcher.send(signal = u'register_pre_exit_callback', callback = self._pre_exit_callback) 152 153 self._PRW_encounter_range.add_callback_on_selection(callback = self._on_encounter_range_selected)
154 #--------------------------------------------------------
155 - def _on_encounter_range_selected(self, data):
156 wx.CallAfter(self.__refresh_encounters, patient = gmPerson.gmCurrentPatient())
157 #--------------------------------------------------------
158 - def _on_pre_patient_selection(self):
159 # only empty out here, do NOT access the patient 160 # or else we will access the old patient while it 161 # may not be valid anymore ... 162 wx.CallAfter(self.__reset_ui_content)
163 #--------------------------------------------------------
164 - def _on_post_patient_selection(self):
165 wx.CallAfter(self._schedule_data_reget)
166 #--------------------------------------------------------
167 - def _on_episode_issue_mod_db(self):
168 wx.CallAfter(self._schedule_data_reget)
169 #----------------------------------------------------- 170 # reget-on-paint mixin API 171 #-----------------------------------------------------
172 - def _populate_with_data(self):
173 pat = gmPerson.gmCurrentPatient() 174 if not pat.connected: 175 self.__reset_ui_content() 176 return True 177 178 self.__refresh_identity(patient = pat) 179 self.__refresh_contacts(patient = pat) 180 self.__refresh_encounters(patient = pat) 181 182 self.__refresh_problems(patient = pat) 183 self.__refresh_meds(patient = pat) 184 self.__refresh_history(patient = pat) 185 186 self.__refresh_inbox(patient = pat) 187 self.__refresh_results(patient = pat) 188 self.__refresh_documents(patient = pat) 189 190 return True
191 #----------------------------------------------------- 192 # internal helpers 193 #-----------------------------------------------------
194 - def __refresh_results(self, patient=None):
195 list_items = [] 196 list_data = [] 197 198 emr = patient.get_emr() 199 most_recent = emr.get_most_recent_results(no_of_results = 1) 200 if most_recent is None: 201 self._LCTRL_results.set_string_items(items = []) 202 self._LCTRL_results.set_data(data = []) 203 return 204 205 list_items.append(_('Latest: %s ago (%s %s %s %s%s)') % ( 206 gmDateTime.format_interval_medically(gmDateTime.pydt_now_here() - most_recent['clin_when']), 207 most_recent['unified_abbrev'], 208 most_recent['unified_val'], 209 most_recent['val_unit'], 210 gmTools.coalesce(most_recent['abnormality_indicator'], u'', u' %s'), 211 gmTools.bool2subst(most_recent['reviewed'], u'', u' %s' % gmTools.u_writing_hand) 212 )) 213 list_data.append(most_recent) 214 most_recent_needs_red = False 215 #if most_recent['is_technically_abnormal'] is True: 216 if most_recent.is_considered_abnormal is True: 217 if most_recent['is_clinically_relevant']: 218 most_recent_needs_red = True 219 # else: 220 # if most_recent['abnormality_indicator'] not in [None, u'']: 221 # most_recent_needs_red = True 222 223 unsigned = emr.get_unsigned_results(order_by = u"(trim(coalesce(abnormality_indicator), '') <> '') DESC NULLS LAST, unified_abbrev") 224 no_of_reds = 0 225 for result in unsigned: 226 if result['pk_test_result'] == most_recent['pk_test_result']: 227 continue 228 if result['abnormality_indicator'] is not None: 229 if result['abnormality_indicator'].strip() != u'': 230 no_of_reds += 1 231 list_items.append(_('%s %s %s %s (%s ago, %s)') % ( 232 result['unified_abbrev'], 233 result['unified_val'], 234 result['val_unit'], 235 gmTools.coalesce(result['abnormality_indicator'], u'', u' %s'), 236 gmDateTime.format_interval_medically(gmDateTime.pydt_now_here() - result['clin_when']), 237 gmTools.u_writing_hand 238 )) 239 list_data.append(result) 240 241 self._LCTRL_results.set_string_items(items = list_items) 242 self._LCTRL_results.set_data(data = list_data) 243 244 if most_recent_needs_red: 245 self._LCTRL_results.SetItemTextColour(0, wx.NamedColour('RED')) 246 if no_of_reds > 0: 247 for idx in range(1, no_of_reds + 1): 248 self._LCTRL_results.SetItemTextColour(idx, wx.NamedColour('RED'))
249 #-----------------------------------------------------
250 - def _calc_results_list_item_tooltip(self, data):
251 return data.format()
252 #-----------------------------------------------------
253 - def _on_result_activated(self, event):
254 # data = self._LCTRL_inbox.get_selected_item_data(only_one = True) 255 # 256 # if data is not None: 257 # # <ctrl> down ? 258 # if wx.GetKeyState(wx.WXK_CONTROL): 259 # if isinstance(data, gmProviderInbox.cInboxMessage): 260 # xxxxxxxxx 261 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmMeasurementsGridPlugin') 262 return
263 #----------------------------------------------------- 264 #-----------------------------------------------------
265 - def __refresh_inbox(self, patient=None):
266 list_items = [] 267 list_data = [] 268 269 overdue_messages = patient.overdue_messages 270 no_of_overdues = len(overdue_messages) 271 for msg in overdue_messages: 272 list_items.append(_('overdue %s: %s') % ( 273 gmDateTime.format_interval_medically(msg['interval_due']), 274 gmTools.coalesce(msg['comment'], u'?') 275 )) 276 list_data.append(msg) 277 278 for msg in patient.get_messages(order_by = u'due_date NULLS LAST, importance DESC, received_when DESC'): 279 # already displayed above ? 280 if msg['is_overdue']: 281 continue 282 # not relevant anymore ? 283 if msg['is_expired']: 284 continue 285 if msg['due_date'] is None: 286 label = u'%s%s' % ( 287 msg['l10n_type'], 288 gmTools.coalesce(msg['comment'], u'', u': %s') 289 ) 290 else: 291 label = _('due in %s%s') % ( 292 gmDateTime.format_interval_medically(msg['interval_due']), 293 gmTools.coalesce(msg['comment'], u'', u': %s') 294 ) 295 296 list_items.append(label) 297 list_data.append(msg) 298 299 for hint in patient.dynamic_hints: 300 list_items.append(hint['title']) 301 list_data.append(hint) 302 303 self._LCTRL_inbox.set_string_items(items = list_items) 304 self._LCTRL_inbox.set_data(data = list_data) 305 306 if no_of_overdues > 0: 307 for idx in range(no_of_overdues): 308 self._LCTRL_inbox.SetItemTextColour(idx, wx.NamedColour('RED'))
309 #-----------------------------------------------------
310 - def _calc_inbox_item_tooltip(self, data):
311 if isinstance(data, gmProviderInbox.cInboxMessage): 312 return data.format() 313 314 if isinstance(data, gmProviderInbox.cDynamicHint): 315 return u'%s\n\n%s\n\n%s %s' % ( 316 data['title'], 317 gmTools.wrap(data['hint'], width = 50), 318 gmTools.wrap(gmTools.coalesce(data['url'], u'', u'%s\n\n'), width = 50), 319 data['source'] 320 ) 321 322 return None
323 #-----------------------------------------------------
324 - def _on_inbox_item_activated(self, event):
325 326 data = self._LCTRL_inbox.get_selected_item_data(only_one = True) 327 328 if isinstance(data, gmProviderInbox.cDynamicHint): 329 if data['url'] is not None: 330 gmNetworkTools.open_url_in_browser(data['url']) 331 return 332 333 # <ctrl> down ? 334 if not wx.GetKeyState(wx.WXK_CONTROL): 335 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmProviderInboxPlugin') 336 return 337 338 if data is None: 339 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmProviderInboxPlugin') 340 return 341 342 if not isinstance(data, gmProviderInbox.cInboxMessage): 343 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmProviderInboxPlugin') 344 return 345 346 delete_it = gmGuiHelpers.gm_show_question ( 347 question = _('Do you really want to\ndelete this inbox message ?'), 348 title = _('Deleting inbox message') 349 ) 350 if not delete_it: 351 return 352 353 gmProviderInbox.delete_inbox_message(inbox_message = data['pk_inbox_message']) 354 return
355 #----------------------------------------------------- 356 #-----------------------------------------------------
357 - def __refresh_documents(self, patient=None):
358 doc_folder = patient.get_document_folder() 359 360 list_items = [] 361 list_data = [] 362 363 docs = doc_folder.get_unsigned_documents() 364 no_of_unsigned = len(docs) 365 for doc in docs: 366 list_items.append(u'%s %s (%s)' % ( 367 gmDateTime.pydt_strftime(doc['clin_when'], format = '%m/%Y', accuracy = gmDateTime.acc_months), 368 doc['l10n_type'], 369 gmTools.u_writing_hand 370 )) 371 list_data.append(doc) 372 373 docs = doc_folder.get_documents(order_by = u'ORDER BY clin_when DESC', exclude_unsigned = True) 374 for doc in docs[:5]: 375 list_items.append(u'%s %s' % ( 376 gmDateTime.pydt_strftime(doc['clin_when'], format = '%m/%Y', accuracy = gmDateTime.acc_months), 377 doc['l10n_type'] 378 )) 379 list_data.append(doc) 380 if len(docs) > 5: 381 list_items.append(_('%s %s more not shown %s') % ( 382 gmTools.u_ellipsis, 383 len(docs) - 5, 384 gmTools.u_ellipsis 385 )) 386 list_data.append(u'') 387 388 self._LCTRL_documents.set_string_items(items = list_items) 389 self._LCTRL_documents.set_data(data = list_data) 390 391 if no_of_unsigned > 0: 392 for idx in range(no_of_unsigned): 393 self._LCTRL_documents.SetItemTextColour(idx, wx.NamedColour('RED'))
394 #-----------------------------------------------------
395 - def _calc_documents_list_item_tooltip(self, data):
396 emr = gmPerson.gmCurrentPatient().get_emr() 397 398 if isinstance(data, gmDocuments.cDocument): 399 return data.format() 400 401 return None
402 #-----------------------------------------------------
403 - def _on_document_activated(self, event):
404 data = self._LCTRL_documents.get_selected_item_data(only_one = True) 405 406 if data is not None: 407 # <ctrl> down ? 408 if wx.GetKeyState(wx.WXK_CONTROL): 409 if isinstance(data, gmDocuments.cDocument): 410 if len(data.parts) > 0: 411 gmDocumentWidgets.display_document_part(parent = self, part = data.parts[0]) 412 else: 413 gmDocumentWidgets.review_document(parent = self, document = data) 414 return 415 416 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs') 417 return
418 #----------------------------------------------------- 419 #-----------------------------------------------------
420 - def __refresh_encounters(self, patient=None):
421 422 cover_period = self._PRW_encounter_range.GetData() 423 if cover_period is None: 424 if self._PRW_encounter_range.GetValue().strip() != u'': 425 return 426 427 emr = patient.get_emr() 428 429 list_items = [] 430 list_data = [] 431 432 is_waiting = False 433 wlist = patient.get_waiting_list_entry() 434 if len(wlist) > 0: 435 is_waiting = True 436 list_items.append(_('Currently %s entries in waiting list') % len(wlist)) 437 tt = [] 438 for w in wlist: 439 tt.append(u'%s %s%s%s' % ( 440 gmTools.u_triangular_bullet, 441 gmDateTime.format_interval_medically(w['waiting_time']), 442 gmTools.coalesce(w['waiting_zone'], u'', u' in "%s"'), 443 gmTools.coalesce(w['comment'], u'', u': %s') 444 )) 445 if len(tt) > 0: 446 tt = u'\n'.join(tt) 447 else: 448 tt = None 449 list_data.append({'wlist': tt}) 450 451 first = emr.get_first_encounter() 452 if first is not None: 453 list_items.append ( 454 _('first: %s, %s') % ( 455 gmDateTime.pydt_strftime ( 456 first['started'], 457 format = '%Y %b %d', 458 accuracy = gmDateTime.acc_days 459 ), 460 first['l10n_type'] 461 ) 462 ) 463 list_data.append(first) 464 465 last = emr.get_last_but_one_encounter() 466 if last is not None: 467 list_items.append ( 468 _('last: %s, %s') % ( 469 gmDateTime.pydt_strftime ( 470 last['started'], 471 format = '%Y %b %d', 472 accuracy = gmDateTime.acc_days 473 ), 474 last['l10n_type'] 475 ) 476 ) 477 list_data.append(last) 478 479 if cover_period is not None: 480 item = _('Last %s:') % self._PRW_encounter_range.GetValue().strip() 481 list_items.append(item) 482 list_data.append(_('Statistics cover period')) 483 484 encs = emr.get_encounter_stats_by_type(cover_period = cover_period) 485 for enc in encs: 486 item = u' %s x %s' % (enc['frequency'], enc['l10n_type']) 487 list_items.append(item) 488 list_data.append(item) 489 490 stays = emr.get_hospital_stay_stats_by_hospital(cover_period = cover_period) 491 for stay in stays: 492 item = u' %s x %s' % ( 493 stay['frequency'], 494 stay['hospital'] 495 ) 496 list_items.append(item) 497 list_data.append({'stay': item}) 498 499 self._LCTRL_encounters.set_string_items(items = list_items) 500 self._LCTRL_encounters.set_data(data = list_data) 501 if is_waiting: 502 self._LCTRL_encounters.SetItemTextColour(0, wx.NamedColour('RED'))
503 #-----------------------------------------------------
504 - def _calc_encounters_list_item_tooltip(self, data):
505 emr = gmPerson.gmCurrentPatient().get_emr() 506 507 if isinstance(data, gmEMRStructItems.cEncounter): 508 return data.format ( 509 with_vaccinations = False, 510 with_tests = False, 511 with_docs = False, 512 with_co_encountlet_hints = True, 513 with_rfe_aoe = True 514 ) 515 516 if type(data) == type({}): 517 key, val = data.items()[0] 518 if key == 'wlist': 519 return val 520 if key == 'stay': 521 return None 522 523 return data
524 #-----------------------------------------------------
525 - def _on_encounter_activated(self, event):
526 data = self._LCTRL_encounters.get_selected_item_data(only_one = True) 527 if data is not None: 528 # <ctrl> down ? 529 if wx.GetKeyState(wx.WXK_CONTROL): 530 if isinstance(data, gmEMRStructItems.cEncounter): 531 gmEMRStructWidgets.edit_encounter(parent = self, encounter = data) 532 return 533 534 if type(data) == type({}): 535 key, val = data.items()[0] 536 if key == 'wlist': 537 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmWaitingListPlugin') 538 return 539 if key == 'stay': 540 wx.CallAfter(gmEMRStructWidgets.manage_hospital_stays, parent = self) 541 return 542 543 wx.CallAfter(gmEMRStructWidgets.manage_encounters, parent = self, ignore_OK_button = False)
544 #----------------------------------------------------- 545 #-----------------------------------------------------
546 - def __refresh_history(self, patient=None):
547 emr = patient.get_emr() 548 549 list_items = [] 550 list_data = [] 551 552 issues = [ 553 i for i in emr.get_health_issues() 554 if ((i['clinically_relevant'] is False) or (i['is_active'] is False)) 555 ] 556 for issue in issues: 557 last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue']) 558 if last_encounter is None: 559 last = issue['modified_when'].strftime('%m/%Y') 560 else: 561 last = last_encounter['last_affirmed'].strftime('%m/%Y') 562 list_items.append(u'%s %s' % (last, issue['description'])) 563 list_data.append(issue) 564 del issues 565 566 fhxs = emr.get_family_history() 567 for fhx in fhxs: 568 list_items.append(u'%s: %s%s' % ( 569 fhx['l10n_relation'], 570 fhx['condition'], 571 gmTools.coalesce(fhx['age_noted'], u'', u' (@ %s)') 572 )) 573 list_data.append(fhx) 574 del fhxs 575 576 stays = emr.get_hospital_stays() 577 for stay in stays: 578 if stay['discharge'] is not None: 579 discharge = u'' 580 else: 581 discharge = gmTools.u_ellipsis 582 list_items.append(u'%s%s %s: %s' % ( 583 gmDateTime.pydt_strftime(stay['admission'], format = '%Y %b %d'), 584 discharge, 585 stay['hospital'], 586 stay['episode'] 587 )) 588 list_data.append(stay) 589 del stays 590 591 procs = emr.get_performed_procedures() 592 for proc in procs: 593 list_items.append(u'%s%s %s' % ( 594 gmDateTime.pydt_strftime(proc['clin_when'], format = '%Y %b %d'), 595 gmTools.bool2subst(proc['is_ongoing'], gmTools.u_ellipsis, u'', u''), 596 proc['performed_procedure'] 597 )) 598 list_data.append(proc) 599 del procs 600 601 vaccs = emr.get_latest_vaccinations() 602 for ind, tmp in vaccs.items(): 603 tmp, vacc = tmp 604 list_items.append(_('%s Vacc: %s') % ( 605 gmDateTime.pydt_strftime(vacc['date_given'], format = '%Y %b %d'), 606 ind 607 )) 608 list_data.append(vacc) 609 del vaccs 610 611 self._LCTRL_history.set_string_items(items = list_items) 612 self._LCTRL_history.set_data(data = list_data)
613 #-----------------------------------------------------
614 - def _calc_history_list_item_tooltip(self, data):
615 616 if isinstance(data, gmEMRStructItems.cHealthIssue): 617 return data.format ( 618 patient = gmPerson.gmCurrentPatient(), 619 with_medications = False, 620 with_hospital_stays = False, 621 with_procedures = False, 622 with_family_history = False, 623 with_documents = False, 624 with_tests = False, 625 with_vaccinations = False 626 ).strip(u'\n') 627 628 if isinstance(data, gmFamilyHistory.cFamilyHistory): 629 return data.format(include_episode = True, include_comment = True) 630 631 if isinstance(data, gmEMRStructItems.cHospitalStay): 632 return data.format() 633 634 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 635 return data.format(include_episode = True) 636 637 if isinstance(data, gmVaccination.cVaccination): 638 return u'\n'.join(data.format ( 639 with_indications = True, 640 with_comment = True, 641 with_reaction = True, 642 date_format = '%Y %b %d' 643 )) 644 645 return None
646 #-----------------------------------------------------
647 - def _on_history_item_activated(self, event):
648 data = self._LCTRL_history.get_selected_item_data(only_one = True) 649 if data is None: 650 return 651 652 # <ctrl> down ? 653 if wx.GetKeyState(wx.WXK_CONTROL): 654 if isinstance(data, gmEMRStructItems.cHealthIssue): 655 gmEMRStructWidgets.edit_health_issue(parent = self, issue = data) 656 return 657 if isinstance(data, gmFamilyHistory.cFamilyHistory): 658 FamilyHistoryWidgets.edit_family_history(parent = self, family_history = data) 659 return 660 if isinstance(data, gmEMRStructItems.cHospitalStay): 661 gmEMRStructWidgets.edit_hospital_stay(parent = self, hospital_stay = data) 662 return 663 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 664 gmEMRStructWidgets.edit_procedure(parent = self, procedure = data) 665 return 666 if isinstance(data, gmVaccination.cVaccination): 667 gmVaccWidgets.edit_vaccination(parent = self, vaccination = data, single_entry = True) 668 return 669 return 670 671 if isinstance(data, gmEMRStructItems.cHealthIssue): 672 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmEMRBrowserPlugin') 673 return 674 if isinstance(data, gmFamilyHistory.cFamilyHistory): 675 FamilyHistoryWidgets.manage_family_history(parent = self) 676 return 677 if isinstance(data, gmEMRStructItems.cHospitalStay): 678 gmEMRStructWidgets.manage_hospital_stays(parent = self) 679 return 680 if isinstance(data, gmEMRStructItems.cPerformedProcedure): 681 gmEMRStructWidgets.manage_performed_procedures(parent = self) 682 return 683 if isinstance(data, gmVaccination.cVaccination): 684 gmVaccWidgets.manage_vaccinations(parent = self) 685 return 686 687 return
688 #----------------------------------------------------- 689 #-----------------------------------------------------
690 - def __refresh_meds(self, patient=None):
691 # list by brand or substance: 692 emr = patient.get_emr() 693 intakes = emr.get_current_substance_intakes(include_inactive = False, include_unapproved = True, order_by = u'substance') 694 695 list_items = [] 696 multi_brands_already_seen = [] 697 data_items = [] 698 for intake in intakes: 699 brand = intake.containing_drug 700 if brand is None or len(brand['pk_components']) == 1: 701 list_items.append(_('%s %s %s%s') % ( 702 intake['substance'], 703 intake['amount'], 704 intake['unit'], 705 gmTools.coalesce ( 706 intake['schedule'], 707 u'', 708 u': %s' 709 ) 710 )) 711 data_items.append(intake) 712 else: 713 if intake['brand'] in multi_brands_already_seen: 714 continue 715 multi_brands_already_seen.append(intake['brand']) 716 list_items.append(_('%s %s%s') % ( 717 intake['brand'], 718 brand['preparation'], 719 gmTools.coalesce ( 720 intake['schedule'], 721 u'', 722 u': %s' 723 ) 724 )) 725 data_items.append(intake) 726 self._LCTRL_meds.set_string_items(items = list_items) 727 self._LCTRL_meds.set_data(data = data_items)
728 #-----------------------------------------------------
729 - def _calc_meds_list_item_tooltip(self, data):
730 emr = gmPerson.gmCurrentPatient().get_emr() 731 atcs = [] 732 if data['atc_substance'] is not None: 733 atcs.append(data['atc_substance']) 734 # if data['atc_brand'] is not None: 735 # atcs.append(data['atc_brand']) 736 # allg = emr.is_allergic_to(atcs = tuple(atcs), inns = (data['substance'],), brand = data['brand']) 737 allg = emr.is_allergic_to(atcs = tuple(atcs), inns = (data['substance'],)) 738 if allg is False: 739 allg = None 740 return data.format(one_line = False, allergy = allg, show_all_brand_components = True)
741 #-----------------------------------------------------
742 - def _on_meds_item_activated(self, event):
743 data = self._LCTRL_meds.get_selected_item_data(only_one = True) 744 if data is not None: 745 # <ctrl> down ? 746 if wx.GetKeyState(wx.WXK_CONTROL): 747 wx.CallAfter(gmMedicationWidgets.edit_intake_of_substance, parent = self, substance = data) 748 return 749 750 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmCurrentSubstancesPlugin')
751 #----------------------------------------------------- 752 #-----------------------------------------------------
753 - def __refresh_contacts(self, patient=None):
754 emr = patient.get_emr() 755 756 list_items = [] 757 list_data = [] 758 is_in_hospital = False 759 760 stays = emr.get_hospital_stays(ongoing_only = True) 761 if len(stays) > 0: 762 list_items.append(_('** Currently hospitalized: %s **') % stays[0]['hospital']) 763 list_data.append(stays[0]) 764 is_in_hospital = True 765 766 adrs = patient.get_addresses() 767 for adr in adrs: 768 list_items.append(adr.format(single_line = True, verbose = False, show_type = True)) 769 list_data.append(adr) 770 771 comms = patient.get_comm_channels() 772 for comm in comms: 773 list_items.append(u'%s: %s%s' % ( 774 comm['l10n_comm_type'], 775 comm['url'], 776 gmTools.coalesce(comm['comment'], u'', u' (%s)') 777 )) 778 list_data.append(comm) 779 780 ident = patient.emergency_contact_in_database 781 if ident is not None: 782 list_items.append(_('emergency: %s') % ident['description_gender']) 783 list_data.append(ident) 784 785 if patient['emergency_contact'] is not None: 786 list_items.append(_('emergency: %s') % patient['emergency_contact'].split(u'\n')[0]) 787 list_data.append(patient['emergency_contact']) 788 789 provider = patient.primary_provider 790 if provider is not None: 791 list_items.append(_('in-praxis: %s') % provider.identity['description_gender']) 792 list_data.append(provider) 793 794 self._LCTRL_contacts.set_string_items(items = list_items) 795 self._LCTRL_contacts.set_data(data = list_data) 796 if is_in_hospital: 797 self._LCTRL_contacts.SetItemTextColour(0, wx.NamedColour('RED'))
798 #-----------------------------------------------------
799 - def _calc_contacts_list_item_tooltip(self, data):
800 801 if isinstance(data, gmEMRStructItems.cHospitalStay): 802 return data.format() 803 804 if isinstance(data, gmDemographicRecord.cPatientAddress): 805 return u'\n'.join(data.format()) 806 807 if isinstance(data, gmDemographicRecord.cCommChannel): 808 parts = [] 809 if data['is_confidential']: 810 parts.append(_('*** CONFIDENTIAL ***')) 811 if data['comment'] is not None: 812 parts.append(data['comment']) 813 return u'\n'.join(parts) 814 815 if isinstance(data, gmPerson.cIdentity): 816 return u'%s\n\n%s' % ( 817 data['description_gender'], 818 u'\n'.join([ 819 u'%s: %s%s' % ( 820 c['l10n_comm_type'], 821 c['url'], 822 gmTools.bool2subst(c['is_confidential'], _(' (confidential !)'), u'', u'') 823 ) 824 for c in data.get_comm_channels() 825 ]) 826 ) 827 828 if isinstance(data, basestring): 829 return data 830 831 if isinstance(data, gmStaff.cStaff): 832 ident = data.identity 833 return u'%s: %s\n\n%s%s' % ( 834 data['short_alias'], 835 ident['description_gender'], 836 u'\n'.join([ 837 u'%s: %s%s' % ( 838 c['l10n_comm_type'], 839 c['url'], 840 gmTools.bool2subst(c['is_confidential'], _(' (confidential !)'), u'', u'') 841 ) 842 for c in ident.get_comm_channels() 843 ]), 844 gmTools.coalesce(data['comment'], u'', u'\n\n%s') 845 ) 846 847 return None
848 #-----------------------------------------------------
849 - def _on_contacts_item_activated(self, event):
850 data = self._LCTRL_contacts.get_selected_item_data(only_one = True) 851 if data is not None: 852 # <ctrl> down ? 853 if wx.GetKeyState(wx.WXK_CONTROL): 854 if isinstance(data, gmEMRStructItems.cHospitalStay): 855 gmEMRStructWidgets.edit_hospital_stay(parent = self, hospital_stay = data) 856 return 857 if isinstance(data, gmDemographicRecord.cPatientAddress): 858 pass 859 if isinstance(data, gmDemographicRecord.cCommChannel): 860 gmContactWidgets.edit_comm_channel(parent = self, comm_channel = data, channel_owner = gmPerson.gmCurrentPatient()) 861 return 862 if isinstance(data, gmPerson.cIdentity): 863 pass 864 if isinstance(data, gmStaff.cStaff): 865 pass 866 867 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
868 #----------------------------------------------------- 869 #-----------------------------------------------------
870 - def __refresh_problems(self, patient=None):
871 emr = patient.get_emr() 872 873 problems = [ 874 p for p in emr.get_problems(include_closed_episodes = False, include_irrelevant_issues = False) 875 if p['problem_active'] 876 ] 877 878 list_items = [] 879 for problem in problems: 880 if problem['type'] == 'issue': 881 issue = emr.problem2issue(problem) 882 last_encounter = emr.get_last_encounter(issue_id = issue['pk_health_issue']) 883 if last_encounter is None: 884 last = issue['modified_when'].strftime('%m/%Y') 885 else: 886 last = last_encounter['last_affirmed'].strftime('%m/%Y') 887 list_items.append(u'%s: %s' % (problem['problem'], last)) 888 889 elif problem['type'] == 'episode': 890 epi = emr.problem2episode(problem) 891 last_encounter = emr.get_last_encounter(episode_id = epi['pk_episode']) 892 if last_encounter is None: 893 last = epi['episode_modified_when'].strftime('%m/%Y') 894 else: 895 last = last_encounter['last_affirmed'].strftime('%m/%Y') 896 list_items.append(u'%s: %s' % (problem['problem'], last)) 897 898 self._LCTRL_problems.set_string_items(items = list_items) 899 self._LCTRL_problems.set_data(data = problems)
900 #-----------------------------------------------------
901 - def _calc_problem_list_item_tooltip(self, data):
902 emr = gmPerson.gmCurrentPatient().get_emr() 903 904 if data['type'] == 'issue': 905 issue = emr.problem2issue(data) 906 tt = issue.format ( 907 patient = gmPerson.gmCurrentPatient(), 908 with_medications = False, 909 with_hospital_stays = False, 910 with_procedures = False, 911 with_family_history = False, 912 with_documents = False, 913 with_tests = False, 914 with_vaccinations = False 915 ).strip(u'\n') 916 return tt 917 918 if data['type'] == 'episode': 919 epi = emr.problem2episode(data) 920 tt = epi.format ( 921 patient = gmPerson.gmCurrentPatient(), 922 with_encounters = False, 923 with_hospital_stays = False, 924 with_procedures = False, 925 with_family_history = False, 926 with_documents = False, 927 with_tests = False, 928 with_vaccinations = False, 929 with_health_issue = True 930 ).strip(u'\n') 931 return tt 932 933 return None
934 #-----------------------------------------------------
935 - def _on_problem_activated(self, event):
936 data = self._LCTRL_problems.get_selected_item_data(only_one = True) 937 if data is not None: 938 # <ctrl> down ? 939 if wx.GetKeyState(wx.WXK_CONTROL): 940 emr = gmPerson.gmCurrentPatient().get_emr() 941 if data['type'] == 'issue': 942 gmEMRStructWidgets.edit_health_issue(parent = self, issue = emr.problem2issue(data)) 943 return 944 if data['type'] == 'episode': 945 gmEMRStructWidgets.edit_episode(parent = self, episode = emr.problem2episode(data)) 946 return 947 948 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmEMRBrowserPlugin')
949 #----------------------------------------------------- 950 #-----------------------------------------------------
951 - def __refresh_identity(self, patient=None):
952 # names (.comment -> tooltip) 953 names = patient.get_names(exclude_active = True) 954 items = [ 955 _('aka: %(last)s, %(first)s%(nick)s') % { 956 'last': n['lastnames'], 957 'first': n['firstnames'], 958 'nick': gmTools.coalesce(n['preferred'], u'', u" '%s'") 959 } for n in names 960 ] 961 data = names 962 963 # IDs (.issuer & .comment -> tooltip) 964 ids = patient.external_ids 965 for i in ids: 966 items.append(u'%s: %s' % (i['name'], i['value'])) 967 data.append({'id': i}) 968 969 # occupation 970 jobs = patient.get_occupations() 971 for j in jobs: 972 items.append(_('job: %s (%s)') % ( 973 j['l10n_occupation'], 974 j['modified_when'].strftime('%m/%Y') 975 )) 976 data.append({'job': j}) 977 978 self._LCTRL_identity.set_string_items(items = items) 979 self._LCTRL_identity.set_data(data = data)
980 #-----------------------------------------------------
981 - def _calc_identity_item_tooltip(self, data):
982 if isinstance(data, gmPerson.cPersonName): 983 return data['comment'] 984 if isinstance(data, type({})): 985 key = data.keys()[0] 986 val = data[key] 987 if key == 'id': 988 return _('issued by: %s%s') % ( 989 val['issuer'], 990 gmTools.coalesce(val['comment'], u'', u'\n\n%s') 991 ) 992 if key == 'job': 993 tt = _('Last modified: %s') % val['modified_when'].strftime('%m/%Y') 994 if val['activities'] is None: 995 return tt 996 return tt + (u'\n\n' + _('Activities:\n\n%s') % val['activities']) 997 998 return None
999 #-----------------------------------------------------
1000 - def _on_identity_item_activated(self, event):
1001 data = self._LCTRL_identity.get_selected_item_data(only_one = True) 1002 if data is not None: 1003 # <ctrl> down ? 1004 if wx.GetKeyState(wx.WXK_CONTROL): 1005 if isinstance(data, gmPerson.cPersonName): 1006 ea = gmDemographicsWidgets.cPersonNameEAPnl(self, -1, name = data) 1007 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True) 1008 dlg.SetTitle(_('Cloning name')) 1009 dlg.ShowModal() 1010 return 1011 if isinstance(data, type({})): 1012 key = data.keys()[0] 1013 val = data[key] 1014 if key == 'id': 1015 ea = gmDemographicsWidgets.cExternalIDEditAreaPnl(self, -1, external_id = val) 1016 ea.identity = gmPerson.gmCurrentPatient() 1017 dlg = gmEditArea.cGenericEditAreaDlg2(self, -1, edit_area = ea, single_entry = True) 1018 dlg.SetTitle(_('Editing external ID')) 1019 dlg.ShowModal() 1020 return 1021 if key == 'job': 1022 gmDemographicsWidgets.edit_occupation() 1023 return 1024 1025 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmNotebookedPatientEditionPlugin')
1026 #============================================================ 1027 # main 1028 #------------------------------------------------------------ 1029 if __name__ == "__main__": 1030 1031 if len(sys.argv) < 2: 1032 sys.exit() 1033 1034 if sys.argv[1] != u'test': 1035 sys.exit() 1036 1037 # from Gnumed.pycommon import gmPG2 1038 # from Gnumed.pycommon import gmI18N 1039 # gmI18N.activate_locale() 1040 # gmI18N.install_domain() 1041 1042 #-------------------------------------------------------- 1043 #test_org_unit_prw() 1044