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

Source Code for Module Gnumed.wxpython.gmNarrativeWorkflows

  1  """GNUmed narrative workflows.""" 
  2  #================================================================ 
  3  __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>" 
  4  __license__ = "GPL v2 or later (details at http://www.gnu.org)" 
  5   
  6  import sys 
  7  import logging 
  8  import os.path 
  9  import time 
 10   
 11   
 12  import wx 
 13   
 14   
 15  if __name__ == '__main__': 
 16          sys.path.insert(0, '../../') 
 17   
 18  from Gnumed.pycommon import gmI18N 
 19   
 20  if __name__ == '__main__': 
 21          gmI18N.activate_locale() 
 22          gmI18N.install_domain() 
 23   
 24  from Gnumed.pycommon import gmDispatcher 
 25  from Gnumed.pycommon import gmTools 
 26  from Gnumed.pycommon import gmDateTime 
 27   
 28  from Gnumed.business import gmPerson 
 29  from Gnumed.business import gmStaff 
 30  from Gnumed.business import gmEMRStructItems 
 31  from Gnumed.business import gmClinNarrative 
 32  from Gnumed.business import gmSoapDefs 
 33  from Gnumed.business import gmProviderInbox 
 34   
 35  from Gnumed.wxpython import gmListWidgets 
 36  from Gnumed.wxpython import gmEMRStructWidgets 
 37  from Gnumed.wxpython import gmEncounterWidgets 
 38  from Gnumed.wxpython import gmGuiHelpers 
 39  from Gnumed.wxpython import gmNarrativeWidgets 
 40  from Gnumed.wxpython.gmPatSearchWidgets import set_active_patient 
 41   
 42  from Gnumed.exporters import gmPatientExporter 
 43   
 44   
 45  _log = logging.getLogger('gm.ui') 
 46   
 47  #============================================================ 
 48  # narrative related widgets/functions 
 49  #------------------------------------------------------------ 
50 -def edit_narrative(parent=None, narrative=None, single_entry=False):
51 assert isinstance(narrative, gmClinNarrative.cNarrative), '<narrative> must be of type <cNarrative>' 52 53 title = _('Editing progress note') 54 if narrative['modified_by_raw'] == gmStaff.gmCurrentProvider()['db_user']: 55 msg = _('Your original progress note:') 56 else: 57 msg = _('Original progress note by %s [%s]\n(will be notified of changes):') % ( 58 narrative['modified_by'], 59 narrative['modified_by_raw'] 60 ) 61 if parent is None: 62 parent = wx.GetApp().GetTopWindow() 63 dlg = gmGuiHelpers.cMultilineTextEntryDlg ( 64 parent, 65 -1, 66 title = title, 67 msg = msg, 68 data = narrative.format(left_margin = ' ', fancy = True), 69 text = narrative['narrative'].strip() 70 ) 71 decision = dlg.ShowModal() 72 val = dlg.value.strip() 73 dlg.DestroyLater() 74 if decision != wx.ID_SAVE: 75 return False 76 77 if val == '': 78 return False 79 80 if val == narrative['narrative'].strip(): 81 return False 82 83 if narrative['modified_by_raw'] == gmStaff.gmCurrentProvider()['db_user']: 84 narrative['narrative'] = val 85 narrative.save_payload() 86 return True 87 88 q = _( 89 'Original progress note written by someone else:\n' 90 '\n' 91 ' %s (%s)\n' 92 '\n' 93 'Upon saving changes that person will be notified.\n' 94 '\n' 95 'Consider saving as a new progress note instead.' 96 ) % ( 97 narrative['modified_by_raw'], 98 narrative['modified_by'] 99 ) 100 buttons = [ 101 {'label': _('Save changes'), 'default': True}, 102 {'label': _('Save new note')}, 103 {'label': _('Discard')} 104 ] 105 dlg = gmGuiHelpers.c3ButtonQuestionDlg(parent = parent, caption = title, question = q, button_defs = buttons) 106 decision = dlg.ShowModal() 107 dlg.DestroyLater() 108 if decision not in [wx.ID_YES, wx.ID_NO]: 109 return False 110 111 if decision == wx.ID_NO: 112 # create new progress note within the same context as the original one 113 gmClinNarrative.create_narrative_item ( 114 narrative = val, 115 soap_cat = narrative['soap_cat'], 116 episode_id = narrative['pk_episode'], 117 encounter_id = narrative['pk_encounter'] 118 ) 119 return True 120 121 # notify original provider 122 msg = gmProviderInbox.create_inbox_message ( 123 staff = narrative.staff_id, 124 message_type = _('Change notification'), 125 message_category = 'administrative', 126 subject = _('A progress note of yours has been edited.'), 127 patient = narrative['pk_patient'] 128 ) 129 msg['data'] = _( 130 'Original (by [%s]):\n' 131 '%s\n' 132 '\n' 133 'Edited (by [%s]):\n' 134 '%s' 135 ) % ( 136 narrative['modified_by'], 137 narrative['narrative'].strip(), 138 gmStaff.gmCurrentProvider()['short_alias'], 139 val 140 ) 141 msg.save() 142 # notify /me about the staff member notification 143 #gmProviderInbox.create_inbox_message ( 144 # staff = curr_prov['pk_staff'], 145 # message_type = _('Privacy notice'), 146 # message_category = 'administrative', 147 # subject = _('%s: Staff member %s has been notified of your chart access.') % (prov, pat) 148 #) 149 # save narrative change 150 narrative['narrative'] = val 151 narrative.save() 152 return True
153 154 #------------------------------------------------------------
155 -def move_progress_notes_to_another_encounter(parent=None, encounters=None, episodes=None, patient=None, move_all=False):
156 157 # sanity checks 158 if patient is None: 159 patient = gmPerson.gmCurrentPatient() 160 161 if not patient.connected: 162 gmDispatcher.send(signal = 'statustext', msg = _('Cannot move progress notes. No active patient.')) 163 return False 164 165 if parent is None: 166 parent = wx.GetApp().GetTopWindow() 167 168 emr = patient.emr 169 170 if encounters is None: 171 all_encs_in_epi = emr.get_encounters(episodes = episodes, skip_empty = True) 172 # nothing to do ? 173 if len(all_encs_in_epi) == 0: 174 return True 175 encounters = gmEncounterWidgets.select_encounters ( 176 parent = parent, 177 patient = patient, 178 single_selection = False, 179 encounters = all_encs_in_epi 180 ) 181 # cancelled 182 if encounters is None: 183 return True 184 # none selected 185 if len(encounters) == 0: 186 return True 187 188 notes = emr.get_clin_narrative ( 189 encounters = encounters, 190 episodes = episodes 191 ) 192 193 # which narrative 194 if move_all: 195 selected_narr = notes 196 else: 197 selected_narr = gmListWidgets.get_choices_from_list ( 198 parent = parent, 199 caption = _('Moving progress notes between encounters ...'), 200 single_selection = False, 201 can_return_empty = True, 202 data = notes, 203 msg = _('\n Select the progress notes to move from the list !\n\n'), 204 columns = [_('when'), _('who'), _('type'), _('entry')], 205 choices = [ 206 [ narr['date'].strftime('%x %H:%M'), 207 narr['modified_by'], 208 gmSoapDefs.soap_cat2l10n[narr['soap_cat']], 209 narr['narrative'].replace('\n', '/').replace('\r', '/') 210 ] for narr in notes 211 ] 212 ) 213 214 if not selected_narr: 215 return True 216 217 # which encounter to move to 218 enc2move2 = gmEncounterWidgets.select_encounters ( 219 parent = parent, 220 patient = patient, 221 single_selection = True 222 ) 223 224 if not enc2move2: 225 return True 226 227 for narr in selected_narr: 228 narr['pk_encounter'] = enc2move2['pk_encounter'] 229 narr.save() 230 231 return True
232 233 #------------------------------------------------------------
234 -def manage_progress_notes(parent=None, encounters=None, episodes=None, patient=None):
235 236 # sanity checks 237 if patient is None: 238 patient = gmPerson.gmCurrentPatient() 239 240 if not patient.connected: 241 gmDispatcher.send(signal = 'statustext', msg = _('Cannot edit progress notes. No active patient.')) 242 return False 243 244 if parent is None: 245 parent = wx.GetApp().GetTopWindow() 246 247 emr = patient.emr 248 #-------------------------- 249 def delete(item): 250 if item is None: 251 return False 252 dlg = gmGuiHelpers.c2ButtonQuestionDlg ( 253 parent, 254 -1, 255 caption = _('Deleting progress note'), 256 question = _( 257 'Are you positively sure you want to delete this\n' 258 'progress note from the medical record ?\n' 259 '\n' 260 'Note that even if you chose to delete the entry it will\n' 261 'still be (invisibly) kept in the audit trail to protect\n' 262 'you from litigation because physical deletion is known\n' 263 'to be unlawful in some jurisdictions.\n' 264 ), 265 button_defs = ( 266 {'label': _('Delete'), 'tooltip': _('Yes, delete the progress note.'), 'default': False}, 267 {'label': _('Cancel'), 'tooltip': _('No, do NOT delete the progress note.'), 'default': True} 268 ) 269 ) 270 decision = dlg.ShowModal() 271 272 if decision != wx.ID_YES: 273 return False 274 275 gmClinNarrative.delete_clin_narrative(narrative = item['pk_narrative']) 276 return True
277 #-------------------------- 278 def edit(item): 279 if item is None: 280 return False 281 282 dlg = gmGuiHelpers.cMultilineTextEntryDlg ( 283 parent, 284 -1, 285 title = _('Editing progress note'), 286 msg = _('This is the original progress note:'), 287 data = item.format(left_margin = ' ', fancy = True), 288 text = item['narrative'] 289 ) 290 decision = dlg.ShowModal() 291 292 if decision != wx.ID_SAVE: 293 return False 294 295 val = dlg.value 296 dlg.DestroyLater() 297 if val.strip() == '': 298 return False 299 300 item['narrative'] = val 301 item.save_payload() 302 return True 303 304 #-------------------------- 305 def refresh(lctrl): 306 notes = emr.get_clin_narrative ( 307 encounters = encounters, 308 episodes = episodes, 309 providers = [ gmStaff.gmCurrentProvider()['short_alias'] ] 310 ) 311 lctrl.set_string_items(items = [ 312 [ narr['date'].strftime('%x %H:%M'), 313 gmSoapDefs.soap_cat2l10n[narr['soap_cat']], 314 narr['narrative'].replace('\n', '/').replace('\r', '/') 315 ] for narr in notes 316 ]) 317 lctrl.set_data(data = notes) 318 #-------------------------- 319 320 gmListWidgets.get_choices_from_list ( 321 parent = parent, 322 caption = _('Managing progress notes'), 323 msg = _( 324 '\n' 325 ' This list shows the progress notes by %s.\n' 326 '\n' 327 ) % gmStaff.gmCurrentProvider()['short_alias'], 328 columns = [_('when'), _('type'), _('entry')], 329 single_selection = True, 330 can_return_empty = False, 331 edit_callback = edit, 332 delete_callback = delete, 333 refresh_callback = refresh 334 ) 335 336 #------------------------------------------------------------
337 -def search_narrative_across_emrs(parent=None):
338 339 if parent is None: 340 parent = wx.GetApp().GetTopWindow() 341 342 search_term_dlg = wx.TextEntryDialog ( 343 parent, 344 _('Enter (regex) term to search for across all EMRs:'), 345 caption = _('Text search across all EMRs'), 346 style = wx.OK | wx.CANCEL | wx.CENTRE 347 ) 348 result = search_term_dlg.ShowModal() 349 350 if result != wx.ID_OK: 351 return 352 353 wx.BeginBusyCursor() 354 search_term = search_term_dlg.GetValue() 355 search_term_dlg.DestroyLater() 356 results = gmClinNarrative.search_text_across_emrs(search_term = search_term) 357 wx.EndBusyCursor() 358 359 if len(results) == 0: 360 gmGuiHelpers.gm_show_info ( 361 _( 362 'Nothing found for search term:\n' 363 ' "%s"' 364 ) % search_term, 365 _('Search results') 366 ) 367 return 368 369 items = [ [ 370 gmPerson.cPerson(aPK_obj = r['pk_patient'])['description_gender'], 371 r['narrative'], 372 r['src_table'] 373 ] for r in results ] 374 375 selected_patient = gmListWidgets.get_choices_from_list ( 376 parent = parent, 377 caption = _('Search results for [%s]') % search_term, 378 choices = items, 379 columns = [_('Patient'), _('Match'), _('Match location')], 380 data = [ r['pk_patient'] for r in results ], 381 single_selection = True, 382 can_return_empty = False 383 ) 384 385 if selected_patient is None: 386 return 387 388 wx.CallAfter(set_active_patient, patient = gmPerson.cPerson(aPK_obj = selected_patient))
389 390 #------------------------------------------------------------
391 -def search_narrative_in_emr(parent=None, patient=None):
392 393 # sanity checks 394 if patient is None: 395 patient = gmPerson.gmCurrentPatient() 396 397 if not patient.connected: 398 gmDispatcher.send(signal = 'statustext', msg = _('Cannot search EMR. No active patient.')) 399 return False 400 401 if parent is None: 402 parent = wx.GetApp().GetTopWindow() 403 404 search_term_dlg = wx.TextEntryDialog ( 405 parent, 406 _('Enter search term:'), 407 caption = _('Text search of entire EMR of active patient'), 408 style = wx.OK | wx.CANCEL | wx.CENTRE 409 ) 410 result = search_term_dlg.ShowModal() 411 412 if result != wx.ID_OK: 413 search_term_dlg.DestroyLater() 414 return False 415 416 wx.BeginBusyCursor() 417 val = search_term_dlg.GetValue() 418 search_term_dlg.DestroyLater() 419 emr = patient.emr 420 rows = emr.search_narrative_simple(val) 421 wx.EndBusyCursor() 422 423 if len(rows) == 0: 424 gmGuiHelpers.gm_show_info ( 425 _( 426 'Nothing found for search term:\n' 427 ' "%s"' 428 ) % val, 429 _('Search results') 430 ) 431 return True 432 433 txt = '' 434 for row in rows: 435 txt += '%s: %s\n' % ( 436 row['soap_cat'], 437 row['narrative'] 438 ) 439 440 txt += ' %s: %s - %s %s\n' % ( 441 _('Encounter'), 442 row['encounter_started'].strftime('%x %H:%M'), 443 row['encounter_ended'].strftime('%H:%M'), 444 row['encounter_type'] 445 ) 446 txt += ' %s: %s\n' % ( 447 _('Episode'), 448 row['episode'] 449 ) 450 txt += ' %s: %s\n\n' % ( 451 _('Health issue'), 452 row['health_issue'] 453 ) 454 455 msg = _( 456 'Search term was: "%s"\n' 457 '\n' 458 'Search results:\n\n' 459 '%s\n' 460 ) % (val, txt) 461 462 dlg = wx.MessageDialog ( 463 parent = parent, 464 message = msg, 465 caption = _('Search results for [%s]') % val, 466 style = wx.OK | wx.STAY_ON_TOP 467 ) 468 dlg.ShowModal() 469 dlg.DestroyLater() 470 471 return True
472 473 #------------------------------------------------------------
474 -def export_narrative_for_medistar_import(parent=None, soap_cats='soapu', encounter=None):
475 476 # sanity checks 477 pat = gmPerson.gmCurrentPatient() 478 if not pat.connected: 479 gmDispatcher.send(signal = 'statustext', msg = _('Cannot export EMR for Medistar. No active patient.')) 480 return False 481 482 if encounter is None: 483 encounter = pat.emr.active_encounter 484 485 if parent is None: 486 parent = wx.GetApp().GetTopWindow() 487 488 # get file name 489 aWildcard = "%s (*.txt)|*.txt|%s (*)|*" % (_("text files"), _("all files")) 490 # FIXME: make configurable 491 aDefDir = os.path.abspath(os.path.expanduser(os.path.join('~', 'gnumed'))) 492 # FIXME: make configurable 493 fname = '%s-%s-%s-%s-%s.txt' % ( 494 'Medistar-MD', 495 time.strftime('%Y-%m-%d',time.localtime()), 496 pat['lastnames'].replace(' ', '-'), 497 pat['firstnames'].replace(' ', '_'), 498 pat.get_formatted_dob(format = '%Y-%m-%d') 499 ) 500 dlg = wx.FileDialog ( 501 parent = parent, 502 message = _("Save EMR extract for MEDISTAR import as..."), 503 defaultDir = aDefDir, 504 defaultFile = fname, 505 wildcard = aWildcard, 506 style = wx.FD_SAVE 507 ) 508 choice = dlg.ShowModal() 509 fname = dlg.GetPath() 510 dlg.DestroyLater() 511 if choice != wx.ID_OK: 512 return False 513 514 wx.BeginBusyCursor() 515 _log.debug('exporting encounter for medistar import to [%s]', fname) 516 exporter = gmPatientExporter.cMedistarSOAPExporter(patient = pat) 517 successful, fname = exporter.save_to_file ( 518 filename = fname, 519 encounter = encounter, 520 soap_cats = 'soapu', 521 export_to_import_file = True 522 ) 523 if not successful: 524 gmGuiHelpers.gm_show_error ( 525 _('Error exporting progress notes for MEDISTAR import.'), 526 _('MEDISTAR progress notes export') 527 ) 528 wx.EndBusyCursor() 529 return False 530 531 gmDispatcher.send(signal = 'statustext', msg = _('Successfully exported progress notes into file [%s] for Medistar import.') % fname, beep=False) 532 533 wx.EndBusyCursor() 534 return True
535 536 #------------------------------------------------------------
537 -def select_narrative(parent=None, soap_cats=None, msg=None):
538 539 pat = gmPerson.gmCurrentPatient() 540 emr = pat.emr 541 542 if parent is None: 543 parent = wx.GetApp().GetTopWindow() 544 545 if soap_cats is None: 546 soap_cats = 'soapu' 547 soap_cats = list(soap_cats) 548 i18n_soap_cats = [ gmSoapDefs.soap_cat2l10n[cat].upper() for cat in soap_cats ] 549 550 if msg is None: 551 msg = _('Pick the [%s] narrative you want to use.') % '/'.join(i18n_soap_cats) 552 553 #----------------------------------------------- 554 def get_tooltip(soap): 555 return soap.format(fancy = True, width = 60)
556 #----------------------------------------------- 557 def refresh(lctrl): 558 lctrl.secondary_sort_column = 0 559 soap = emr.get_clin_narrative(soap_cats = soap_cats) 560 lctrl.set_string_items ([ [ 561 gmDateTime.pydt_strftime(s['date'], '%Y %m %d'), 562 s['modified_by'], 563 gmSoapDefs.soap_cat2l10n[s['soap_cat']], 564 s['narrative'], 565 s['episode'], 566 s['health_issue'] 567 ] for s in soap ]) 568 lctrl.set_data(soap) 569 #----------------------------------------------- 570 return gmListWidgets.get_choices_from_list ( 571 parent = parent, 572 msg = msg, 573 caption = _('Picking [%s] narrative') % ('/'.join(i18n_soap_cats)), 574 columns = [_('When'), _('Who'), _('Type'), _('Entry'), _('Episode'), _('Issue')], 575 single_selection = False, 576 can_return_empty = False, 577 refresh_callback = refresh, 578 list_tooltip_callback = get_tooltip 579 ) 580 581 #------------------------------------------------------------
582 -def select_narrative_by_issue(parent=None, soap_cats=None):
583 584 pat = gmPerson.gmCurrentPatient() 585 emr = pat.emr 586 587 # not useful if you think about it: 588 # issues = [ i for i in emr.health_issues ] 589 # if len(issues) == 0: 590 # gmDispatcher.send(signal = 'statustext', msg = _('No progress notes found.')) 591 # return [] 592 593 if parent is None: 594 parent = wx.GetApp().GetTopWindow() 595 596 if soap_cats is None: 597 soap_cats = 'soapu' 598 soap_cats = list(soap_cats) 599 i18n_soap_cats = [ gmSoapDefs.soap_cat2l10n[cat].upper() for cat in soap_cats ] 600 601 selected_soap = {} 602 #selected_narrative_pks = [] 603 604 #----------------------------------------------- 605 def get_soap_tooltip(soap): 606 return soap.format(fancy = True, width = 60)
607 #----------------------------------------------- 608 def pick_soap_from_issue(issue): 609 610 if issue is None: 611 return False 612 613 narr_for_issue = emr.get_clin_narrative(issues = [issue['pk_health_issue']], soap_cats = soap_cats) 614 615 if len(narr_for_issue) == 0: 616 gmDispatcher.send(signal = 'statustext', msg = _('No narrative available for this health issue.')) 617 return True 618 619 selected_narr = gmListWidgets.get_choices_from_list ( 620 parent = parent, 621 msg = _('Pick the [%s] narrative you want to include in the report.') % '/'.join(i18n_soap_cats), 622 caption = _('Picking [%s] from %s%s%s') % ( 623 '/'.join(i18n_soap_cats), 624 gmTools.u_left_double_angle_quote, 625 issue['description'], 626 gmTools.u_right_double_angle_quote 627 ), 628 columns = [_('When'), _('Who'), _('Type'), _('Entry')], 629 choices = [ [ 630 gmDateTime.pydt_strftime(narr['date'], '%Y %b %d %H:%M', accuracy = gmDateTime.acc_minutes), 631 narr['modified_by'], 632 gmSoapDefs.soap_cat2l10n[narr['soap_cat']], 633 narr['narrative'].replace('\n', '//').replace('\r', '//') 634 ] for narr in narr_for_issue ], 635 data = narr_for_issue, 636 #selections=None, 637 #edit_callback=None, 638 single_selection = False, 639 can_return_empty = False, 640 list_tooltip_callback = get_soap_tooltip 641 ) 642 643 if selected_narr is None: 644 return True 645 646 for narr in selected_narr: 647 selected_soap[narr['pk_narrative']] = narr 648 649 return True 650 #----------------------------------------------- 651 def edit_issue(issue): 652 return gmEMRStructWidgets.edit_health_issue(parent = parent, issue = issue) 653 #----------------------------------------------- 654 def refresh_issues(lctrl): 655 #issues = [ i for i in emr.health_issues ] 656 issues = emr.health_issues 657 lctrl.set_string_items ([ [ 658 gmTools.bool2subst(i['is_confidential'], _('!! CONFIDENTIAL !!'), ''), 659 i['description'], 660 gmTools.bool2subst(i['is_active'], _('active'), _('inactive')) 661 ] for i in issues 662 ]) 663 lctrl.set_data(issues) 664 #----------------------------------------------- 665 def get_issue_tooltip(issue): 666 return issue.format ( 667 patient = pat, 668 with_encounters = False, 669 with_medications = False, 670 with_hospital_stays = False, 671 with_procedures = False, 672 with_family_history = False, 673 with_documents = False, 674 with_tests = False, 675 with_vaccinations = False 676 ) 677 #----------------------------------------------- 678 #selected_episode_pks = [] 679 680 issues_picked_from = gmListWidgets.get_choices_from_list ( 681 parent = parent, 682 msg = _('\n Select the issue you want to report on.'), 683 caption = _('Picking [%s] from health issues') % '/'.join(i18n_soap_cats), 684 columns = [_('Privacy'), _('Issue'), _('Status')], 685 edit_callback = edit_issue, 686 refresh_callback = refresh_issues, 687 single_selection = True, 688 can_return_empty = True, 689 ignore_OK_button = False, 690 left_extra_button = ( 691 _('&Pick notes'), 692 _('Pick [%s] entries from selected health issue') % '/'.join(i18n_soap_cats), 693 pick_soap_from_issue 694 ), 695 list_tooltip_callback = get_issue_tooltip 696 ) 697 698 if issues_picked_from is None: 699 return [] 700 701 return selected_soap.values() 702 703 # selection_idxs = [] 704 # for idx in range(len(all_epis)): 705 # if all_epis[idx]['pk_episode'] in selected_episode_pks: 706 # selection_idxs.append(idx) 707 # if len(selection_idxs) != 0: 708 # dlg.set_selections(selections = selection_idxs) 709 710 #------------------------------------------------------------
711 -def select_narrative_by_episode(parent=None, soap_cats=None):
712 713 pat = gmPerson.gmCurrentPatient() 714 emr = pat.emr 715 716 all_epis = [ epi for epi in emr.get_episodes(order_by = 'description') if epi.has_narrative ] 717 if len(all_epis) == 0: 718 gmDispatcher.send(signal = 'statustext', msg = _('No episodes with progress notes found.')) 719 return [] 720 721 if parent is None: 722 parent = wx.GetApp().GetTopWindow() 723 724 if soap_cats is None: 725 soap_cats = 'soapu' 726 soap_cats = list(soap_cats) 727 i18n_soap_cats = [ gmSoapDefs.soap_cat2l10n[cat].upper() for cat in soap_cats ] 728 729 selected_soap = {} 730 #selected_narrative_pks = [] 731 732 #----------------------------------------------- 733 def get_soap_tooltip(soap): 734 return soap.format(fancy = True, width = 60)
735 #----------------------------------------------- 736 def pick_soap_from_episode(episode): 737 738 if episode is None: 739 return False 740 741 narr_for_epi = emr.get_clin_narrative(episodes = [episode['pk_episode']], soap_cats = soap_cats) 742 743 if len(narr_for_epi) == 0: 744 gmDispatcher.send(signal = 'statustext', msg = _('No narrative available for selected episode.')) 745 return True 746 747 selected_narr = gmListWidgets.get_choices_from_list ( 748 parent = parent, 749 msg = _('Pick the [%s] narrative you want to include in the report.') % '/'.join(i18n_soap_cats), 750 caption = _('Picking [%s] from %s%s%s') % ( 751 '/'.join(i18n_soap_cats), 752 gmTools.u_left_double_angle_quote, 753 episode['description'], 754 gmTools.u_right_double_angle_quote 755 ), 756 columns = [_('When'), _('Who'), _('Type'), _('Entry')], 757 choices = [ [ 758 gmDateTime.pydt_strftime(narr['date'], '%Y %b %d %H:%M', accuracy = gmDateTime.acc_minutes), 759 narr['modified_by'], 760 gmSoapDefs.soap_cat2l10n[narr['soap_cat']], 761 narr['narrative'].replace('\n', '//').replace('\r', '//') 762 ] for narr in narr_for_epi ], 763 data = narr_for_epi, 764 #selections=None, 765 #edit_callback=None, 766 single_selection = False, 767 can_return_empty = False, 768 list_tooltip_callback = get_soap_tooltip 769 ) 770 771 if selected_narr is None: 772 return True 773 774 for narr in selected_narr: 775 selected_soap[narr['pk_narrative']] = narr 776 777 return True 778 779 # selection_idxs = [] 780 # for idx in range(len(narr_for_epi)): 781 # if narr_for_epi[idx]['pk_narrative'] in selected_narrative_pks: 782 # selection_idxs.append(idx) 783 # if len(selection_idxs) != 0: 784 # dlg.set_selections(selections = selection_idxs) 785 786 # selected_narrative_pks = [ i['pk_narrative'] for i in selected_narr ] 787 # for narr in selected_narr: 788 # selected_soap[narr['pk_narrative']] = narr 789 # 790 # print "before returning from picking soap" 791 # 792 # return True 793 # #----------------------------------------------- 794 def edit_episode(episode): 795 return gmEMRStructWidgets.edit_episode(parent = parent, episode = episode) 796 #----------------------------------------------- 797 def refresh_episodes(lctrl): 798 all_epis = [ epi for epi in emr.get_episodes(order_by = 'description') if epi.has_narrative ] 799 lctrl.set_string_items ([ [ 800 '%s%s' % (e['description'], gmTools.coalesce(e['health_issue'], '', ' (%s)')), 801 gmTools.bool2subst(e['episode_open'], _('open'), _('closed')) 802 ] for e in all_epis 803 ]) 804 lctrl.set_data(all_epis) 805 #----------------------------------------------- 806 def get_episode_tooltip(episode): 807 return episode.format ( 808 patient = pat, 809 with_encounters = False, 810 with_documents = False, 811 with_hospital_stays = False, 812 with_procedures = False, 813 with_family_history = False, 814 with_tests = False, 815 with_vaccinations = False 816 ) 817 #----------------------------------------------- 818 #selected_episode_pks = [] 819 820 epis_picked_from = gmListWidgets.get_choices_from_list ( 821 parent = parent, 822 msg = _('\n Select the episode you want to report on.'), 823 caption = _('Picking [%s] from episodes') % '/'.join(i18n_soap_cats), 824 columns = [_('Episode'), _('Status')], 825 edit_callback = edit_episode, 826 refresh_callback = refresh_episodes, 827 single_selection = True, 828 can_return_empty = True, 829 ignore_OK_button = False, 830 left_extra_button = ( 831 _('&Pick notes'), 832 _('Pick [%s] entries from selected episode') % '/'.join(i18n_soap_cats), 833 pick_soap_from_episode 834 ), 835 list_tooltip_callback = get_episode_tooltip 836 ) 837 838 if epis_picked_from is None: 839 return [] 840 841 return selected_soap.values() 842 843 # selection_idxs = [] 844 # for idx in range(len(all_epis)): 845 # if all_epis[idx]['pk_episode'] in selected_episode_pks: 846 # selection_idxs.append(idx) 847 # if len(selection_idxs) != 0: 848 # dlg.set_selections(selections = selection_idxs) 849 850 #------------------------------------------------------------
851 -def select_narrative_from_episodes(parent=None, soap_cats=None):
852 """soap_cats needs to be a list""" 853 854 pat = gmPerson.gmCurrentPatient() 855 emr = pat.emr 856 857 if parent is None: 858 parent = wx.GetApp().GetTopWindow() 859 860 selected_soap = {} 861 selected_issue_pks = [] 862 selected_episode_pks = [] 863 selected_narrative_pks = [] 864 865 while 1: 866 # 1) select health issues to select episodes from 867 all_issues = emr.get_health_issues() 868 all_issues.insert(0, gmEMRStructItems.get_dummy_health_issue()) 869 dlg = gmEMRStructWidgets.cIssueListSelectorDlg ( 870 parent = parent, 871 id = -1, 872 issues = all_issues, 873 msg = _('\n In the list below mark the health issues you want to report on.\n') 874 ) 875 selection_idxs = [] 876 for idx in range(len(all_issues)): 877 if all_issues[idx]['pk_health_issue'] in selected_issue_pks: 878 selection_idxs.append(idx) 879 if len(selection_idxs) != 0: 880 dlg.set_selections(selections = selection_idxs) 881 btn_pressed = dlg.ShowModal() 882 selected_issues = dlg.get_selected_item_data() 883 dlg.DestroyLater() 884 885 if btn_pressed == wx.ID_CANCEL: 886 return selected_soap.values() 887 888 selected_issue_pks = [ i['pk_health_issue'] for i in selected_issues ] 889 890 while 1: 891 # 2) select episodes to select items from 892 all_epis = emr.get_episodes(issues = selected_issue_pks) 893 894 if len(all_epis) == 0: 895 gmDispatcher.send(signal = 'statustext', msg = _('No episodes recorded for the health issues selected.')) 896 break 897 898 dlg = gmEMRStructWidgets.cEpisodeListSelectorDlg ( 899 parent = parent, 900 id = -1, 901 episodes = all_epis, 902 msg = _( 903 '\n These are the episodes known for the health issues just selected.\n\n' 904 ' Now, mark the the episodes you want to report on.\n' 905 ) 906 ) 907 selection_idxs = [] 908 for idx in range(len(all_epis)): 909 if all_epis[idx]['pk_episode'] in selected_episode_pks: 910 selection_idxs.append(idx) 911 if len(selection_idxs) != 0: 912 dlg.set_selections(selections = selection_idxs) 913 btn_pressed = dlg.ShowModal() 914 selected_epis = dlg.get_selected_item_data() 915 dlg.DestroyLater() 916 917 if btn_pressed == wx.ID_CANCEL: 918 break 919 920 selected_episode_pks = [ i['pk_episode'] for i in selected_epis ] 921 922 # 3) select narrative corresponding to the above constraints 923 all_narr = emr.get_clin_narrative(episodes = selected_episode_pks, soap_cats = soap_cats) 924 925 if len(all_narr) == 0: 926 gmDispatcher.send(signal = 'statustext', msg = _('No narrative available for selected episodes.')) 927 continue 928 929 dlg = cNarrativeListSelectorDlg ( 930 parent = parent, 931 id = -1, 932 narrative = all_narr, 933 msg = _( 934 '\n This is the narrative (type %s) for the chosen episodes.\n\n' 935 ' Now, mark the entries you want to include in your report.\n' 936 ) % '/'.join([ gmSoapDefs.soap_cat2l10n[cat] for cat in gmTools.coalesce(soap_cats, list('soapu')) ]) 937 ) 938 selection_idxs = [] 939 for idx in range(len(all_narr)): 940 if all_narr[idx]['pk_narrative'] in selected_narrative_pks: 941 selection_idxs.append(idx) 942 if len(selection_idxs) != 0: 943 dlg.set_selections(selections = selection_idxs) 944 btn_pressed = dlg.ShowModal() 945 selected_narr = dlg.get_selected_item_data() 946 dlg.DestroyLater() 947 948 if btn_pressed == wx.ID_CANCEL: 949 continue 950 951 selected_narrative_pks = [ i['pk_narrative'] for i in selected_narr ] 952 for narr in selected_narr: 953 selected_soap[narr['pk_narrative']] = narr
954 955 #============================================================ 956 # main 957 #------------------------------------------------------------ 958 if __name__ == '__main__': 959 960 if len(sys.argv) < 2: 961 sys.exit() 962 963 if sys.argv[1] != 'test': 964 sys.exit() 965 966 from Gnumed.business import gmPersonSearch 967 968 gmI18N.activate_locale() 969 gmI18N.install_domain(domain = 'gnumed') 970 971 #----------------------------------------
972 - def test_select_narrative_from_episodes():
973 pat = gmPersonSearch.ask_for_patient() 974 set_active_patient(patient = pat) 975 app = wx.PyWidgetTester(size = (200, 200)) 976 sels = select_narrative_from_episodes_new() 977 print("selected:") 978 for sel in sels: 979 print(sel)
980 #----------------------------------------
981 - def test_select_narrative():
982 pat = gmPersonSearch.ask_for_patient() 983 set_active_patient(patient = pat) 984 app = wx.PyWidgetTester(size = (200, 200)) 985 sels = select_narrative(parent=None, soap_cats = None) 986 print("selected:") 987 for sel in sels: 988 print(sel)
989 #---------------------------------------- 990 #test_select_narrative_from_episodes() 991 test_select_narrative() 992