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

Source Code for Module Gnumed.wxpython.gmVaccWidgets

   1  """GNUmed immunisation/vaccination widgets. 
   2   
   3  Modelled after Richard Terry's design document. 
   4   
   5  copyright: authors 
   6  """ 
   7  #====================================================================== 
   8  __author__ = "R.Terry, S.J.Tan, K.Hilbert" 
   9  __license__ = "GPL v2 or later (details at http://www.gnu.org)" 
  10   
  11  import sys 
  12  import logging 
  13   
  14   
  15  import wx 
  16   
  17   
  18  if __name__ == '__main__': 
  19          sys.path.insert(0, '../../') 
  20  from Gnumed.pycommon import gmDispatcher 
  21  from Gnumed.pycommon import gmMatchProvider 
  22  from Gnumed.pycommon import gmTools 
  23  from Gnumed.pycommon import gmI18N 
  24  from Gnumed.pycommon import gmCfg 
  25  from Gnumed.pycommon import gmCfg2 
  26  from Gnumed.pycommon import gmDateTime 
  27  from Gnumed.pycommon import gmNetworkTools 
  28  from Gnumed.pycommon import gmPrinting 
  29  from Gnumed.pycommon import gmPG2 
  30   
  31  from Gnumed.business import gmPerson 
  32  from Gnumed.business import gmVaccination 
  33  from Gnumed.business import gmPraxis 
  34  from Gnumed.business import gmProviderInbox 
  35   
  36  from Gnumed.wxpython import gmPhraseWheel 
  37  from Gnumed.wxpython import gmTerryGuiParts 
  38  from Gnumed.wxpython import gmRegetMixin 
  39  from Gnumed.wxpython import gmGuiHelpers 
  40  from Gnumed.wxpython import gmEditArea 
  41  from Gnumed.wxpython import gmListWidgets 
  42  from Gnumed.wxpython import gmFormWidgets 
  43  from Gnumed.wxpython import gmMacro 
  44  from Gnumed.wxpython import gmAuthWidgets 
  45  from Gnumed.wxpython import gmSubstanceMgmtWidgets 
  46   
  47   
  48  _log = logging.getLogger('gm.vacc') 
  49   
  50  #====================================================================== 
  51  # vaccine related widgets 
  52  #---------------------------------------------------------------------- 
53 -def regenerate_generic_vaccines():
54 55 dbo_conn = gmAuthWidgets.get_dbowner_connection(procedure = _('Regenerating generic vaccines')) 56 if dbo_conn is None: 57 return False 58 59 wx.BeginBusyCursor() 60 _cfg = gmCfg2.gmCfgData() 61 sql_script = gmVaccination.write_generic_vaccine_sql ( 62 'client-%s' % _cfg.get(option = 'client_version'), 63 include_indications_mapping = False 64 ) 65 _log.debug('regenerating generic vaccines, SQL script: %s', sql_script) 66 if not gmPG2.run_sql_script(sql_script, conn = dbo_conn): 67 wx.EndBusyCursor() 68 gmGuiHelpers.gm_show_warning ( 69 aMessage = _('Error regenerating generic vaccines.\n\nSee [%s]') % sql_script, 70 aTitle = _('Regenerating generic vaccines') 71 ) 72 return False 73 74 gmDispatcher.send(signal = 'statustext', msg = _('Successfully regenerated generic vaccines ...'), beep = False) 75 wx.EndBusyCursor() 76 return True
77 78 #----------------------------------------------------------------------
79 -def edit_vaccine(parent=None, vaccine=None, single_entry=True):
80 ea = cVaccineEAPnl(parent, -1) 81 ea.data = vaccine 82 ea.mode = gmTools.coalesce(vaccine, 'new', 'edit') 83 dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea, single_entry = single_entry) 84 dlg.SetTitle(gmTools.coalesce(vaccine, _('Adding new vaccine'), _('Editing vaccine'))) 85 if dlg.ShowModal() == wx.ID_OK: 86 dlg.Destroy() 87 return True 88 dlg.Destroy() 89 return False
90 91 #----------------------------------------------------------------------
92 -def manage_vaccines(parent=None):
93 94 if parent is None: 95 parent = wx.GetApp().GetTopWindow() 96 97 # #------------------------------------------------------------ 98 # def delete(vaccine=None): 99 # product = vaccine.product 100 # deleted = gmVaccination.delete_vaccine(vaccine = vaccine['pk_vaccine']) 101 # if not deleted: 102 # gmGuiHelpers.gm_show_info ( 103 # _( 'Cannot delete vaccine\n' 104 # '\n' 105 # ' %s - %s (#%s)\n' 106 # '\n' 107 # 'It is probably documented in a vaccination.' 108 # ) % ( 109 # vaccine['vaccine'], 110 # vaccine['l10n_preparation'], 111 # vaccine['pk_vaccine'] 112 # ), 113 # _('Deleting vaccine') 114 # ) 115 # return False 116 # delete_product = gmGuiHelpers.gm_show_question ( 117 # title = _('Deleting vaccine'), 118 # question = _( 119 # u'Fully delete the vaccine (including the associated drug product) ?\n' 120 # u'\n' 121 # u' "%s" (%s)' 122 # ) % (product['product'], product['l10n_preparation']) 123 # ) 124 # if delete_product: 125 # pass 126 # return True 127 128 #------------------------------------------------------------ 129 def manage_drug_products(vaccine): 130 gmSubstanceMgmtWidgets.manage_drug_products(parent = parent) 131 return True
132 133 #------------------------------------------------------------ 134 def edit(vaccine=None): 135 return edit_vaccine(parent = parent, vaccine = vaccine, single_entry = True) 136 137 #------------------------------------------------------------ 138 def get_tooltip(vaccine): 139 if vaccine is None: 140 return None 141 return '\n'.join(vaccine.format()) 142 143 #------------------------------------------------------------ 144 def refresh(lctrl): 145 vaccines = gmVaccination.get_vaccines(order_by = 'vaccine') 146 147 items = [ [ 148 '%s' % v['pk_drug_product'], 149 '%s%s' % ( 150 v['vaccine'], 151 gmTools.bool2subst ( 152 v['is_fake_vaccine'], 153 ' (%s)' % _('fake'), 154 '' 155 ) 156 ), 157 v['l10n_preparation'], 158 gmTools.coalesce(v['atc_code'], ''), 159 '%s - %s' % ( 160 gmTools.coalesce(v['min_age'], '?'), 161 gmTools.coalesce(v['max_age'], '?'), 162 ), 163 gmTools.coalesce(v['comment'], '') 164 ] for v in vaccines ] 165 lctrl.set_string_items(items) 166 lctrl.set_data(vaccines) 167 168 #------------------------------------------------------------ 169 gmListWidgets.get_choices_from_list ( 170 parent = parent, 171 caption = _('Showing vaccine details'), 172 columns = [ '#', _('Vaccine'), _('Preparation'), _('ATC'), _('Age range'), _('Comment') ], 173 single_selection = True, 174 refresh_callback = refresh, 175 edit_callback = edit, 176 new_callback = edit, 177 #delete_callback = delete, 178 list_tooltip_callback = get_tooltip, 179 left_extra_button = (_('Products'), _('Manage drug products'), manage_drug_products) 180 ) 181 182 #----------------------------------------------------------------------
183 -class cBatchNoPhraseWheel(gmPhraseWheel.cPhraseWheel):
184
185 - def __init__(self, *args, **kwargs):
186 187 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 188 189 context = { 190 'ctxt_vaccine': { 191 'where_part': 'AND pk_vaccine = %(pk_vaccine)s', 192 'placeholder': 'pk_vaccine' 193 } 194 } 195 196 query = """ 197 SELECT data, field_label, list_label FROM ( 198 199 SELECT distinct on (field_label) 200 data, 201 field_label, 202 list_label, 203 rank 204 FROM (( 205 -- batch_no by vaccine 206 SELECT 207 batch_no AS data, 208 batch_no AS field_label, 209 batch_no || ' (' || vaccine || ')' AS list_label, 210 1 as rank 211 FROM 212 clin.v_vaccinations 213 WHERE 214 batch_no %(fragment_condition)s 215 %(ctxt_vaccine)s 216 ) UNION ALL ( 217 -- batch_no for any vaccine 218 SELECT 219 batch_no AS data, 220 batch_no AS field_label, 221 batch_no || ' (' || vaccine || ')' AS list_label, 222 2 AS rank 223 FROM 224 clin.v_vaccinations 225 WHERE 226 batch_no %(fragment_condition)s 227 ) 228 229 ) AS matching_batch_nos 230 231 ) as unique_matches 232 233 ORDER BY rank, list_label 234 LIMIT 25 235 """ 236 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query, context = context) 237 mp.setThresholds(1, 2, 3) 238 self.matcher = mp 239 240 self.unset_context(context = 'pk_vaccine') 241 self.SetToolTip(_('Enter or select the batch/lot number of the vaccine used.')) 242 self.selection_only = False
243 244 #----------------------------------------------------------------------
245 -class cVaccinePhraseWheel(gmPhraseWheel.cPhraseWheel):
246
247 - def __init__(self, *args, **kwargs):
248 249 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 250 251 # consider ATCs in ref.drug_product and ref.vacc_indication 252 query = """ 253 SELECT data, list_label, field_label FROM ( 254 255 SELECT DISTINCT ON (data) 256 data, 257 list_label, 258 field_label 259 FROM (( 260 -- fragment -> vaccine 261 SELECT 262 r_v_v.pk_vaccine 263 AS data, 264 r_v_v.vaccine || ' (' 265 || (SELECT string_agg(l10n_inds.ind_desc::text, ', ') FROM ( 266 SELECT unnest(r_v_v.indications)->>'l10n_indication' AS ind_desc 267 ) AS l10n_inds) 268 || ')' 269 AS list_label, 270 r_v_v.vaccine 271 AS field_label 272 FROM 273 ref.v_vaccines r_v_v 274 WHERE 275 r_v_v.vaccine %(fragment_condition)s 276 277 ) union all ( 278 279 -- fragment -> localized indication -> vaccines 280 SELECT 281 r_vi4v.pk_vaccine 282 AS data, 283 r_vi4v.vaccine || ' (' 284 || (SELECT string_agg(l10n_inds.ind_desc::text, ', ') FROM ( 285 SELECT unnest(r_vi4v.indications)->>'l10n_indication' AS ind_desc 286 ) AS l10n_inds) 287 || ')' 288 AS list_label, 289 r_vi4v.vaccine 290 AS field_label 291 FROM 292 ref.v_indications4vaccine r_vi4v 293 WHERE 294 r_vi4v.l10n_indication %(fragment_condition)s 295 296 ) union all ( 297 298 -- fragment -> indication -> vaccines 299 SELECT 300 r_vi4v.pk_vaccine 301 AS data, 302 r_vi4v.vaccine || ' (' 303 || (SELECT string_agg(l10n_inds.ind_desc::text, ', ') FROM ( 304 SELECT unnest(r_vi4v.indications)->>'l10n_indication' AS ind_desc 305 ) AS l10n_inds) 306 || ')' 307 AS list_label, 308 r_vi4v.vaccine 309 AS field_label 310 FROM 311 ref.v_indications4vaccine r_vi4v 312 WHERE 313 r_vi4v.indication %(fragment_condition)s 314 ) 315 ) AS distinct_total 316 317 ) AS total 318 319 ORDER by list_label 320 LIMIT 25 321 """ 322 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query) 323 mp.setThresholds(1, 2, 3) 324 self.matcher = mp 325 326 self.selection_only = True
327 #------------------------------------------------------------------
328 - def _data2instance(self):
329 return gmVaccination.cVaccine(aPK_obj = self.GetData())
330 331 #---------------------------------------------------------------------- 332 from Gnumed.wxGladeWidgets import wxgVaccineEAPnl 333
334 -class cVaccineEAPnl(wxgVaccineEAPnl.wxgVaccineEAPnl, gmEditArea.cGenericEditAreaMixin):
335
336 - def __init__(self, *args, **kwargs):
337 try: 338 data = kwargs['vaccine'] 339 del kwargs['vaccine'] 340 except KeyError: 341 data = None 342 343 wxgVaccineEAPnl.wxgVaccineEAPnl.__init__(self, *args, **kwargs) 344 gmEditArea.cGenericEditAreaMixin.__init__(self) 345 346 self.mode = 'new' 347 self.data = data 348 if data is not None: 349 self.mode = 'edit' 350 351 self.__indications = None
352 353 #----------------------------------------------------------------
354 - def __refresh_indications(self):
355 self._TCTRL_indications.SetValue('') 356 if self.data is None: 357 return 358 self._TCTRL_indications.SetValue('- ' + '\n- '.join([ i['l10n_indication'] for i in self.data['indications'] ]))
359 360 #---------------------------------------------------------------- 361 # generic Edit Area mixin API 362 #----------------------------------------------------------------
363 - def _valid_for_save(self):
364 365 has_errors = False 366 367 if self._PRW_drug_product.GetValue().strip() == '': 368 has_errors = True 369 self._PRW_drug_product.display_as_valid(False) 370 else: 371 self._PRW_drug_product.display_as_valid(True) 372 373 atc = self._PRW_atc.GetValue().strip() 374 if (atc == '') or (atc.startswith('J07')): 375 self._PRW_atc.display_as_valid(True) 376 else: 377 if self._PRW_atc.GetData() is None: 378 self._PRW_atc.display_as_valid(True) 379 else: 380 has_errors = True 381 self._PRW_atc.display_as_valid(False) 382 383 val = self._PRW_age_min.GetValue().strip() 384 if val == '': 385 self._PRW_age_min.display_as_valid(True) 386 else: 387 if gmDateTime.str2interval(val) is None: 388 has_errors = True 389 self._PRW_age_min.display_as_valid(False) 390 else: 391 self._PRW_age_min.display_as_valid(True) 392 393 val = self._PRW_age_max.GetValue().strip() 394 if val == '': 395 self._PRW_age_max.display_as_valid(True) 396 else: 397 if gmDateTime.str2interval(val) is None: 398 has_errors = True 399 self._PRW_age_max.display_as_valid(False) 400 else: 401 self._PRW_age_max.display_as_valid(True) 402 403 # complex conditions 404 # are we editing ? 405 if self.mode == 'edit': 406 change_of_product = self.data['pk_drug_product'] != self._PRW_drug_product.GetData() 407 if change_of_product and self.data.is_in_use: 408 do_it = gmGuiHelpers.gm_show_question ( 409 aTitle = _('Saving vaccine'), 410 aMessage = _( 411 'This vaccine is already in use:\n' 412 '\n' 413 ' "%s"\n' 414 '\n' 415 'Are you absolutely positively sure that\n' 416 'you really want to edit this vaccine ?\n' 417 '\n' 418 'This will change the vaccine name and/or target\n' 419 'conditions in each patient this vaccine was\n' 420 'used in to document a vaccination with.\n' 421 ) % self._PRW_drug_product.GetValue().strip() 422 ) 423 if not do_it: 424 has_errors = True 425 else: 426 if self._PRW_drug_product.GetData() is None: 427 # need to ask for indications ? 428 if self._PRW_drug_product.GetValue().strip() != '': 429 self.__indications = gmSubstanceMgmtWidgets.manage_substance_doses(vaccine_indications_only = True) 430 if self.__indications is None: 431 has_errors = True 432 else: 433 # existing drug product selected 434 pass 435 436 return (has_errors is False)
437 438 #----------------------------------------------------------------
439 - def _save_as_new(self):
440 441 # save the data as a new instance 442 vaccine = gmVaccination.create_vaccine ( 443 pk_drug_product = self._PRW_drug_product.GetData(), 444 product_name = self._PRW_drug_product.GetValue().strip(), 445 indications = self.__indications 446 ) 447 448 vaccine['is_live'] = self._CHBOX_live.GetValue() 449 val = self._PRW_age_min.GetValue().strip() 450 if val != '': 451 vaccine['min_age'] = gmDateTime.str2interval(val) 452 val = self._PRW_age_max.GetValue().strip() 453 if val != '': 454 vaccine['max_age'] = gmDateTime.str2interval(val) 455 val = self._TCTRL_comment.GetValue().strip() 456 if val != '': 457 vaccine['comment'] = val 458 vaccine.save() 459 460 drug = vaccine.product 461 drug['is_fake_product'] = self._CHBOX_fake.GetValue() 462 val = self._PRW_atc.GetData() 463 if val is not None: 464 if val != 'J07': 465 drug['atc'] = val.strip() 466 drug.save() 467 468 # must be done very late or else the property access 469 # will refresh the display such that later field 470 # access will return empty values 471 self.data = vaccine 472 473 return True
474 475 #----------------------------------------------------------------
476 - def _save_as_update(self):
477 478 drug = self.data.product 479 drug['product'] = self._PRW_drug_product.GetValue().strip() 480 drug['is_fake_product'] = self._CHBOX_fake.GetValue() 481 val = self._PRW_atc.GetData() 482 if val is not None: 483 if val != 'J07': 484 drug['atc'] = val.strip() 485 drug.save() 486 487 self.data['is_live'] = self._CHBOX_live.GetValue() 488 val = self._PRW_age_min.GetValue().strip() 489 if val != '': 490 self.data['min_age'] = gmDateTime.str2interval(val) 491 if val != '': 492 self.data['max_age'] = gmDateTime.str2interval(val) 493 val = self._TCTRL_comment.GetValue().strip() 494 if val != '': 495 self.data['comment'] = val 496 self.data.save() 497 498 return True
499 500 #----------------------------------------------------------------
501 - def _refresh_as_new(self):
502 self._PRW_drug_product.SetText(value = '', data = None, suppress_smarts = True) 503 self._CHBOX_live.SetValue(False) 504 self._CHBOX_fake.SetValue(False) 505 self._PRW_atc.SetText(value = '', data = None, suppress_smarts = True) 506 self._PRW_age_min.SetText(value = '', data = None, suppress_smarts = True) 507 self._PRW_age_max.SetText(value = '', data = None, suppress_smarts = True) 508 self._TCTRL_comment.SetValue('') 509 510 self.__refresh_indications() 511 512 self._PRW_drug_product.SetFocus()
513 514 #----------------------------------------------------------------
515 - def _refresh_from_existing(self):
516 self._PRW_drug_product.SetText(value = self.data['vaccine'], data = self.data['pk_drug_product']) 517 self._CHBOX_live.SetValue(self.data['is_live']) 518 self._CHBOX_fake.SetValue(self.data['is_fake_vaccine']) 519 self._PRW_atc.SetText(value = self.data['atc_code'], data = self.data['atc_code']) 520 if self.data['min_age'] is None: 521 self._PRW_age_min.SetText(value = '', data = None, suppress_smarts = True) 522 else: 523 self._PRW_age_min.SetText ( 524 value = gmDateTime.format_interval(self.data['min_age'], gmDateTime.acc_years), 525 data = self.data['min_age'] 526 ) 527 if self.data['max_age'] is None: 528 self._PRW_age_max.SetText(value = '', data = None, suppress_smarts = True) 529 else: 530 self._PRW_age_max.SetText ( 531 value = gmDateTime.format_interval(self.data['max_age'], gmDateTime.acc_years), 532 data = self.data['max_age'] 533 ) 534 self._TCTRL_comment.SetValue(gmTools.coalesce(self.data['comment'], '')) 535 536 self.__refresh_indications() 537 538 self._PRW_drug_product.SetFocus()
539 540 #----------------------------------------------------------------
542 self._refresh_as_new()
543 544 #---------------------------------------------------------------- 545 #---------------------------------------------------------------- 546 547 #====================================================================== 548 # vaccination related widgets 549 #---------------------------------------------------------------------- 576 577 #----------------------------------------------------------------------
578 -def edit_vaccination(parent=None, vaccination=None, single_entry=True):
579 ea = cVaccinationEAPnl(parent, -1) 580 ea.data = vaccination 581 ea.mode = gmTools.coalesce(vaccination, 'new', 'edit') 582 dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea, single_entry = single_entry) 583 dlg.SetTitle(gmTools.coalesce(vaccination, _('Adding new vaccinations'), _('Editing vaccination'))) 584 if dlg.ShowModal() == wx.ID_OK: 585 dlg.Destroy() 586 return True 587 dlg.Destroy() 588 if not single_entry: 589 return True 590 return False
591 592 #----------------------------------------------------------------------
593 -def manage_vaccinations(parent=None, latest_only=False, expand_indications=False):
594 595 pat = gmPerson.gmCurrentPatient() 596 emr = pat.emr 597 598 if parent is None: 599 parent = wx.GetApp().GetTopWindow() 600 601 #------------------------------------------------------------ 602 def browse2schedules(vaccination=None): 603 dbcfg = gmCfg.cCfgSQL() 604 url = dbcfg.get2 ( 605 option = 'external.urls.vaccination_plans', 606 workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace, 607 bias = 'user', 608 default = gmVaccination.URL_vaccination_plan 609 ) 610 611 gmNetworkTools.open_url_in_browser(url = url) 612 return False
613 614 #------------------------------------------------------------ 615 def print_vaccs(vaccination=None): 616 print_vaccinations(parent = parent) 617 return False 618 619 #------------------------------------------------------------ 620 def add_recall(vaccination=None): 621 if vaccination is None: 622 subject = _('vaccination recall') 623 else: 624 subject = _('vaccination recall (%s)') % vaccination['vaccine'] 625 626 recall = gmProviderInbox.create_inbox_message ( 627 message_type = _('Vaccination'), 628 subject = subject, 629 patient = pat.ID, 630 staff = None 631 ) 632 633 if vaccination is not None: 634 recall['data'] = _('Existing vaccination:\n\n%s') % '\n'.join(vaccination.format( 635 with_indications = True, 636 with_comment = True, 637 with_reaction = False, 638 date_format = '%Y %b %d' 639 )) 640 recall.save() 641 642 from Gnumed.wxpython import gmProviderInboxWidgets 643 gmProviderInboxWidgets.edit_inbox_message ( 644 parent = parent, 645 message = recall, 646 single_entry = False 647 ) 648 649 return False 650 651 #------------------------------------------------------------ 652 def get_tooltip(vaccination): 653 if vaccination is None: 654 return None 655 return '\n'.join(vaccination.format ( 656 with_indications = True, 657 with_comment = True, 658 with_reaction = True, 659 date_format = '%Y %b %d' 660 )) 661 662 #------------------------------------------------------------ 663 def edit(vaccination=None): 664 return edit_vaccination(parent = parent, vaccination = vaccination, single_entry = (vaccination is not None)) 665 666 #------------------------------------------------------------ 667 def delete(vaccination=None): 668 gmVaccination.delete_vaccination(vaccination = vaccination['pk_vaccination']) 669 return True 670 671 #------------------------------------------------------------ 672 def refresh(lctrl): 673 674 items = [] 675 data = [] 676 if latest_only: 677 latest_vaccs = emr.get_latest_vaccinations() 678 for indication in sorted(latest_vaccs.keys()): 679 no_of_shots4ind, latest_vacc4ind = latest_vaccs[indication] 680 items.append ([ 681 indication, 682 _('%s (latest of %s: %s ago)') % ( 683 gmDateTime.pydt_strftime(latest_vacc4ind['date_given'], format = '%Y %b'), 684 no_of_shots4ind, 685 gmDateTime.format_interval_medically(gmDateTime.pydt_now_here() - latest_vacc4ind['date_given']) 686 ), 687 latest_vacc4ind['vaccine'], 688 latest_vacc4ind['batch_no'], 689 gmTools.coalesce(latest_vacc4ind['site'], ''), 690 gmTools.coalesce(latest_vacc4ind['reaction'], ''), 691 gmTools.coalesce(latest_vacc4ind['comment'], '') 692 ]) 693 data.append(latest_vacc4ind) 694 else: 695 shots = emr.get_vaccinations(order_by = 'date_given DESC, pk_vaccination') 696 if expand_indications: 697 shots_by_ind = {} 698 for shot in shots: 699 for ind in shot['indications']: 700 try: 701 shots_by_ind[ind['l10n_indication']].append(shot) 702 except KeyError: 703 shots_by_ind[ind['l10n_indication']] = [shot] 704 for ind in sorted(shots_by_ind.keys()): 705 idx = len(shots_by_ind[ind]) 706 for shot in shots_by_ind[ind]: 707 items.append ([ 708 '%s (#%s)' % (ind, idx), 709 _('%s (%s ago)') % ( 710 gmDateTime.pydt_strftime(shot['date_given'], '%Y %b %d'), 711 gmDateTime.format_interval_medically(gmDateTime.pydt_now_here() - shot['date_given']) 712 ), 713 shot['vaccine'], 714 shot['batch_no'], 715 gmTools.coalesce(shot['site'], ''), 716 gmTools.coalesce(shot['reaction'], ''), 717 gmTools.coalesce(shot['comment'], '') 718 ]) 719 idx -= 1 720 data.append(shot) 721 else: 722 items = [ [ 723 gmDateTime.pydt_strftime(s['date_given'], '%Y %b %d'), 724 s['vaccine'], 725 ', '.join([ i['l10n_indication'] for i in s['indications'] ]), 726 s['batch_no'], 727 gmTools.coalesce(s['site'], ''), 728 gmTools.coalesce(s['reaction'], ''), 729 gmTools.coalesce(s['comment'], '') 730 ] for s in shots ] 731 data = shots 732 733 lctrl.set_string_items(items) 734 lctrl.set_data(data) 735 736 #------------------------------------------------------------ 737 if latest_only: 738 msg = _('Most recent vaccination for each indication.\n') 739 cols = [ _('Indication'), _('Date'), _('Vaccine'), _('Batch'), _('Site'), _('Reaction'), _('Comment') ] 740 else: 741 if expand_indications: 742 msg = _('Complete vaccination history (per indication).\n') 743 cols = [ _('Indication'), _('Date'), _('Vaccine'), _('Batch'), _('Site'), _('Reaction'), _('Comment') ] 744 else: 745 msg = _('Complete vaccination history (by shot).\n') 746 cols = [ _('Date'), _('Vaccine'), _('Intended to protect from'), _('Batch'), _('Site'), _('Reaction'), _('Comment') ] 747 748 gmListWidgets.get_choices_from_list ( 749 parent = parent, 750 msg = msg, 751 caption = _('Showing vaccinations.'), 752 columns = cols, 753 single_selection = True, 754 refresh_callback = refresh, 755 new_callback = edit, 756 edit_callback = edit, 757 delete_callback = delete, 758 list_tooltip_callback = get_tooltip, 759 left_extra_button = (_('Print'), _('Print vaccinations or recalls.'), print_vaccs), 760 middle_extra_button = (_('Recall'), _('Add a recall for a vaccination'), add_recall), 761 right_extra_button = (_('Vx schedules'), _('Open a browser showing vaccination schedules.'), browse2schedules) 762 ) 763 764 #---------------------------------------------------------------------- 765 from Gnumed.wxGladeWidgets import wxgVaccinationEAPnl 766
767 -class cVaccinationEAPnl(wxgVaccinationEAPnl.wxgVaccinationEAPnl, gmEditArea.cGenericEditAreaMixin):
768 """ 769 - warn on apparent duplicates 770 - ask if "missing" (= previous, non-recorded) vaccinations 771 should be estimated and saved (add note "auto-generated") 772 773 Batch No (http://www.fao.org/docrep/003/v9952E12.htm) 774 """
775 - def __init__(self, *args, **kwargs):
776 777 try: 778 data = kwargs['vaccination'] 779 del kwargs['vaccination'] 780 except KeyError: 781 data = None 782 783 wxgVaccinationEAPnl.wxgVaccinationEAPnl.__init__(self, *args, **kwargs) 784 gmEditArea.cGenericEditAreaMixin.__init__(self) 785 786 self.mode = 'new' 787 self.data = data 788 if data is not None: 789 self.mode = 'edit' 790 791 self.__init_ui()
792 793 #----------------------------------------------------------------
794 - def __init_ui(self):
795 # adjust phrasewheels etc 796 self._PRW_vaccine.add_callback_on_lose_focus(self._on_PRW_vaccine_lost_focus) 797 self._PRW_provider.selection_only = False 798 self._PRW_reaction.add_callback_on_lose_focus(self._on_PRW_reaction_lost_focus)
799 800 #----------------------------------------------------------------
801 - def _on_PRW_vaccine_lost_focus(self):
802 803 vaccine = self._PRW_vaccine.GetData(as_instance=True) 804 805 if self.mode == 'edit': 806 if vaccine is None: 807 self._PRW_batch.unset_context(context = 'pk_vaccine') 808 else: 809 self._PRW_batch.set_context(context = 'pk_vaccine', val = vaccine['pk_vaccine']) 810 # we are entering a new vaccination 811 else: 812 if vaccine is None: 813 self._PRW_batch.unset_context(context = 'pk_vaccine') 814 else: 815 self._PRW_batch.set_context(context = 'pk_vaccine', val = vaccine['pk_vaccine']) 816 817 self.__refresh_indications()
818 819 #----------------------------------------------------------------
821 if self._PRW_reaction.GetValue().strip() == '': 822 self._BTN_report.Enable(False) 823 else: 824 self._BTN_report.Enable(True)
825 826 #----------------------------------------------------------------
827 - def __refresh_indications(self):
828 self._TCTRL_indications.SetValue('') 829 vaccine = self._PRW_vaccine.GetData(as_instance = True) 830 if vaccine is None: 831 return 832 lines = [] 833 emr = gmPerson.gmCurrentPatient().emr 834 latest_vaccs = emr.get_latest_vaccinations ( 835 atc_indications = [ i['atc_indication'] for i in vaccine['indications'] ] 836 ) 837 for l10n_ind in [ i['l10n_indication'] for i in vaccine['indications'] ]: 838 try: 839 no_of_shots4ind, latest_vacc4ind = latest_vaccs[l10n_ind] 840 ago = gmDateTime.format_interval_medically(gmDateTime.pydt_now_here() - latest_vacc4ind['date_given']) 841 lines.append(_('%s (most recent shot of %s: %s ago)') % (l10n_ind, no_of_shots4ind, ago)) 842 except KeyError: 843 lines.append(_('%s (no previous vaccination recorded)') % l10n_ind) 844 845 self._TCTRL_indications.SetValue(_('Protects against:\n ') + '\n '.join(lines))
846 847 #---------------------------------------------------------------- 848 # generic Edit Area mixin API 849 #----------------------------------------------------------------
850 - def _valid_for_save(self):
851 852 has_errors = False 853 854 if not self._PRW_date_given.is_valid_timestamp(empty_is_valid = False): 855 has_errors = True 856 857 vaccine = self._PRW_vaccine.GetData(as_instance = True) 858 if vaccine is None: 859 has_errors = True 860 self._PRW_vaccine.display_as_valid(False) 861 else: 862 self._PRW_vaccine.display_as_valid(True) 863 864 if self._PRW_batch.GetValue().strip() == '': 865 has_errors = True 866 self._PRW_batch.display_as_valid(False) 867 else: 868 self._PRW_batch.display_as_valid(True) 869 870 if self._PRW_episode.GetValue().strip() == '': 871 self._PRW_episode.SetText(value = _('prevention')) 872 873 return (has_errors is False)
874 875 #----------------------------------------------------------------
876 - def _save_as_new(self):
877 878 vaccine = self._PRW_vaccine.GetData() 879 data = self.__save_new_from_vaccine(vaccine = vaccine) 880 881 # must be done very late or else the property access 882 # will refresh the display such that later field 883 # access will return empty values 884 self.data = data 885 886 return True
887 888 #----------------------------------------------------------------
889 - def __save_new_from_vaccine(self, vaccine=None):
890 891 emr = gmPerson.gmCurrentPatient().emr 892 893 data = emr.add_vaccination ( 894 episode = self._PRW_episode.GetData(can_create = True, is_open = False), 895 vaccine = vaccine, 896 batch_no = self._PRW_batch.GetValue().strip() 897 ) 898 899 if self._CHBOX_anamnestic.GetValue() is True: 900 data['soap_cat'] = 's' 901 else: 902 data['soap_cat'] = 'p' 903 904 data['date_given'] = self._PRW_date_given.GetData() 905 data['site'] = self._PRW_site.GetValue().strip() 906 data['pk_provider'] = self._PRW_provider.GetData() 907 data['reaction'] = self._PRW_reaction.GetValue().strip() 908 data['comment'] = self._TCTRL_comment.GetValue().strip() 909 910 data.save() 911 912 return data
913 914 #----------------------------------------------------------------
915 - def _save_as_update(self):
916 917 if self._CHBOX_anamnestic.GetValue() is True: 918 self.data['soap_cat'] = 's' 919 else: 920 self.data['soap_cat'] = 'p' 921 922 self.data['date_given'] = self._PRW_date_given.GetData() 923 self.data['pk_vaccine'] = self._PRW_vaccine.GetData() 924 self.data['batch_no'] = self._PRW_batch.GetValue().strip() 925 self.data['pk_episode'] = self._PRW_episode.GetData(can_create = True, is_open = False) 926 self.data['site'] = self._PRW_site.GetValue().strip() 927 self.data['pk_provider'] = self._PRW_provider.GetData() 928 self.data['reaction'] = self._PRW_reaction.GetValue().strip() 929 self.data['comment'] = self._TCTRL_comment.GetValue().strip() 930 931 self.data.save() 932 933 return True
934 935 #----------------------------------------------------------------
936 - def _refresh_as_new(self):
937 self._PRW_date_given.SetText(data = gmDateTime.pydt_now_here()) 938 self._CHBOX_anamnestic.SetValue(False) 939 self._PRW_vaccine.SetText(value = '', data = None, suppress_smarts = True) 940 self._PRW_batch.unset_context(context = 'pk_vaccine') 941 self._PRW_batch.SetValue('') 942 self._PRW_episode.SetText(value = '', data = None, suppress_smarts = True) 943 self._PRW_site.SetValue('') 944 self._PRW_provider.SetData(data = None) 945 self._PRW_reaction.SetText(value = '', data = None, suppress_smarts = True) 946 self._BTN_report.Enable(False) 947 self._TCTRL_comment.SetValue('') 948 949 self.__refresh_indications() 950 951 self._PRW_date_given.SetFocus()
952 953 #----------------------------------------------------------------
954 - def _refresh_from_existing(self):
955 self._PRW_date_given.SetText(data = self.data['date_given']) 956 if self.data['soap_cat'] == 's': 957 self._CHBOX_anamnestic.SetValue(True) 958 else: 959 self._CHBOX_anamnestic.SetValue(False) 960 self._PRW_vaccine.SetText(value = self.data['vaccine'], data = self.data['pk_vaccine']) 961 962 self._PRW_batch.SetValue(self.data['batch_no']) 963 self._PRW_episode.SetData(data = self.data['pk_episode']) 964 self._PRW_site.SetValue(gmTools.coalesce(self.data['site'], '')) 965 self._PRW_provider.SetData(self.data['pk_provider']) 966 self._PRW_reaction.SetValue(gmTools.coalesce(self.data['reaction'], '')) 967 if self.data['reaction'] is None: 968 self._BTN_report.Enable(False) 969 else: 970 self._BTN_report.Enable(True) 971 self._TCTRL_comment.SetValue(gmTools.coalesce(self.data['comment'], '')) 972 973 self.__refresh_indications() 974 975 self._PRW_date_given.SetFocus()
976 977 #----------------------------------------------------------------
979 self._PRW_date_given.SetText(data = self.data['date_given']) 980 #self._CHBOX_anamnestic.SetValue(False) 981 self._PRW_vaccine.SetText(value = self.data['vaccine'], data = self.data['pk_vaccine']) 982 983 self._PRW_batch.set_context(context = 'pk_vaccine', val = self.data['pk_vaccine']) 984 self._PRW_batch.SetValue('') 985 986 self._PRW_episode.SetData(data = self.data['pk_episode']) 987 self._PRW_site.SetValue(gmTools.coalesce(self.data['site'], '')) 988 self._PRW_provider.SetData(self.data['pk_provider']) 989 self._PRW_reaction.SetValue('') 990 self._BTN_report.Enable(False) 991 self._TCTRL_comment.SetValue('') 992 993 self.__refresh_indications() 994 995 self._PRW_date_given.SetFocus()
996 997 #---------------------------------------------------------------- 998 # event handlers 999 #----------------------------------------------------------------
1000 - def _on_report_button_pressed(self, event):
1001 event.Skip() 1002 dbcfg = gmCfg.cCfgSQL() 1003 url = dbcfg.get2 ( 1004 option = 'external.urls.report_vaccine_ADR', 1005 workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace, 1006 bias = 'user', 1007 default = 'http://www.pei.de/cln_042/SharedDocs/Downloads/fachkreise/uaw/meldeboegen/b-ifsg-meldebogen,templateId=raw,property=publicationFile.pdf/b-ifsg-meldebogen.pdf' 1008 ) 1009 1010 if url.strip() == '': 1011 url = dbcfg.get2 ( 1012 option = 'external.urls.report_ADR', 1013 workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace, 1014 bias = 'user' 1015 ) 1016 gmNetworkTools.open_url_in_browser(url = url)
1017 #----------------------------------------------------------------
1018 - def _on_add_vaccine_button_pressed(self, event):
1019 edit_vaccine(parent = self, vaccine = None, single_entry = False)
1020 # FIXME: could set newly generated vaccine here 1021 1022 #====================================================================== 1023 #====================================================================== 1024 #====================================================================== 1025 #======================================================================
1026 -class cImmunisationsPanel(wx.Panel, gmRegetMixin.cRegetOnPaintMixin):
1027
1028 - def __init__(self, parent, id):
1029 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, wx.RAISED_BORDER) 1030 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 1031 self.__pat = gmPerson.gmCurrentPatient() 1032 # do this here so "import cImmunisationsPanel from gmVaccWidgets" works 1033 self.ID_VaccinatedIndicationsList = wx.NewId() 1034 self.ID_VaccinationsPerRegimeList = wx.NewId() 1035 self.ID_MissingShots = wx.NewId() 1036 self.ID_ActiveSchedules = wx.NewId() 1037 self.__do_layout() 1038 self.__register_interests() 1039 self.__reset_ui_content()
1040 #----------------------------------------------------
1041 - def __do_layout(self):
1042 #----------------------------------------------- 1043 # top part 1044 #----------------------------------------------- 1045 pnl_UpperCaption = gmTerryGuiParts.cHeadingCaption(self, -1, _(" IMMUNISATIONS ")) 1046 self.editarea = cVaccinationEditArea(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.NO_BORDER) 1047 1048 #----------------------------------------------- 1049 # middle part 1050 #----------------------------------------------- 1051 # divider headings below editing area 1052 indications_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Indications")) 1053 vaccinations_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Vaccinations")) 1054 schedules_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Active Schedules")) 1055 szr_MiddleCap = wx.BoxSizer(wx.HORIZONTAL) 1056 szr_MiddleCap.Add(indications_heading, 4, wx.EXPAND) 1057 szr_MiddleCap.Add(vaccinations_heading, 6, wx.EXPAND) 1058 szr_MiddleCap.Add(schedules_heading, 10, wx.EXPAND) 1059 1060 # left list: indications for which vaccinations have been given 1061 self.LBOX_vaccinated_indications = wx.ListBox( 1062 parent = self, 1063 id = self.ID_VaccinatedIndicationsList, 1064 choices = [], 1065 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 1066 ) 1067 self.LBOX_vaccinated_indications.SetFont(wx.Font(12,wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 1068 1069 # right list: when an indication has been selected on the left 1070 # display the corresponding vaccinations on the right 1071 self.LBOX_given_shots = wx.ListBox( 1072 parent = self, 1073 id = self.ID_VaccinationsPerRegimeList, 1074 choices = [], 1075 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 1076 ) 1077 self.LBOX_given_shots.SetFont(wx.Font(12,wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 1078 1079 self.LBOX_active_schedules = wx.ListBox ( 1080 parent = self, 1081 id = self.ID_ActiveSchedules, 1082 choices = [], 1083 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 1084 ) 1085 self.LBOX_active_schedules.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 1086 1087 szr_MiddleLists = wx.BoxSizer(wx.HORIZONTAL) 1088 szr_MiddleLists.Add(self.LBOX_vaccinated_indications, 4, wx.EXPAND) 1089 szr_MiddleLists.Add(self.LBOX_given_shots, 6, wx.EXPAND) 1090 szr_MiddleLists.Add(self.LBOX_active_schedules, 10, wx.EXPAND) 1091 1092 #--------------------------------------------- 1093 # bottom part 1094 #--------------------------------------------- 1095 missing_heading = gmTerryGuiParts.cDividerCaption(self, -1, _("Missing Immunisations")) 1096 szr_BottomCap = wx.BoxSizer(wx.HORIZONTAL) 1097 szr_BottomCap.Add(missing_heading, 1, wx.EXPAND) 1098 1099 self.LBOX_missing_shots = wx.ListBox ( 1100 parent = self, 1101 id = self.ID_MissingShots, 1102 choices = [], 1103 style = wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.SUNKEN_BORDER 1104 ) 1105 self.LBOX_missing_shots.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, '')) 1106 1107 szr_BottomLists = wx.BoxSizer(wx.HORIZONTAL) 1108 szr_BottomLists.Add(self.LBOX_missing_shots, 1, wx.EXPAND) 1109 1110 # alert caption 1111 pnl_AlertCaption = gmTerryGuiParts.cAlertCaption(self, -1, _(' Alerts ')) 1112 1113 #--------------------------------------------- 1114 # add all elements to the main background sizer 1115 #--------------------------------------------- 1116 self.mainsizer = wx.BoxSizer(wx.VERTICAL) 1117 self.mainsizer.Add(pnl_UpperCaption, 0, wx.EXPAND) 1118 self.mainsizer.Add(self.editarea, 6, wx.EXPAND) 1119 self.mainsizer.Add(szr_MiddleCap, 0, wx.EXPAND) 1120 self.mainsizer.Add(szr_MiddleLists, 4, wx.EXPAND) 1121 self.mainsizer.Add(szr_BottomCap, 0, wx.EXPAND) 1122 self.mainsizer.Add(szr_BottomLists, 4, wx.EXPAND) 1123 self.mainsizer.Add(pnl_AlertCaption, 0, wx.EXPAND) 1124 1125 self.SetAutoLayout(True) 1126 self.SetSizer(self.mainsizer) 1127 self.mainsizer.Fit(self)
1128 #----------------------------------------------------
1129 - def __register_interests(self):
1130 # wxPython events 1131 wx.EVT_SIZE(self, self.OnSize) 1132 wx.EVT_LISTBOX(self, self.ID_VaccinatedIndicationsList, self._on_vaccinated_indication_selected) 1133 wx.EVT_LISTBOX_DCLICK(self, self.ID_VaccinationsPerRegimeList, self._on_given_shot_selected) 1134 wx.EVT_LISTBOX_DCLICK(self, self.ID_MissingShots, self._on_missing_shot_selected) 1135 # wx.EVT_RIGHT_UP(self.lb1, self.EvtRightButton) 1136 1137 # client internal signals 1138 gmDispatcher.connect(signal= 'post_patient_selection', receiver=self._schedule_data_reget) 1139 gmDispatcher.connect(signal= 'vaccinations_updated', receiver=self._schedule_data_reget)
1140 #---------------------------------------------------- 1141 # event handlers 1142 #----------------------------------------------------
1143 - def OnSize (self, event):
1144 w, h = event.GetSize() 1145 self.mainsizer.SetDimension (0, 0, w, h)
1146 #----------------------------------------------------
1147 - def _on_given_shot_selected(self, event):
1148 """Paste previously given shot into edit area. 1149 """ 1150 self.editarea.set_data(aVacc=event.GetClientData())
1151 #----------------------------------------------------
1152 - def _on_missing_shot_selected(self, event):
1153 self.editarea.set_data(aVacc = event.GetClientData())
1154 #----------------------------------------------------
1155 - def _on_vaccinated_indication_selected(self, event):
1156 """Update right hand middle list to show vaccinations given for selected indication.""" 1157 ind_list = event.GetEventObject() 1158 selected_item = ind_list.GetSelection() 1159 ind = ind_list.GetClientData(selected_item) 1160 # clear list 1161 self.LBOX_given_shots.Set([]) 1162 emr = self.__pat.emr 1163 shots = emr.get_vaccinations(indications = [ind]) 1164 # FIXME: use Set() for entire array (but problem with client_data) 1165 for shot in shots: 1166 if shot['is_booster']: 1167 marker = 'B' 1168 else: 1169 marker = '#%s' % shot['seq_no'] 1170 label = '%s - %s: %s' % (marker, shot['date'].strftime('%m/%Y'), shot['vaccine']) 1171 self.LBOX_given_shots.Append(label, shot)
1172 #----------------------------------------------------
1173 - def __reset_ui_content(self):
1174 # clear edit area 1175 self.editarea.set_data() 1176 # clear lists 1177 self.LBOX_vaccinated_indications.Clear() 1178 self.LBOX_given_shots.Clear() 1179 self.LBOX_active_schedules.Clear() 1180 self.LBOX_missing_shots.Clear()
1181 #----------------------------------------------------
1182 - def _populate_with_data(self):
1183 # clear lists 1184 self.LBOX_vaccinated_indications.Clear() 1185 self.LBOX_given_shots.Clear() 1186 self.LBOX_active_schedules.Clear() 1187 self.LBOX_missing_shots.Clear() 1188 1189 emr = self.__pat.emr 1190 1191 t1 = time.time() 1192 # populate vaccinated-indications list 1193 # FIXME: consider adding virtual indication "most recent" to 1194 # FIXME: display most recent of all indications as suggested by Syan 1195 status, indications = emr.get_vaccinated_indications() 1196 # FIXME: would be faster to use Set() but can't 1197 # use Set(labels, client_data), and have to know 1198 # line position in SetClientData :-( 1199 for indication in indications: 1200 self.LBOX_vaccinated_indications.Append(indication[1], indication[0]) 1201 # self.LBOX_vaccinated_indications.Set(lines) 1202 # self.LBOX_vaccinated_indications.SetClientData(data) 1203 print("vaccinated indications took", time.time()-t1, "seconds") 1204 1205 t1 = time.time() 1206 # populate active schedules list 1207 scheds = emr.get_scheduled_vaccination_regimes() 1208 if scheds is None: 1209 label = _('ERROR: cannot retrieve active vaccination schedules') 1210 self.LBOX_active_schedules.Append(label) 1211 elif len(scheds) == 0: 1212 label = _('no active vaccination schedules') 1213 self.LBOX_active_schedules.Append(label) 1214 else: 1215 for sched in scheds: 1216 label = _('%s for %s (%s shots): %s') % (sched['regime'], sched['l10n_indication'], sched['shots'], sched['comment']) 1217 self.LBOX_active_schedules.Append(label) 1218 print("active schedules took", time.time()-t1, "seconds") 1219 1220 t1 = time.time() 1221 # populate missing-shots list 1222 missing_shots = emr.get_missing_vaccinations() 1223 print("getting missing shots took", time.time()-t1, "seconds") 1224 if missing_shots is None: 1225 label = _('ERROR: cannot retrieve due/overdue vaccinations') 1226 self.LBOX_missing_shots.Append(label, None) 1227 return True 1228 # due 1229 due_template = _('%.0d weeks left: shot %s for %s in %s, due %s (%s)') 1230 overdue_template = _('overdue %.0dyrs %.0dwks: shot %s for %s in schedule "%s" (%s)') 1231 for shot in missing_shots['due']: 1232 if shot['overdue']: 1233 years, days_left = divmod(shot['amount_overdue'].days, 364.25) 1234 weeks = days_left / 7 1235 # amount_overdue, seq_no, indication, regime, vacc_comment 1236 label = overdue_template % ( 1237 years, 1238 weeks, 1239 shot['seq_no'], 1240 shot['l10n_indication'], 1241 shot['regime'], 1242 shot['vacc_comment'] 1243 ) 1244 self.LBOX_missing_shots.Append(label, shot) 1245 else: 1246 # time_left, seq_no, regime, latest_due, vacc_comment 1247 label = due_template % ( 1248 shot['time_left'].days / 7, 1249 shot['seq_no'], 1250 shot['indication'], 1251 shot['regime'], 1252 shot['latest_due'].strftime('%m/%Y'), 1253 shot['vacc_comment'] 1254 ) 1255 self.LBOX_missing_shots.Append(label, shot) 1256 # booster 1257 lbl_template = _('due now: booster for %s in schedule "%s" (%s)') 1258 for shot in missing_shots['boosters']: 1259 # indication, regime, vacc_comment 1260 label = lbl_template % ( 1261 shot['l10n_indication'], 1262 shot['regime'], 1263 shot['vacc_comment'] 1264 ) 1265 self.LBOX_missing_shots.Append(label, shot) 1266 print("displaying missing shots took", time.time()-t1, "seconds") 1267 1268 return True
1269 #----------------------------------------------------
1270 - def _on_post_patient_selection(self, **kwargs):
1271 return 1
1272 # FIXME: 1273 # if has_focus: 1274 # wxCallAfter(self.__reset_ui_content) 1275 # else: 1276 # return 1 1277 #----------------------------------------------------
1278 - def _on_vaccinations_updated(self, **kwargs):
1279 return 1
1280 # FIXME: 1281 # if has_focus: 1282 # wxCallAfter(self.__reset_ui_content) 1283 # else: 1284 # is_stale == True 1285 # return 1 1286 #====================================================================== 1287 # main 1288 #---------------------------------------------------------------------- 1289 if __name__ == "__main__": 1290 1291 if len(sys.argv) < 2: 1292 sys.exit() 1293 1294 if sys.argv[1] != 'test': 1295 sys.exit() 1296 1297 app = wx.PyWidgetTester(size = (600, 600)) 1298 app.SetWidget(cXxxPhraseWheel, -1) 1299 app.MainLoop() 1300