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