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

Source Code for Module Gnumed.wxpython.gmBillingWidgets

   1  """GNUmed billing handling widgets. 
   2  """ 
   3  #================================================================ 
   4  __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>" 
   5  __license__ = "GPL v2 or later" 
   6   
   7  import logging 
   8  import sys 
   9   
  10   
  11  import wx 
  12   
  13   
  14  if __name__ == '__main__': 
  15          sys.path.insert(0, '../../') 
  16  from Gnumed.pycommon import gmTools 
  17  from Gnumed.pycommon import gmDateTime 
  18  from Gnumed.pycommon import gmMatchProvider 
  19  from Gnumed.pycommon import gmDispatcher 
  20  from Gnumed.pycommon import gmPG2 
  21  from Gnumed.pycommon import gmCfg 
  22  from Gnumed.pycommon import gmPrinting 
  23  from Gnumed.pycommon import gmNetworkTools 
  24   
  25  from Gnumed.business import gmBilling 
  26  from Gnumed.business import gmPerson 
  27  from Gnumed.business import gmStaff 
  28  from Gnumed.business import gmDocuments 
  29  from Gnumed.business import gmSurgery 
  30  from Gnumed.business import gmForms 
  31  from Gnumed.business import gmDemographicRecord 
  32   
  33  from Gnumed.wxpython import gmListWidgets 
  34  from Gnumed.wxpython import gmRegetMixin 
  35  from Gnumed.wxpython import gmPhraseWheel 
  36  from Gnumed.wxpython import gmGuiHelpers 
  37  from Gnumed.wxpython import gmEditArea 
  38  from Gnumed.wxpython import gmPersonContactWidgets 
  39  from Gnumed.wxpython import gmMacro 
  40  from Gnumed.wxpython import gmFormWidgets 
  41  from Gnumed.wxpython import gmDocumentWidgets 
  42  from Gnumed.wxpython import gmDataPackWidgets 
  43   
  44   
  45  _log = logging.getLogger('gm.ui') 
  46   
  47  #================================================================ 
48 -def manage_billables(parent=None):
49 50 if parent is None: 51 parent = wx.GetApp().GetTopWindow() 52 #------------------------------------------------------------ 53 # def edit(substance=None): 54 # return edit_consumable_substance(parent = parent, substance = substance, single_entry = (substance is not None)) 55 #------------------------------------------------------------ 56 def delete(billable): 57 if billable.is_in_use: 58 gmDispatcher.send(signal = 'statustext', msg = _('Cannot delete this billable item. It is in use.'), beep = True) 59 return False 60 return gmBilling.delete_billable(pk_billable = billable['pk_billable'])
61 #------------------------------------------------------------ 62 def get_tooltip(item): 63 if item is None: 64 return None 65 return item.format() 66 #------------------------------------------------------------ 67 def refresh(lctrl): 68 billables = gmBilling.get_billables() 69 items = [ [ 70 b['billable_code'], 71 b['billable_description'], 72 u'%s %s' % (b['raw_amount'], b['currency']), 73 u'%s (%s)' % (b['catalog_short'], b['catalog_version']), 74 gmTools.coalesce(b['comment'], u''), 75 b['pk_billable'] 76 ] for b in billables ] 77 lctrl.set_string_items(items) 78 lctrl.set_data(billables) 79 #------------------------------------------------------------ 80 def manage_data_packs(billable): 81 gmDataPackWidgets.manage_data_packs(parent = parent) 82 return True 83 #------------------------------------------------------------ 84 def browse_catalogs(billable): 85 dbcfg = gmCfg.cCfgSQL() 86 url = dbcfg.get2 ( 87 option = 'external.urls.schedules_of_fees', 88 workplace = gmSurgery.gmCurrentPractice().active_workplace, 89 bias = 'user', 90 default = u'http://www.e-bis.de/goae/defaultFrame.htm' 91 ) 92 gmNetworkTools.open_url_in_browser(url = url) 93 return False 94 #------------------------------------------------------------ 95 msg = _('\nThese are the items for billing registered with GNUmed.\n') 96 97 gmListWidgets.get_choices_from_list ( 98 parent = parent, 99 msg = msg, 100 caption = _('Showing billable items.'), 101 columns = [_('Code'), _('Description'), _('Value'), _('Catalog'), _('Comment'), u'#'], 102 single_selection = True, 103 #new_callback = edit, 104 #edit_callback = edit, 105 delete_callback = delete, 106 refresh_callback = refresh, 107 middle_extra_button = ( 108 _('Data packs'), 109 _('Browse and install billing catalog (schedule of fees) data packs'), 110 manage_data_packs 111 ), 112 right_extra_button = ( 113 _('Catalogs (WWW)'), 114 _('Browse billing catalogs (schedules of fees) on the web'), 115 browse_catalogs 116 ), 117 list_tooltip_callback = get_tooltip 118 ) 119 120 #================================================================
121 -class cBillablePhraseWheel(gmPhraseWheel.cPhraseWheel):
122
123 - def __init__(self, *args, **kwargs):
124 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 125 query = u""" 126 SELECT -- DISTINCT ON (label) 127 r_vb.pk_billable 128 AS data, 129 r_vb.billable_code || ': ' || r_vb.billable_description || ' (' || r_vb.catalog_short || ' - ' || r_vb.catalog_version || ')' 130 AS list_label, 131 r_vb.billable_code || ' (' || r_vb.catalog_short || ' - ' || r_vb.catalog_version || ')' 132 AS field_label 133 FROM 134 ref.v_billables r_vb 135 WHERE 136 r_vb.active 137 AND ( 138 r_vb.billable_code %(fragment_condition)s 139 OR 140 r_vb.billable_description %(fragment_condition)s 141 ) 142 ORDER BY list_label 143 LIMIT 20 144 """ 145 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query) 146 mp.setThresholds(1, 2, 4) 147 self.matcher = mp
148 #------------------------------------------------------------
149 - def _data2instance(self):
150 return gmBilling.cBillable(aPK_obj = self._data.values()[0]['data'])
151 #------------------------------------------------------------
152 - def _get_data_tooltip(self):
153 if self.GetData() is None: 154 return None 155 billable = gmBilling.cBillable(aPK_obj = self._data.values()[0]['data']) 156 return billable.format()
157 #------------------------------------------------------------
158 - def set_from_instance(self, instance):
159 val = u'%s (%s - %s)' % ( 160 instance['billable_code'], 161 instance['catalog_short'], 162 instance['catalog_version'] 163 ) 164 self.SetText(value = val, data = instance['pk_billable'])
165 #------------------------------------------------------------
166 - def set_from_pk(self, pk):
167 self.set_from_instance(gmBilling.cBillable(aPK_obj = pk))
168 169 #================================================================ 170 # invoice related widgets 171 #----------------------------------------------------------------
172 -def configure_invoice_template(parent=None, with_vat=True):
173 174 if parent is None: 175 parent = wx.GetApp().GetTopWindow() 176 177 template = gmFormWidgets.manage_form_templates ( 178 parent = parent, 179 template_types = ['invoice'] 180 ) 181 182 if template is None: 183 gmDispatcher.send(signal = 'statustext', msg = _('No invoice template configured.'), beep = True) 184 return None 185 186 if template['engine'] != u'L': 187 gmDispatcher.send(signal = 'statustext', msg = _('No invoice template configured.'), beep = True) 188 return None 189 190 if with_vat: 191 option = u'form_templates.invoice_with_vat' 192 else: 193 option = u'form_templates.invoice_no_vat' 194 195 dbcfg = gmCfg.cCfgSQL() 196 dbcfg.set ( 197 workplace = gmSurgery.gmCurrentPractice().active_workplace, 198 option = option, 199 value = u'%s - %s' % (template['name_long'], template['external_version']) 200 ) 201 202 return template
203 #----------------------------------------------------------------
204 -def get_invoice_template(parent=None, with_vat=True):
205 206 dbcfg = gmCfg.cCfgSQL() 207 if with_vat: 208 option = u'form_templates.invoice_with_vat' 209 else: 210 option = u'form_templates.invoice_no_vat' 211 212 template = dbcfg.get2 ( 213 option = option, 214 workplace = gmSurgery.gmCurrentPractice().active_workplace, 215 bias = 'user' 216 ) 217 218 if template is None: 219 template = configure_invoice_template(parent = parent, with_vat = with_vat) 220 if template is None: 221 gmGuiHelpers.gm_show_error ( 222 aMessage = _('There is no invoice template configured.'), 223 aTitle = _('Getting invoice template') 224 ) 225 return None 226 else: 227 try: 228 name, ver = template.split(u' - ') 229 except: 230 _log.exception('problem splitting invoice template name [%s]', template) 231 gmDispatcher.send(signal = 'statustext', msg = _('Problem loading invoice template.'), beep = True) 232 return None 233 template = gmForms.get_form_template(name_long = name, external_version = ver) 234 if template is None: 235 gmGuiHelpers.gm_show_error ( 236 aMessage = _('Cannot load invoice template [%s - %s]') % (name, ver), 237 aTitle = _('Getting invoice template') 238 ) 239 return None 240 241 return template
242 243 #================================================================ 244 # per-patient bill related widgets 245 #----------------------------------------------------------------
246 -def edit_bill(parent=None, bill=None, single_entry=False):
247 248 if bill is None: 249 # manually creating bills is not yet supported 250 return 251 252 ea = cBillEAPnl(parent = parent, id = -1) 253 ea.data = bill 254 ea.mode = gmTools.coalesce(bill, 'new', 'edit') 255 dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = single_entry) 256 dlg.SetTitle(gmTools.coalesce(bill, _('Adding new bill'), _('Editing bill'))) 257 if dlg.ShowModal() == wx.ID_OK: 258 dlg.Destroy() 259 return True 260 dlg.Destroy() 261 return False
262 #----------------------------------------------------------------
263 -def create_bill_from_items(bill_items=None):
264 265 if len(bill_items) == 0: 266 return None 267 268 item = bill_items[0] 269 currency = item['currency'] 270 vat = item['vat_multiplier'] 271 pat = item['pk_patient'] 272 273 # check item consistency 274 has_errors = False 275 for item in bill_items: 276 if (item['currency'] != currency) or ( 277 item['vat_multiplier'] != vat) or ( 278 item['pk_patient'] != pat 279 ): 280 msg = _( 281 'All items to be included with a bill must\n' 282 'coincide on currency, VAT, and patient.\n' 283 '\n' 284 'This item does not:\n' 285 '\n' 286 '%s\n' 287 ) % item.format() 288 has_errors = True 289 290 if item['pk_bill'] is not None: 291 msg = _( 292 'This item is already invoiced:\n' 293 '\n' 294 '%s\n' 295 '\n' 296 'Cannot put it on a second bill.' 297 ) % item.format() 298 has_errors = True 299 300 if has_errors: 301 gmGuiHelpers.gm_show_warning(aTitle = _('Checking invoice items'), aMessage = msg) 302 return None 303 304 # create bill 305 bill = gmBilling.create_bill(invoice_id = gmBilling.get_invoice_id(pk_patient = pat)) 306 _log.info('created bill [%s]', bill['invoice_id']) 307 bill.add_items(items = bill_items) 308 bill.set_missing_address_from_default() 309 310 return bill
311 #----------------------------------------------------------------
312 -def create_invoice_from_bill(parent = None, bill=None, print_it=False, keep_a_copy=True):
313 314 if None in [ bill['close_date'], bill['pk_receiver_address'] ]: 315 edit_bill(parent = parent, bill = bill, single_entry = True) 316 # cannot invoice open bills 317 if bill['close_date'] is None: 318 _log.error('cannot create invoice from bill, bill not closed') 319 gmGuiHelpers.gm_show_warning ( 320 aTitle = _('Creating invoice'), 321 aMessage = _( 322 'Cannot create invoice from bill.\n' 323 '\n' 324 'The bill is not closed.' 325 ) 326 ) 327 return False 328 # cannot create invoice if no receiver address 329 if bill['pk_receiver_address'] is None: 330 _log.error('cannot create invoice from bill, lacking receiver address') 331 gmGuiHelpers.gm_show_warning ( 332 aTitle = _('Creating invoice'), 333 aMessage = _( 334 'Cannot create invoice from bill.\n' 335 '\n' 336 'There is no receiver address.' 337 ) 338 ) 339 return False 340 341 # find template 342 template = get_invoice_template(parent = parent, with_vat = bill['apply_vat']) 343 if template is None: 344 gmGuiHelpers.gm_show_warning ( 345 aTitle = _('Creating invoice'), 346 aMessage = _( 347 'Cannot create invoice from bill\n' 348 'without an invoice template.' 349 ) 350 ) 351 return False 352 353 # process template 354 try: 355 invoice = template.instantiate() 356 except KeyError: 357 _log.exception('cannot instantiate invoice template [%s]', template) 358 gmGuiHelpers.gm_show_error ( 359 aMessage = _('Invalid invoice template [%s - %s (%s)]') % (name, ver, template['engine']), 360 aTitle = _('Printing medication list') 361 ) 362 return False 363 364 ph = gmMacro.gmPlaceholderHandler() 365 #ph.debug = True 366 ph.set_cache_value('bill', bill) 367 invoice.substitute_placeholders(data_source = ph) 368 ph.unset_cache_value('bill') 369 pdf_name = invoice.generate_output() 370 if pdf_name is None: 371 gmGuiHelpers.gm_show_error ( 372 aMessage = _('Error generating invoice PDF.'), 373 aTitle = _('Creating invoice') 374 ) 375 return False 376 377 # keep a copy 378 if keep_a_copy: 379 files2import = [] 380 files2import.extend(invoice.final_output_filenames) 381 files2import.extend(invoice.re_editable_filenames) 382 doc = gmDocumentWidgets.save_files_as_new_document ( 383 parent = parent, 384 filenames = files2import, 385 document_type = template['instance_type'], 386 review_as_normal = True, 387 reference = bill['invoice_id'] 388 ) 389 bill['pk_doc'] = doc['pk_doc'] 390 bill.save() 391 392 if not print_it: 393 return True 394 395 # print template 396 printed = gmPrinting.print_files(filenames = [pdf_name], jobtype = 'invoice') 397 if not printed: 398 gmGuiHelpers.gm_show_error ( 399 aMessage = _('Error printing the invoice.'), 400 aTitle = _('Printing invoice') 401 ) 402 return True 403 404 return True
405 406 #----------------------------------------------------------------
407 -def delete_bill(parent=None, bill=None):
408 409 if parent is None: 410 parent = wx.GetApp().GetTopWindow() 411 412 dlg = gmGuiHelpers.c3ButtonQuestionDlg ( 413 parent, -1, 414 caption = _('Deleting bill'), 415 question = _( 416 'When deleting the bill [%s]\n' 417 'do you want to keep its items (effectively \"unbilling\" them)\n' 418 'or do you want to also delete the bill items from the patient ?\n' 419 ) % bill['invoice_id'], 420 button_defs = [ 421 {'label': _('Delete + keep'), 'tooltip': _('Delete the bill but keep ("unbill") its items.'), 'default': True}, 422 {'label': _('Delete all'), 'tooltip': _('Delete both the bill and its items from the patient.')} 423 ], 424 show_checkbox = True, 425 checkbox_msg = _('Also remove invoice PDF'), 426 checkbox_tooltip = _('Also remove the invoice PDF from the document archive (because it will not correspond to the bill anymore).') 427 ) 428 button_pressed = dlg.ShowModal() 429 delete_invoice = dlg.checkbox_is_checked() 430 dlg.Destroy() 431 432 if button_pressed == wx.ID_CANCEL: 433 return False 434 435 if button_pressed == wx.ID_YES: 436 for item in bill.bill_items: 437 item['pk_bill'] = None 438 item.save() 439 440 if button_pressed == wx.ID_NO: 441 for item in bill.bill_items: 442 item['pk_bill'] = None 443 item.save() 444 gmBilling.delete_bill_item(pk_bill_item = item['pk_bill_item']) 445 446 if delete_invoice: 447 if bill['pk_doc'] is not None: 448 gmDocuments.delete_document ( 449 document_id = bill['pk_doc'], 450 encounter_id = gmPerson.cPatient(aPK_obj = bill['pk_patient']).emr.active_encounter['pk_encounter'] 451 ) 452 453 return gmBilling.delete_bill(pk_bill = bill['pk_bill'])
454 455 #----------------------------------------------------------------
456 -def remove_items_from_bill(parent=None, bill=None):
457 458 if bill is None: 459 return False 460 461 list_data = bill.bill_items 462 if len(list_data) == 0: 463 return False 464 465 if parent is None: 466 parent = wx.GetApp().GetTopWindow() 467 468 list_items = [ [ 469 gmDateTime.pydt_strftime(b['date_to_bill'], '%x', accuracy = gmDateTime.acc_days), 470 b['unit_count'], 471 u'%s: %s%s' % (b['billable_code'], b['billable_description'], gmTools.coalesce(b['item_detail'], u'', u' - %s')), 472 u'%s %s (%s %s %s%s%s)' % ( 473 b['total_amount'], 474 b['currency'], 475 b['unit_count'], 476 gmTools.u_multiply, 477 b['net_amount_per_unit'], 478 gmTools.u_multiply, 479 b['amount_multiplier'] 480 ), 481 u'%s %s (%s%%)' % ( 482 b['vat'], 483 b['currency'], 484 b['vat_multiplier'] * 100 485 ), 486 u'%s (%s)' % (b['catalog_short'], b['catalog_version']), 487 b['pk_bill_item'] 488 ] for b in list_data ] 489 490 msg = _('Select the items you want to remove from bill [%s]:\n') % bill['invoice_id'] 491 items2remove = gmListWidgets.get_choices_from_list ( 492 parent = parent, 493 msg = msg, 494 caption = _('Removing items from bill'), 495 columns = [_('Date'), _('Count'), _('Description'), _('Value'), _('VAT'), _('Catalog'), u'#'], 496 single_selection = False, 497 choices = list_items, 498 data = list_data 499 ) 500 501 if items2remove is None: 502 return False 503 504 dlg = gmGuiHelpers.c3ButtonQuestionDlg ( 505 parent, -1, 506 caption = _('Removing items from bill'), 507 question = _( 508 '%s items selected from bill [%s]\n' 509 '\n' 510 'Do you want to only remove the selected items\n' 511 'from the bill ("unbill" them) or do you want\n' 512 'to delete them entirely from the patient ?\n' 513 '\n' 514 'Note that neither action is reversible.' 515 ) % ( 516 len(items2remove), 517 bill['invoice_id'] 518 ), 519 button_defs = [ 520 {'label': _('"Unbill"'), 'tooltip': _('Only "unbill" items (remove from bill but do not delete from patient).'), 'default': True}, 521 {'label': _('Delete'), 'tooltip': _('Completely delete items from the patient.')} 522 ], 523 show_checkbox = True, 524 checkbox_msg = _('Also remove invoice PDF'), 525 checkbox_tooltip = _('Also remove the invoice PDF from the document archive (because it will not correspond to the bill anymore).') 526 ) 527 button_pressed = dlg.ShowModal() 528 delete_invoice = dlg.checkbox_is_checked() 529 dlg.Destroy() 530 531 if button_pressed == wx.ID_CANCEL: 532 return False 533 534 # remember this because unlinking/deleting the items 535 # will remove the patient PK from the bill 536 pk_patient = bill['pk_patient'] 537 538 for item in items2remove: 539 item['pk_bill'] = None 540 item.save() 541 if button_pressed == wx.ID_NO: 542 gmBilling.delete_bill_item(pk_bill_item = item['pk_bill_item']) 543 544 if delete_invoice: 545 if bill['pk_doc'] is not None: 546 gmDocuments.delete_document ( 547 document_id = bill['pk_doc'], 548 encounter_id = gmPerson.cPatient(aPK_obj = pk_patient).emr.active_encounter['pk_encounter'] 549 ) 550 551 # delete bill, too, if empty 552 if len(bill.bill_items) == 0: 553 gmBilling.delete_bill(pk_bill = bill['pk_bill']) 554 555 return True
556 #----------------------------------------------------------------
557 -def manage_bills(parent=None, patient=None):
558 559 if parent is None: 560 parent = wx.GetApp().GetTopWindow() 561 562 #------------------------------------------------------------ 563 def show_pdf(bill): 564 if bill is None: 565 return False 566 567 # find invoice 568 invoice = bill.invoice 569 if invoice is not None: 570 success, msg = invoice.parts[-1].display_via_mime() 571 if not success: 572 gmGuiHelpers.gm_show_error(aMessage = msg, aTitle = _('Displaying invoice')) 573 return False 574 575 # create it ? 576 create_it = gmGuiHelpers.gm_show_question ( 577 title = _('Displaying invoice'), 578 question = _( 579 'Cannot find an existing\n' 580 'invoice PDF for this bill.\n' 581 '\n' 582 'Do you want to create one ?' 583 ), 584 ) 585 if not create_it: 586 return False 587 588 # prepare invoicing 589 if not bill.set_missing_address_from_default(): 590 gmGuiHelpers.gm_show_warning ( 591 aTitle = _('Creating invoice'), 592 aMessage = _( 593 'There is no pre-configured billing address.\n' 594 '\n' 595 'Select the address you want to send the bill to.' 596 ) 597 ) 598 edit_bill(parent = parent, bill = bill, single_entry = True) 599 if bill['pk_receiver_address'] is None: 600 return False 601 if bill['close_date'] is None: 602 bill['close_date'] = gmDateTime.pydt_now_here() 603 bill.save() 604 605 return create_invoice_from_bill(parent = parent, bill = bill, print_it = True, keep_a_copy = True)
606 #------------------------------------------------------------ 607 def edit(bill): 608 return edit_bill(parent = parent, bill = bill, single_entry = True) 609 #------------------------------------------------------------ 610 def delete(bill): 611 return delete_bill(parent = parent, bill = bill) 612 #------------------------------------------------------------ 613 def remove_items(bill): 614 return remove_items_from_bill(parent = parent, bill = bill) 615 #------------------------------------------------------------ 616 def get_tooltip(item): 617 if item is None: 618 return None 619 return item.format() 620 #------------------------------------------------------------ 621 def refresh(lctrl): 622 if patient is None: 623 bills = gmBilling.get_bills() 624 else: 625 bills = gmBilling.get_bills(pk_patient = patient.ID) 626 items = [] 627 for b in bills: 628 if b['close_date'] is None: 629 close_date = _('<open>') 630 else: 631 close_date = gmDateTime.pydt_strftime(b['close_date'], '%Y %b %d') 632 if b['total_amount'] is None: 633 amount = _('no items on bill') 634 else: 635 amount = gmTools.bool2subst ( 636 b['apply_vat'], 637 _('%s %s (with %s%% VAT)') % (b['total_amount_with_vat'], b['currency'], b['percent_vat']), 638 u'%s %s' % (b['total_amount'], b['currency']) 639 ) 640 items.append ([ 641 close_date, 642 b['invoice_id'], 643 amount 644 ]) 645 lctrl.set_string_items(items) 646 lctrl.set_data(bills) 647 #------------------------------------------------------------ 648 return gmListWidgets.get_choices_from_list ( 649 parent = parent, 650 caption = _('Showing bills.'), 651 columns = [_('Close date'), _('Invoice ID'), _('Value')], 652 single_selection = True, 653 edit_callback = edit, 654 delete_callback = delete, 655 refresh_callback = refresh, 656 middle_extra_button = ( 657 u'PDF', 658 _('Create if necessary, and show the corresponding invoice PDF'), 659 show_pdf 660 ), 661 right_extra_button = ( 662 _('Unbill'), 663 _('Select and remove items from a bill.'), 664 remove_items 665 ), 666 list_tooltip_callback = get_tooltip 667 ) 668 669 #---------------------------------------------------------------- 670 from Gnumed.wxGladeWidgets import wxgBillEAPnl 671
672 -class cBillEAPnl(wxgBillEAPnl.wxgBillEAPnl, gmEditArea.cGenericEditAreaMixin):
673
674 - def __init__(self, *args, **kwargs):
675 676 try: 677 data = kwargs['bill'] 678 del kwargs['bill'] 679 except KeyError: 680 data = None 681 682 wxgBillEAPnl.wxgBillEAPnl.__init__(self, *args, **kwargs) 683 gmEditArea.cGenericEditAreaMixin.__init__(self) 684 685 self.mode = 'new' 686 self.data = data 687 if data is not None: 688 self.mode = 'edit'
689 690 # self.__init_ui() 691 #---------------------------------------------------------------- 692 # def __init_ui(self): 693 #---------------------------------------------------------------- 694 # generic Edit Area mixin API 695 #----------------------------------------------------------------
696 - def _valid_for_save(self):
697 validity = True 698 699 # flag but do not count as wrong 700 if not self._PRW_close_date.is_valid_timestamp(allow_empty = False): 701 self._PRW_close_date.SetFocus() 702 703 return validity
704 #----------------------------------------------------------------
705 - def _save_as_new(self):
706 # not intended to be used 707 return False
708 #----------------------------------------------------------------
709 - def _save_as_update(self):
710 self.data['close_date'] = self._PRW_close_date.GetData() 711 self.data['apply_vat'] = self._CHBOX_vat_applies.GetValue() 712 self.data.save() 713 return True
714 #----------------------------------------------------------------
715 - def _refresh_as_new(self):
716 pass # not used
717 #----------------------------------------------------------------
719 self._refresh_as_new()
720 #----------------------------------------------------------------
721 - def _refresh_from_existing(self):
722 self._TCTRL_invoice_id.SetValue(self.data['invoice_id']) 723 self._PRW_close_date.SetText(data = self.data['close_date']) 724 725 self.data.set_missing_address_from_default() 726 if self.data['pk_receiver_address'] is None: 727 self._TCTRL_address.SetValue(u'') 728 else: 729 adr = self.data.address 730 self._TCTRL_address.SetValue(adr.format(single_line = True, show_type = False)) 731 732 self._TCTRL_value.SetValue(u'%s %s' % ( 733 self.data['total_amount'], 734 self.data['currency'] 735 )) 736 self._CHBOX_vat_applies.SetValue(self.data['apply_vat']) 737 self._CHBOX_vat_applies.SetLabel(_('&VAT applies (%s%%)') % self.data['percent_vat']) 738 if self.data['apply_vat']: 739 self._TCTRL_value_with_vat.SetValue(u'%s %s %s %s %s %s %s' % ( 740 gmTools.u_corresponds_to, 741 self.data['total_vat'], 742 self.data['currency'], 743 gmTools.u_right_arrow, 744 gmTools.u_sum, 745 self.data['total_amount_with_vat'], 746 self.data['currency'] 747 )) 748 else: 749 self._TCTRL_value_with_vat.SetValue(u'') 750 751 self._PRW_close_date.SetFocus()
752 #---------------------------------------------------------------- 753 # event handling 754 #----------------------------------------------------------------
755 - def _on_vat_applies_box_checked(self, event):
756 if self._CHBOX_vat_applies.GetValue(): 757 self._TCTRL_value_with_vat.SetValue(u'%s %s %s %s %s %s %s' % ( 758 gmTools.u_corresponds_to, 759 self.data['total_vat'], 760 self.data['currency'], 761 gmTools.u_right_arrow, 762 gmTools.u_sum, 763 self.data['total_amount_with_vat'], 764 self.data['currency'] 765 )) 766 return 767 self._TCTRL_value_with_vat.SetValue(u'')
768 #----------------------------------------------------------------
769 - def _on_select_address_button_pressed(self, event):
770 adr = gmPersonContactWidgets.select_address ( 771 missing = _('billing'), 772 person = gmPerson.cIdentity(aPK_obj = self.data['pk_patient']) 773 ) 774 if adr is None: 775 gmGuiHelpers.gm_show_info ( 776 aTitle = _('Selecting address'), 777 aMessage = _('GNUmed does not know any addresses for this patient.') 778 ) 779 return 780 self.data['pk_receiver_address'] = adr['pk_lnk_person_org_address'] 781 self.data.save() 782 self._TCTRL_address.SetValue(adr.format(single_line = True, show_type = False))
783 784 #================================================================ 785 # per-patient bill items related widgets 786 #----------------------------------------------------------------
787 -def edit_bill_item(parent=None, bill_item=None, single_entry=False):
788 789 if bill_item is not None: 790 if bill_item.is_in_use: 791 gmDispatcher.send(signal = 'statustext', msg = _('Cannot edit already invoiced bill item.'), beep = True) 792 return False 793 794 ea = cBillItemEAPnl(parent = parent, id = -1) 795 ea.data = bill_item 796 ea.mode = gmTools.coalesce(bill_item, 'new', 'edit') 797 dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = single_entry) 798 dlg.SetTitle(gmTools.coalesce(bill_item, _('Adding new bill item'), _('Editing bill item'))) 799 if dlg.ShowModal() == wx.ID_OK: 800 dlg.Destroy() 801 return True 802 dlg.Destroy() 803 return False
804 #----------------------------------------------------------------
805 -def manage_bill_items(parent=None, pk_patient=None):
806 807 if parent is None: 808 parent = wx.GetApp().GetTopWindow() 809 #------------------------------------------------------------ 810 def edit(item=None): 811 return edit_bill_item(parent = parent, bill_item = item, single_entry = (item is not None))
812 #------------------------------------------------------------ 813 def delete(item): 814 if item.is_in_use is not None: 815 gmDispatcher.send(signal = 'statustext', msg = _('Cannot delete already invoiced bill items.'), beep = True) 816 return False 817 gmBilling.delete_bill_item(pk_bill_item = item['pk_bill_item']) 818 return True 819 #------------------------------------------------------------ 820 def get_tooltip(item): 821 if item is None: 822 return None 823 return item.format() 824 #------------------------------------------------------------ 825 def refresh(lctrl): 826 b_items = gmBilling.get_bill_items(pk_patient = pk_patient) 827 items = [ [ 828 gmDateTime.pydt_strftime(b['date_to_bill'], '%x', accuracy = gmDateTime.acc_days), 829 b['unit_count'], 830 u'%s: %s%s' % (b['billable_code'], b['billable_description'], gmTools.coalesce(b['item_detail'], u'', u' - %s')), 831 b['currency'], 832 u'%s (%s %s %s%s%s)' % ( 833 b['total_amount'], 834 b['unit_count'], 835 gmTools.u_multiply, 836 b['net_amount_per_unit'], 837 gmTools.u_multiply, 838 b['amount_multiplier'] 839 ), 840 u'%s (%s%%)' % ( 841 b['vat'], 842 b['vat_multiplier'] * 100 843 ), 844 u'%s (%s)' % (b['catalog_short'], b['catalog_version']), 845 b['pk_bill_item'] 846 ] for b in b_items ] 847 lctrl.set_string_items(items) 848 lctrl.set_data(b_items) 849 #------------------------------------------------------------ 850 gmListWidgets.get_choices_from_list ( 851 parent = parent, 852 #msg = msg, 853 caption = _('Showing bill items.'), 854 columns = [_('Date'), _('Count'), _('Description'), u'%s$%s%s' % (gmTools.u_euro, gmTools.u_currency_pound, gmTools.u_kanji_yen), _('Value'), _('VAT'), _('Catalog'), u'#'], 855 single_selection = True, 856 new_callback = edit, 857 edit_callback = edit, 858 delete_callback = delete, 859 refresh_callback = refresh, 860 list_tooltip_callback = get_tooltip 861 ) 862 863 #------------------------------------------------------------
864 -class cPersonBillItemsManagerPnl(gmListWidgets.cGenericListManagerPnl):
865 """A list for managing a patient's bill items. 866 867 Does NOT act on/listen to the current patient. 868 """
869 - def __init__(self, *args, **kwargs):
870 871 try: 872 self.__identity = kwargs['identity'] 873 del kwargs['identity'] 874 except KeyError: 875 self.__identity = None 876 877 gmListWidgets.cGenericListManagerPnl.__init__(self, *args, **kwargs) 878 879 self.new_callback = self._add_item 880 self.edit_callback = self._edit_item 881 self.delete_callback = self._del_item 882 self.refresh_callback = self.refresh 883 884 self.__show_non_invoiced_only = True 885 886 self.__init_ui() 887 self.refresh()
888 #-------------------------------------------------------- 889 # external API 890 #--------------------------------------------------------
891 - def refresh(self, *args, **kwargs):
892 if self.__identity is None: 893 self._LCTRL_items.set_string_items() 894 return 895 896 b_items = gmBilling.get_bill_items(pk_patient = self.__identity.ID, non_invoiced_only = self.__show_non_invoiced_only) 897 items = [ [ 898 gmDateTime.pydt_strftime(b['date_to_bill'], '%x', accuracy = gmDateTime.acc_days), 899 b['unit_count'], 900 u'%s: %s%s' % (b['billable_code'], b['billable_description'], gmTools.coalesce(b['item_detail'], u'', u' - %s')), 901 b['currency'], 902 b['total_amount'], 903 u'%s (%s%%)' % ( 904 b['vat'], 905 b['vat_multiplier'] * 100 906 ), 907 u'%s (%s)' % (b['catalog_short'], b['catalog_version']), 908 u'%s %s %s %s %s' % ( 909 b['unit_count'], 910 gmTools.u_multiply, 911 b['net_amount_per_unit'], 912 gmTools.u_multiply, 913 b['amount_multiplier'] 914 ), 915 gmTools.coalesce(b['pk_bill'], gmTools.u_diameter), 916 b['pk_encounter_to_bill'], 917 b['pk_bill_item'] 918 ] for b in b_items ] 919 920 self._LCTRL_items.set_string_items(items = items) 921 self._LCTRL_items.set_column_widths() 922 self._LCTRL_items.set_data(data = b_items)
923 #-------------------------------------------------------- 924 # internal helpers 925 #--------------------------------------------------------
926 - def __init_ui(self):
927 self._LCTRL_items.set_columns(columns = [ 928 _('Charge date'), 929 _('Count'), 930 _('Description'), 931 u'%s$%s%s' % (gmTools.u_euro, gmTools.u_currency_pound, gmTools.u_kanji_yen), 932 _('Value'), 933 _('VAT'), 934 _('Catalog'), 935 _('Count %s Value %s Factor') % (gmTools.u_multiply, gmTools.u_multiply), 936 _('Invoice'), 937 _('Encounter'), 938 u'#' 939 ]) 940 self._LCTRL_items.item_tooltip_callback = self._get_item_tooltip 941 # self.left_extra_button = ( 942 # _('Select pending'), 943 # _('Select non-invoiced (pending) items.'), 944 # self._select_pending_items 945 # ) 946 self.left_extra_button = ( 947 _('Invoice selected items'), 948 _('Create invoice from selected items.'), 949 self._invoice_selected_items 950 ) 951 self.middle_extra_button = ( 952 _('Bills'), 953 _('Browse bills of this patient.'), 954 self._browse_bills 955 ) 956 self.right_extra_button = ( 957 _('Billables'), 958 _('Browse list of billables.'), 959 self._browse_billables 960 )
961 #--------------------------------------------------------
962 - def _add_item(self):
963 return edit_bill_item(parent = self, bill_item = None, single_entry = False)
964 #--------------------------------------------------------
965 - def _edit_item(self, bill_item):
966 return edit_bill_item(parent = self, bill_item = bill_item, single_entry = True)
967 #--------------------------------------------------------
968 - def _del_item(self, item):
969 if item['pk_bill'] is not None: 970 gmDispatcher.send(signal = 'statustext', msg = _('Cannot delete already invoiced bill items.'), beep = True) 971 return False 972 go_ahead = gmGuiHelpers.gm_show_question ( 973 _( 'Do you really want to delete this\n' 974 'bill item from the patient ?'), 975 _('Deleting bill item') 976 ) 977 if not go_ahead: 978 return False 979 gmBilling.delete_bill_item(pk_bill_item = item['pk_bill_item']) 980 return True
981 #--------------------------------------------------------
982 - def _get_item_tooltip(self, item):
983 if item is None: 984 return None 985 return item.format()
986 #--------------------------------------------------------
987 - def _select_pending_items(self, item):
988 pass
989 #--------------------------------------------------------
990 - def _invoice_selected_items(self, item):
991 bill_items = self._LCTRL_items.get_selected_item_data() 992 bill = create_bill_from_items(bill_items) 993 if bill is None: 994 return 995 if bill['pk_receiver_address'] is None: 996 gmGuiHelpers.gm_show_error ( 997 aMessage = _( 998 'Cannot create invoice.\n' 999 '\n' 1000 'No receiver address selected.' 1001 ), 1002 aTitle = _('Creating invoice') 1003 ) 1004 return 1005 if bill['close_date'] is None: 1006 bill['close_date'] = gmDateTime.pydt_now_here() 1007 bill.save() 1008 create_invoice_from_bill(parent = self, bill = bill, print_it = True, keep_a_copy = True)
1009 #--------------------------------------------------------
1010 - def _browse_billables(self, item):
1011 manage_billables(parent = self) 1012 return False
1013 #--------------------------------------------------------
1014 - def _browse_bills(self, item):
1015 manage_bills(parent = self, patient = self.__identity)
1016 #-------------------------------------------------------- 1017 # properties 1018 #--------------------------------------------------------
1019 - def _get_identity(self):
1020 return self.__identity
1021
1022 - def _set_identity(self, identity):
1023 self.__identity = identity 1024 self.refresh()
1025 1026 identity = property(_get_identity, _set_identity) 1027 #--------------------------------------------------------
1029 return self.__show_non_invoiced_only
1030
1031 - def _set_show_non_invoiced_only(self, value):
1032 self.__show_non_invoiced_only = value 1033 self.refresh()
1034 1035 show_non_invoiced_only = property(_get_show_non_invoiced_only, _set_show_non_invoiced_only)
1036 1037 #------------------------------------------------------------ 1038 from Gnumed.wxGladeWidgets import wxgBillItemEAPnl 1039
1040 -class cBillItemEAPnl(wxgBillItemEAPnl.wxgBillItemEAPnl, gmEditArea.cGenericEditAreaMixin):
1041
1042 - def __init__(self, *args, **kwargs):
1043 1044 try: 1045 data = kwargs['bill_item'] 1046 del kwargs['bill_item'] 1047 except KeyError: 1048 data = None 1049 1050 wxgBillItemEAPnl.wxgBillItemEAPnl.__init__(self, *args, **kwargs) 1051 gmEditArea.cGenericEditAreaMixin.__init__(self) 1052 1053 self.mode = 'new' 1054 self.data = data 1055 if data is not None: 1056 self.mode = 'edit' 1057 1058 self.__init_ui()
1059 #----------------------------------------------------------------
1060 - def __init_ui(self):
1061 self._PRW_encounter.set_context(context = 'patient', val = gmPerson.gmCurrentPatient().ID) 1062 self._PRW_billable.add_callback_on_selection(self._on_billable_selected)
1063 #---------------------------------------------------------------- 1064 # generic Edit Area mixin API 1065 #----------------------------------------------------------------
1066 - def _valid_for_save(self):
1067 1068 validity = True 1069 1070 if self._TCTRL_factor.GetValue().strip() == u'': 1071 validity = False 1072 self.display_tctrl_as_valid(tctrl = self._TCTRL_factor, valid = False) 1073 self._TCTRL_factor.SetFocus() 1074 else: 1075 converted, factor = gmTools.input2decimal(self._TCTRL_factor.GetValue()) 1076 if not converted: 1077 validity = False 1078 self.display_tctrl_as_valid(tctrl = self._TCTRL_factor, valid = False) 1079 self._TCTRL_factor.SetFocus() 1080 else: 1081 self.display_tctrl_as_valid(tctrl = self._TCTRL_factor, valid = True) 1082 1083 if self._TCTRL_amount.GetValue().strip() == u'': 1084 validity = False 1085 self.display_tctrl_as_valid(tctrl = self._TCTRL_amount, valid = False) 1086 self._TCTRL_amount.SetFocus() 1087 else: 1088 converted, factor = gmTools.input2decimal(self._TCTRL_amount.GetValue()) 1089 if not converted: 1090 validity = False 1091 self.display_tctrl_as_valid(tctrl = self._TCTRL_amount, valid = False) 1092 self._TCTRL_amount.SetFocus() 1093 else: 1094 self.display_tctrl_as_valid(tctrl = self._TCTRL_amount, valid = True) 1095 1096 if self._TCTRL_count.GetValue().strip() == u'': 1097 validity = False 1098 self.display_tctrl_as_valid(tctrl = self._TCTRL_count, valid = False) 1099 self._TCTRL_count.SetFocus() 1100 else: 1101 converted, factor = gmTools.input2decimal(self._TCTRL_count.GetValue()) 1102 if not converted: 1103 validity = False 1104 self.display_tctrl_as_valid(tctrl = self._TCTRL_count, valid = False) 1105 self._TCTRL_count.SetFocus() 1106 else: 1107 self.display_tctrl_as_valid(tctrl = self._TCTRL_count, valid = True) 1108 1109 if self._PRW_date.is_valid_timestamp(allow_empty = True): 1110 self._PRW_date.display_as_valid(True) 1111 else: 1112 validity = False 1113 self._PRW_date.display_as_valid(False) 1114 self._PRW_date.SetFocus() 1115 1116 if self._PRW_encounter.GetData() is None: 1117 validity = False 1118 self._PRW_encounter.display_as_valid(False) 1119 self._PRW_encounter.SetFocus() 1120 else: 1121 self._PRW_encounter.display_as_valid(True) 1122 1123 if self._PRW_billable.GetData() is None: 1124 validity = False 1125 self._PRW_billable.display_as_valid(False) 1126 self._PRW_billable.SetFocus() 1127 else: 1128 self._PRW_billable.display_as_valid(True) 1129 1130 return validity
1131 #----------------------------------------------------------------
1132 - def _save_as_new(self):
1133 data = gmBilling.create_bill_item ( 1134 pk_encounter = gmPerson.gmCurrentPatient().emr.active_encounter['pk_encounter'], 1135 pk_billable = self._PRW_billable.GetData(), 1136 pk_staff = gmStaff.gmCurrentProvider()['pk_staff'] # should be settable ! 1137 ) 1138 data['raw_date_to_bill'] = self._PRW_date.GetData() 1139 converted, data['unit_count'] = gmTools.input2decimal(self._TCTRL_count.GetValue()) 1140 converted, data['net_amount_per_unit'] = gmTools.input2decimal(self._TCTRL_amount.GetValue()) 1141 converted, data['amount_multiplier'] = gmTools.input2decimal(self._TCTRL_factor.GetValue()) 1142 data['item_detail'] = self._TCTRL_comment.GetValue().strip() 1143 data.save() 1144 1145 self.data = data 1146 return True
1147 #----------------------------------------------------------------
1148 - def _save_as_update(self):
1149 self.data['pk_encounter_to_bill'] = self._PRW_encounter.GetData() 1150 self.data['raw_date_to_bill'] = self._PRW_date.GetData() 1151 converted, self.data['unit_count'] = gmTools.input2decimal(self._TCTRL_count.GetValue()) 1152 converted, self.data['net_amount_per_unit'] = gmTools.input2decimal(self._TCTRL_amount.GetValue()) 1153 converted, self.data['amount_multiplier'] = gmTools.input2decimal(self._TCTRL_factor.GetValue()) 1154 self.data['item_detail'] = self._TCTRL_comment.GetValue().strip() 1155 return self.data.save()
1156 #----------------------------------------------------------------
1157 - def _refresh_as_new(self):
1158 self._PRW_billable.SetText() 1159 self._PRW_encounter.set_from_instance(gmPerson.gmCurrentPatient().emr.active_encounter) 1160 self._PRW_date.SetData() 1161 self._TCTRL_count.SetValue(u'1') 1162 self._TCTRL_amount.SetValue(u'') 1163 self._LBL_currency.SetLabel(gmTools.u_euro) 1164 self._TCTRL_factor.SetValue(u'1') 1165 self._TCTRL_comment.SetValue(u'') 1166 1167 self._PRW_billable.Enable() 1168 self._PRW_billable.SetFocus()
1169 #----------------------------------------------------------------
1171 self._PRW_billable.SetText() 1172 self._TCTRL_count.SetValue(u'1') 1173 self._TCTRL_amount.SetValue(u'') 1174 self._TCTRL_comment.SetValue(u'') 1175 1176 self._PRW_billable.Enable() 1177 self._PRW_billable.SetFocus()
1178 #----------------------------------------------------------------
1179 - def _refresh_from_existing(self):
1180 self._PRW_billable.set_from_pk(self.data['pk_billable']) 1181 self._PRW_encounter.set_from_instance(gmPerson.gmCurrentPatient().emr.active_encounter) 1182 self._PRW_date.SetData(data = self.data['raw_date_to_bill']) 1183 self._TCTRL_count.SetValue(u'%s' % self.data['unit_count']) 1184 self._TCTRL_amount.SetValue(u'%s' % self.data['net_amount_per_unit']) 1185 self._LBL_currency.SetLabel(self.data['currency']) 1186 self._TCTRL_factor.SetValue(u'%s' % self.data['amount_multiplier']) 1187 self._TCTRL_comment.SetValue(gmTools.coalesce(self.data['item_detail'], u'')) 1188 1189 self._PRW_billable.Disable() 1190 self._PRW_date.SetFocus()
1191 #----------------------------------------------------------------
1192 - def _on_billable_selected(self, item):
1193 if item is None: 1194 return 1195 if self._TCTRL_amount.GetValue().strip() != u'': 1196 return 1197 val = u'%s' % self._PRW_billable.GetData(as_instance = True)['raw_amount'] 1198 wx.CallAfter(self._TCTRL_amount.SetValue, val)
1199 1200 #============================================================ 1201 # a plugin for billing 1202 #------------------------------------------------------------ 1203 from Gnumed.wxGladeWidgets import wxgBillingPluginPnl 1204
1205 -class cBillingPluginPnl(wxgBillingPluginPnl.wxgBillingPluginPnl, gmRegetMixin.cRegetOnPaintMixin):
1206 - def __init__(self, *args, **kwargs):
1207 1208 wxgBillingPluginPnl.wxgBillingPluginPnl.__init__(self, *args, **kwargs) 1209 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 1210 self.__register_interests()
1211 #-----------------------------------------------------
1212 - def __reset_ui(self):
1213 self._PNL_bill_items.identity = None 1214 self._CHBOX_show_non_invoiced_only.SetValue(1) 1215 self._PRW_billable.SetText(u'', None) 1216 self._TCTRL_factor.SetValue(u'1.0') 1217 self._TCTRL_factor.Disable() 1218 self._TCTRL_details.SetValue(u'') 1219 self._TCTRL_details.Disable()
1220 #----------------------------------------------------- 1221 # event handling 1222 #-----------------------------------------------------
1223 - def __register_interests(self):
1224 gmDispatcher.connect(signal = u'pre_patient_selection', receiver = self._on_pre_patient_selection) 1225 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection) 1226 1227 gmDispatcher.connect(signal = u'bill_item_mod_db', receiver = self._on_bill_item_modified) 1228 1229 self._PRW_billable.add_callback_on_selection(self._on_billable_selected_in_prw)
1230 #-----------------------------------------------------
1231 - def _on_pre_patient_selection(self):
1232 wx.CallAfter(self.__reset_ui)
1233 #-----------------------------------------------------
1234 - def _on_post_patient_selection(self):
1235 wx.CallAfter(self._schedule_data_reget)
1236 #-----------------------------------------------------
1237 - def _on_bill_item_modified(self):
1238 wx.CallAfter(self._schedule_data_reget)
1239 #-----------------------------------------------------
1241 self._PNL_bill_items.show_non_invoiced_only = self._CHBOX_show_non_invoiced_only.GetValue()
1242 #--------------------------------------------------------
1243 - def _on_insert_bill_item_button_pressed(self, event):
1244 val = self._TCTRL_factor.GetValue().strip() 1245 if val == u'': 1246 factor = 1.0 1247 else: 1248 converted, factor = gmTools.input2decimal(val) 1249 if not converted: 1250 gmGuiHelpers.gm_show_warning ( 1251 _('"Factor" must be a number\n\nCannot insert bill item.'), 1252 _('Inserting bill item') 1253 ) 1254 return False 1255 bill_item = gmBilling.create_bill_item ( 1256 pk_encounter = gmPerson.gmCurrentPatient().emr.active_encounter['pk_encounter'], 1257 pk_billable = self._PRW_billable.GetData(), 1258 pk_staff = gmStaff.gmCurrentProvider()['pk_staff'] 1259 ) 1260 bill_item['amount_multiplier'] = factor 1261 bill_item['item_detail'] = self._TCTRL_details.GetValue() 1262 bill_item.save() 1263 1264 self._TCTRL_details.SetValue(u'') 1265 1266 return True
1267 #--------------------------------------------------------
1268 - def _on_billable_selected_in_prw(self, billable):
1269 if billable is None: 1270 self._TCTRL_factor.Disable() 1271 self._TCTRL_details.Disable() 1272 self._BTN_insert_item.Disable() 1273 else: 1274 self._TCTRL_factor.Enable() 1275 self._TCTRL_details.Enable() 1276 self._BTN_insert_item.Enable()
1277 #----------------------------------------------------- 1278 # reget-on-paint mixin API 1279 #-----------------------------------------------------
1280 - def _populate_with_data(self):
1281 self._PNL_bill_items.identity = gmPerson.gmCurrentPatient() 1282 return True
1283 #============================================================ 1284 # main 1285 #------------------------------------------------------------ 1286 if __name__ == '__main__': 1287 1288 if len(sys.argv) < 2: 1289 sys.exit() 1290 1291 if sys.argv[1] != 'test': 1292 sys.exit() 1293 1294 from Gnumed.pycommon import gmI18N 1295 gmI18N.activate_locale() 1296 gmI18N.install_domain(domain = 'gnumed') 1297 1298 #---------------------------------------- 1299 app = wx.PyWidgetTester(size = (600, 600)) 1300 #app.SetWidget(cATCPhraseWheel, -1) 1301 #app.SetWidget(cSubstancePhraseWheel, -1) 1302 app.MainLoop() 1303