def _setup_clients_widget(self): self._update_sale_client() marker('Filling clients') self.client_gadget = ClientEntryGadget( entry=self.client, store=self.store, initial_value=self.model.client, parent=self.wizard, run_editor=self._run_client_editor) marker('Filled clients')
def _setup_client_widget(self): self.client_gadget = ClientEntryGadget(entry=self.client, store=self.store, initial_value=self.model.client, parent=self)
def _setup_clients_widget(self): self.client.mandatory = True self.client_gadget = ClientEntryGadget(entry=self.client, store=self.store, initial_value=self.model.client, parent=self.wizard)
class SalesPersonStep(BaseMethodSelectionStep, WizardEditorStep): """ An abstract step which allows to define a salesperson, the sale's discount and surcharge, when it is needed. """ gladefile = 'SalesPersonStep' model_type = Sale proxy_widgets = ['salesperson', 'client', 'transporter', 'cost_center'] cfop_widgets = ('cfop', ) def __init__(self, wizard, store, model, payment_group, previous=None): self.pm_slave = None self.payment_group = payment_group BaseMethodSelectionStep.__init__(self) marker("WizardEditorStep.__init__") WizardEditorStep.__init__(self, store, wizard, model, previous=previous) self._update_totals() self.update_discount_and_surcharge() # # Private API # def _update_totals(self): subtotal = self.wizard.get_subtotal() self.subtotal_lbl.update(subtotal) total_paid = self.wizard.get_total_paid() self.total_paid_lbl.update(total_paid) to_pay = self.model.get_total_sale_amount( subtotal=subtotal) - total_paid self.cash_change_slave.update_total_sale_amount(to_pay) self.total_lbl.update(to_pay) def _update_sale_client(self): """Update the sale client based on the informed document If the sale does not have a client yet, and the current_document (informed by the ecf plugin) is set, and a person with the given document exists, that client will be associated with this sale. """ if self.model.client or not self.wizard._current_document: return person = Person.get_by_document(self.store, str(self.wizard._current_document)) if not person: return if person.client: self.model.client = person.client else: self.model.client = Client(store=self.store, person=person) def _setup_clients_widget(self): self._update_sale_client() marker('Filling clients') self.client_gadget = ClientEntryGadget( entry=self.client, store=self.store, initial_value=self.model.client, parent=self.wizard, run_editor=self._run_client_editor) marker('Filled clients') def _run_client_editor(self, store, model, description=None, visual_mode=False): return run_person_role_dialog(ClientEditor, self.wizard, store, model, document=self.wizard._current_document, description=description, visual_mode=visual_mode) def _fill_transporter_combo(self): marker('Filling transporters') transporters = Transporter.get_active_transporters(self.store) items = stoq_api.for_person_combo(transporters) self.transporter.prefill(items) self.transporter.set_sensitive(len(items)) marker('Filled transporters') def _fill_cost_center_combo(self): marker('Filling cost centers') cost_centers = CostCenter.get_active(self.store) # we keep this value because each call to is_empty() is a new sql query # to the database cost_centers_exists = not cost_centers.is_empty() if cost_centers_exists: self.cost_center.prefill( stoq_api.for_combo(cost_centers, attr='name', empty=_('No cost center.'))) self.cost_center.set_visible(cost_centers_exists) self.cost_center_lbl.set_visible(cost_centers_exists) marker('Filled cost centers') def _fill_cfop_combo(self): marker('Filling CFOPs') cfops = CfopData.get_for_sale(self.store) self.cfop.prefill(stoq_api.for_combo(cfops)) marker('Filled CFOPs') # # Public API # def update_discount_and_surcharge(self): marker("update_discount_and_surcharge") # Here we need avoid to reset sale data defined when creating the # Sale in the POS application, i.e, we should not reset the # discount and surcharge if they are already set (this is the # case when one of the parameters, CONFIRM_SALES_ON_TILL or # USE_TRADE_AS_DISCOUNT is enabled). if (not sysparam.get_bool('CONFIRM_SALES_ON_TILL') and not sysparam.get_bool('USE_TRADE_AS_DISCOUNT')): self.model.discount_value = currency(0) self.model.surcharge_value = currency(0) def setup_widgets(self): marker('Setting up widgets') # Only quotes have expire date. self.expire_date.hide() self.expire_label.hide() # Hide client category widgets self.client_category_lbl.hide() self.client_category.hide() # if the NF-e plugin is active, the client is mandantory in this # wizard (in this situation, we have only quote sales). if self.model.status == Sale.STATUS_QUOTE: manager = get_plugin_manager() mandatory_client = manager.is_active('nfe') self.client.set_property('mandatory', mandatory_client) marker('Filling sales persons') salespersons = SalesPerson.get_active_salespersons( self.store, api.get_current_branch(self.store)) self.salesperson.prefill(salespersons) marker('Finished filling sales persons') marker('Read parameter') change_salesperson = sysparam.get_int('ACCEPT_CHANGE_SALESPERSON') if change_salesperson == ChangeSalespersonPolicy.ALLOW: self.salesperson.grab_focus() elif change_salesperson == ChangeSalespersonPolicy.DISALLOW: self.salesperson.set_sensitive(False) elif change_salesperson == ChangeSalespersonPolicy.FORCE_CHOOSE: self.model.salesperson = None self.salesperson.grab_focus() else: raise AssertionError marker('Finished reading parameter') self._setup_clients_widget() self._fill_transporter_combo() self._fill_cost_center_combo() if sysparam.get_bool('ASK_SALES_CFOP'): self._fill_cfop_combo() else: self.cfop_lbl.hide() self.cfop.hide() self.create_cfop.hide() marker('Finished setting up widgets') def _refresh_next(self, validation_value): self.client.validate(force=True) client_valid = self.client.is_valid() self.wizard.refresh_next(validation_value and client_valid) # # WizardStep hooks # def post_init(self): BaseMethodSelectionStep.post_init(self) marker('Entering post_init') if self.wizard.need_create_payment(): self.wizard.payment_group.clear_unused() self.register_validate_function(self._refresh_next) self._update_next_step(self.get_selected_method()) # If there's no salesperson, keep the focus there as it should be # selected first to have a nice flow if (hasattr(self, 'cash_change_slave') and self.model.salesperson is not None): self.cash_change_slave.received_value.grab_focus() self.force_validation() self.data_table.set_focus_chain([ self.salesperson, self.invoice_number_holder, self.client_gadget.box, self.transporter, self.create_transporter, self.cfop, self.create_cfop, ]) marker('Leaving post_init') def setup_slaves(self): marker('Setting up slaves') BaseMethodSelectionStep.setup_slaves(self) marker('Finished parent') self.pm_slave.set_client(self.model.client, total_amount=self.wizard.get_total_to_pay()) marker('Setting discount') self.discount_slave = SaleDiscountSlave(self.store, self.model, self.model_type) if sysparam.get_bool('USE_TRADE_AS_DISCOUNT'): self.subtotal_expander.set_expanded(True) self.discount_slave.discount_value_ck.set_active(True) self.discount_slave.update_sale_discount() marker('Finshed setting up discount') self.discount_slave.connect('discount-changed', self.on_discount_slave_changed) slave_holder = 'discount_surcharge_slave' if self.get_slave(slave_holder): self.detach_slave(slave_holder) self.attach_slave(slave_holder, self.discount_slave) marker('Finished setting up slaves') def setup_proxies(self): marker('Setting up proxies') self.setup_widgets() self.proxy = self.add_proxy(self.model, self.proxy_widgets) if self.model.client: self.client_gadget.set_editable(False) if sysparam.get_bool('ASK_SALES_CFOP'): self.add_proxy(self.model, SalesPersonStep.cfop_widgets) marker('Finished setting up proxies') # # Callbacks # def key_F5(self): self.salesperson.grab_focus() def key_F6(self): self.client.grab_focus() def key_F7(self): self.transporter.grab_focus() def key_F8(self): self.cash_change_slave.received_value.grab_focus() def on_client__content_changed(self, entry): # This gets called before setup_slaves, but we must wait until slaves # are setup correctly if not self.pm_slave: return self.discount_slave.update_max_discount() self.pm_slave.set_client(client=self.model.client, total_amount=self.wizard.get_total_to_pay()) def on_payment_method_changed(self, slave, method): self.force_validation() self._update_next_step(method) def on_client__validate(self, widget, client): if not client: return # this is used to avoid some tests from crashing if self.pm_slave is None: return method = self.pm_slave.get_selected_method() try: client.can_purchase(method, self.get_remaining_value()) except SellError as e: return ValidationError(e) return StockOperationPersonValidationEvent.emit( client.person, type(client)) def on_create_transporter__clicked(self, button): store = api.new_store() transporter = store.fetch(self.model.transporter) model = run_person_role_dialog(TransporterEditor, self.wizard, store, transporter) rv = store.confirm(model) store.close() if rv: self._fill_transporter_combo() model = self.store.fetch(model) self.transporter.select(model) def on_discount_slave_changed(self, slave): self._update_totals() self.client.validate() def on_observations_button__clicked(self, *args): self.store.savepoint('before_run_notes_editor') model = self.model.comments.first() if not model: model = SaleComment(store=self.store, sale=self.model, author=api.get_current_user(self.store)) rv = run_dialog(NoteEditor, self.wizard, self.store, model, 'comment', title=_('Sale observations')) if not rv: self.store.rollback_to_savepoint('before_run_notes_editor') def on_create_cfop__clicked(self, widget): self.store.savepoint('before_run_editor_cfop') cfop = run_dialog(CfopEditor, self.wizard, self.store, None) if cfop: self.cfop.append_item(cfop.get_description(), cfop) self.cfop.select_item_by_data(cfop) else: self.store.rollback_to_savepoint('before_run_editor_cfop') def on_invoice_number__validate(self, widget, value): if not 0 < value <= 999999999: return ValidationError( _("Invoice number must be between 1 and 999999999")) invoice = self.model.invoice branch = self.model.branch if invoice.check_unique_invoice_number_by_branch(value, branch): return ValidationError(_(u'Invoice number already used.')) def on_transporter__validate(self, widget, transporter): return StockOperationPersonValidationEvent.emit( transporter.person, type(transporter))
class StartSaleQuoteStep(WizardEditorStep): gladefile = 'SalesPersonQuoteWizardStep' model_type = Sale sale_widgets = ['client', 'salesperson', 'expire_date', 'client_category'] invoice_widgets = ['operation_nature'] cfop_widgets = ['cfop'] proxy_widgets = sale_widgets + invoice_widgets + cfop_widgets def _setup_widgets(self): # Salesperson combo salespersons = SalesPerson.get_active_salespersons(self.store, api.get_current_branch(self.store)) self.salesperson.prefill(salespersons) change_salesperson = sysparam.get_int('ACCEPT_CHANGE_SALESPERSON') if change_salesperson == ChangeSalespersonPolicy.ALLOW: self.salesperson.grab_focus() elif change_salesperson == ChangeSalespersonPolicy.DISALLOW: self.salesperson.set_sensitive(False) elif change_salesperson == ChangeSalespersonPolicy.FORCE_CHOOSE: self.model.salesperson = None self.salesperson.grab_focus() else: raise AssertionError # CFOP combo if sysparam.get_bool('ASK_SALES_CFOP'): cfops = CfopData.get_for_sale(self.store) self.cfop.prefill(api.for_combo(cfops)) else: self.cfop_lbl.hide() self.cfop.hide() self.create_cfop.hide() self._fill_clients_category_combo() self._setup_clients_widget() self._client_credit_set_visible(bool(self.client.read())) def _client_credit_set_visible(self, visible): if visible and self.model.client: self.client_credit.set_text( self.model.client.credit_account_balance.format(precision=2) ) self.client_credit.set_visible(visible) self.client_credit_lbl.set_visible(visible) def _setup_clients_widget(self): self.client_gadget = ClientEntryGadget( entry=self.client, store=self.store, initial_value=self.model.client, parent=self.wizard) def _fill_clients_category_combo(self): categories = self.store.find(ClientCategory).order_by(ClientCategory.name) self.client_category.prefill(api.for_combo(categories, empty='')) if categories.is_empty(): self.client_category.hide() self.client_category_lbl.hide() def post_init(self): self.toogle_client_details() self.register_validate_function(self.wizard.refresh_next) self.force_validation() def next_step(self): return SaleQuoteItemStep(self.wizard, self, self.store, self.model) def has_previous_step(self): return False def setup_proxies(self): self._setup_widgets() self.sale_proxy = self.add_proxy(self.model, StartSaleQuoteStep.sale_widgets) self.invoice_proxy = self.add_proxy(self.model.invoice, StartSaleQuoteStep.invoice_widgets) if sysparam.get_bool('ASK_SALES_CFOP'): self.add_proxy(self.model, StartSaleQuoteStep.cfop_widgets) expire_delta = sysparam.get_int('EXPIRATION_SALE_QUOTE_DATE') if expire_delta > 0 and not self.model.expire_date: # Only set the expire date if id doesn't already have one. self.expire_date.update(localtoday() + relativedelta(days=expire_delta)) def toogle_client_details(self): client = self.model.client if client and client.status != Client.STATUS_SOLVENT: self.client_gadget.update_edit_button( Gtk.STOCK_DIALOG_WARNING, _("The client is not solvent")) # # Callbacks # def after_client__content_changed(self, widget): # During the setup of client_gadget, the client is changed. So this method is # called before the client_gadget be completely created. # Check if the client_gadget was created to continue setting other widgets. if not hasattr(self, 'client_gadget'): return client = self.model.client self.toogle_client_details() self._client_credit_set_visible(bool(client)) if not client: return self.client_category.select(client.category) def on_expire_date__validate(self, widget, value): # open_date has a seconds precision, so that why we are rounding it to # date here. if value.date() < self.model.open_date.date(): msg = _(u"The expire date must be after the sale open date") return ValidationError(msg) def on_notes_button__clicked(self, *args): self.store.savepoint('before_run_notes_editor') model = self.model.comments.first() if not model: model = SaleComment(store=self.store, sale=self.model, author=api.get_current_user(self.store)) rv = run_dialog(NoteEditor, self.wizard, self.store, model, 'comment', title=_('Additional Information')) if not rv: self.store.rollback_to_savepoint('before_run_notes_editor') def on_create_cfop__clicked(self, widget): self.store.savepoint('before_run_editor_cfop') cfop = run_dialog(CfopEditor, self.wizard, self.store, None) if cfop: self.cfop.append_item(cfop.get_description(), cfop) self.cfop.select_item_by_data(cfop) else: self.store.rollback_to_savepoint('before_run_editor_cfop') def on_client__validate(self, widget, client): return StockOperationPersonValidationEvent.emit(client.person, type(client))