def create_sale(self, id_=None, branch=None, client=None): from stoqlib.domain.sale import Sale from stoqlib.domain.till import Till till = Till.get_current(self.store) if till is None: till = self.create_till() till.open_till() salesperson = self.create_sales_person() group = self.create_payment_group() if client: group.payer = client.person sale = Sale( coupon_id=0, open_date=TransactionTimestamp(), salesperson=salesperson, branch=branch or get_current_branch(self.store), cfop=sysparam(self.store).DEFAULT_SALES_CFOP, group=group, client=client, store=self.store, ) if id_: sale.id = id_ sale.identifier = id_ return sale
def test_default_sales_cfop(self): self._create_examples() group = self.create_payment_group() sale = Sale(coupon_id=123, salesperson=self.salesperson, station=self.current_station, branch=self.branch, group=group, store=self.store) self.assertTrue(self.sparam.compare_object( 'DEFAULT_SALES_CFOP', sale.cfop)) param = self.sparam.get_object(self.store, 'DEFAULT_RECEIVING_CFOP') group = self.create_payment_group() sale = Sale(coupon_id=432, salesperson=self.salesperson, branch=self.branch, group=group, station=self.current_station, cfop=param, store=self.store) self.assertEqual(sale.cfop, param)
def _setup_widgets(self): self.main_dialog.ok_button.set_label(gtk.STOCK_PRINT) if self.model.invoice_number is not None: self.invoice_number.set_sensitive(False) else: last_invoice_number = Sale.get_last_invoice_number(self.store) or 0 self.invoice_number.update(last_invoice_number + 1)
def finish(self): for loan in self.models: for item in loan.loaned_items: original = self.original_items[item] sale_quantity = item.sale_quantity - original.sale_quantity if sale_quantity > 0: self._sold_items.append((item.sellable, sale_quantity, item.price)) if self._create_sale and self._sold_items: user = api.get_current_user(self.store) sale = Sale( store=self.store, # Even if there is more than one loan, they are always from the # same (client, branch) branch=self.models[0].branch, client=self.models[0].client, salesperson=user.person.salesperson, group=PaymentGroup(store=self.store), coupon_id=None, ) for sellable, quantity, price in self._sold_items: sale.add_sellable( sellable, quantity, price, # Quantity was already decreased on loan quantity_decreased=quantity, ) sale.order() info( _("Close loan details..."), _("A sale was created from loan items. You can confirm " "that sale in the Till application later."), ) else: sale = None for model in self.models: model.sync_stock() if model.can_close(): model.close() self.retval = self.models self.close() CloseLoanWizardFinishEvent.emit(self.models, sale, self)
def setup_widgets(self): marker('Setting up widgets') # Only quotes have expire date. self.expire_date.hide() self.expire_label.hide() # Hide operation nature widgets self.operation_nature.hide() self.nature_lbl.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 = self.store.find(SalesPerson) self.salesperson.prefill(api.for_person_combo(salespersons)) marker('Finished filling sales persons') marker('Read parameter') if not sysparam(self.store).ACCEPT_CHANGE_SALESPERSON: self.salesperson.set_sensitive(False) else: self.salesperson.grab_focus() marker('Finished reading parameter') self._fill_clients_combo() self._fill_transporter_combo() self._fill_cost_center_combo() if sysparam(self.store).ASK_SALES_CFOP: self._fill_cfop_combo() else: self.cfop_lbl.hide() self.cfop.hide() self.create_cfop.hide() # the maximum number allowed for an invoice is 999999999. self.invoice_number.set_adjustment( gtk.Adjustment(lower=1, upper=999999999, step_incr=1)) if not self.model.invoice_number: new_invoice_number = Sale.get_last_invoice_number(self.store) + 1 self.invoice_model.invoice_number = new_invoice_number else: new_invoice_number = self.model.invoice_number self.invoice_model.invoice_number = new_invoice_number self.invoice_number.set_sensitive(False) self.invoice_model.original_invoice = new_invoice_number marker('Finished setting up widgets')
def testDefaultSalesCFOP(self): self._create_examples() group = self.create_payment_group() sale = Sale(coupon_id=123, salesperson=self.salesperson, branch=self.branch, group=group, store=self.store) self.assertEqual(sale.cfop, self.sparam.DEFAULT_SALES_CFOP) param = self.sparam.DEFAULT_RECEIVING_CFOP group = self.create_payment_group() sale = Sale(coupon_id=432, salesperson=self.salesperson, branch=self.branch, group=group, cfop=param, store=self.store) self.assertEquals(sale.cfop, param)
def _create_sale(self, store): user = api.get_current_user(store) branch = api.get_current_branch(store) salesperson = user.person.salesperson cfop_id = api.sysparam.get_object_id('DEFAULT_SALES_CFOP') nature = api.sysparam.get_string('DEFAULT_OPERATION_NATURE') group = PaymentGroup(store=store) sale = Sale( store=store, branch=branch, salesperson=salesperson, group=group, cfop_id=cfop_id, coupon_id=None, operation_nature=nature) if self._delivery: sale.client = store.fetch(self._delivery.client) sale.storeporter = store.fetch(self._delivery.transporter) delivery = Delivery( store=store, address=store.fetch(self._delivery.address), transporter=store.fetch(self._delivery.transporter), ) else: delivery = None sale.client = self._suggested_client for fake_sale_item in self.sale_items: sale_item = sale.add_sellable( store.fetch(fake_sale_item.sellable), price=fake_sale_item.price, quantity=fake_sale_item.quantity, quantity_decreased=fake_sale_item.quantity_decreased, batch=store.fetch(fake_sale_item.batch)) sale_item.notes = fake_sale_item.notes sale_item.estimated_fix_date = fake_sale_item.estimated_fix_date if delivery and fake_sale_item.deliver: delivery.add_item(sale_item) elif delivery and fake_sale_item == self._delivery_item: delivery.service_item = sale_item return sale
def process_one(self, data, fields, store): person = store.find(Person, name=data.branch_name).one() if person is None or person.branch is None: raise ValueError(u"%s is not a valid branch" % (data.branch_name, )) branch = person.branch station = store.find(BranchStation).any() user = store.find(LoginUser).any() person = store.find(Person, name=data.client_name).one() if person is None or person.client is None: raise ValueError(u"%s is not a valid client" % (data.client_name, )) client = person.client person = store.find(Person, name=data.salesperson_name).one() if person is None or person.sales_person is None: raise ValueError(u"%s is not a valid sales person" % (data.salesperson_name, )) salesperson = person.sales_person group = PaymentGroup(store=store) sale = Sale(client=client, open_date=self.parse_date(data.open_date), coupon_id=int(data.coupon_id), salesperson=salesperson, branch=branch, station=station, cfop_id=sysparam.get_object_id('DEFAULT_SALES_CFOP'), group=group, store=store) total_price = 0 for product in self.parse_multi(Product, data.product_list, store): sale.add_sellable(product.sellable) total_price += product.sellable.price sale.order(user) method = PaymentMethod.get_by_name(store, data.payment_method) method.create_payment(branch, station, Payment.TYPE_IN, group, total_price, due_date=self.parse_date(data.due_date)) sale.confirm(user) # XXX: The payments are paid automatically when a sale is confirmed. # So, we will change all the payment paid_date to the same date # as open_date, then we can test the reports properly. for payment in sale.payments: payment.open_date = sale.open_date if payment.is_paid(): p = store.fetch(payment) p.paid_date = self.parse_date(data.open_date)
def _create_model(self, store): user = api.get_current_user(store) salesperson = user.person.salesperson return Sale(coupon_id=None, status=Sale.STATUS_QUOTE, salesperson=salesperson, branch=api.get_current_branch(store), group=PaymentGroup(store=store), cfop=sysparam(store).DEFAULT_SALES_CFOP, operation_nature=sysparam(store).DEFAULT_OPERATION_NATURE, store=store)
def _create_model(self, store): user = api.get_current_user(store) salesperson = user.person.sales_person sale = Sale(coupon_id=None, status=Sale.STATUS_QUOTE, salesperson=salesperson, branch=api.get_current_branch(store), group=PaymentGroup(store=store), cfop_id=sysparam.get_object_id('DEFAULT_SALES_CFOP'), store=store) sale.invoice.operation_nature = sysparam.get_string('DEFAULT_OPERATION_NATURE') return sale
def create_sale(self, id_=None, branch=None, client=None): from stoqlib.domain.sale import Sale from stoqlib.domain.till import Till till = Till.get_current(self.store) if till is None: till = self.create_till() till.open_till() salesperson = self.create_sales_person() group = self.create_payment_group() if client: group.payer = client.person sale = Sale(coupon_id=0, open_date=TransactionTimestamp(), salesperson=salesperson, branch=branch or get_current_branch(self.store), cfop=sysparam(self.store).DEFAULT_SALES_CFOP, group=group, client=client, store=self.store) if id_: sale.id = id_ sale.identifier = id_ return sale
def process_one(self, data, fields, store): person = store.find(Person, name=data.branch_name).one() if person is None or person.branch is None: raise ValueError(u"%s is not a valid branch" % ( data.branch_name, )) branch = person.branch person = store.find(Person, name=data.client_name).one() if person is None or person.client is None: raise ValueError(u"%s is not a valid client" % ( data.client_name, )) client = person.client person = store.find(Person, name=data.salesperson_name).one() if person is None or person.salesperson is None: raise ValueError(u"%s is not a valid sales person" % ( data.salesperson_name, )) salesperson = person.salesperson group = PaymentGroup(store=store) sale = Sale(client=client, open_date=self.parse_date(data.open_date), coupon_id=int(data.coupon_id), invoice_number=int(data.coupon_id), salesperson=salesperson, branch=branch, cfop=sysparam(store).DEFAULT_SALES_CFOP, group=group, store=store) total_price = 0 for product in self.parse_multi(Product, data.product_list, store): sale.add_sellable(product.sellable) total_price += product.sellable.price sale.order() method = PaymentMethod.get_by_name(store, data.payment_method) method.create_inpayment(group, branch, total_price, self.parse_date(data.due_date)) sale.confirm() #XXX: The payments are paid automatically when a sale is confirmed. # So, we will change all the payment paid_date to the same date # as open_date, then we can test the reports properly. for payment in sale.payments: if payment.is_paid(): p = store.fetch(payment) p.paid_date = self.parse_date(data.open_date)
def _create_examples(self): person = Person(name=u'Jonas', store=self.store) Individual(person=person, store=self.store) role = EmployeeRole(store=self.store, name=u'desenvolvedor') Employee(person=person, store=self.store, role=role) self.salesperson = SalesPerson(person=person, store=self.store) Company(person=person, store=self.store) client = Client(person=person, store=self.store) self.branch = Branch(person=person, store=self.store) group = self.create_payment_group() self.sale = Sale(coupon_id=123, client=client, cfop_id=self.sparam.get_object_id('DEFAULT_SALES_CFOP'), group=group, branch=self.branch, salesperson=self.salesperson, store=self.store) self.storable = self.create_storable()
def finish(self): for loan in self.models: for item in loan.loaned_items: original = self.original_items[item] sale_quantity = item.sale_quantity - original.sale_quantity if sale_quantity > 0: self._sold_items.append( (item.sellable, sale_quantity, item.price)) if self._create_sale and self._sold_items: user = api.get_current_user(self.store) sale = Sale( store=self.store, # Even if there is more than one loan, they are always from the # same (client, branch) branch=self.models[0].branch, station=api.get_current_station(self.store), client=self.models[0].client, salesperson=user.person.sales_person, group=PaymentGroup(store=self.store), coupon_id=None) for sellable, quantity, price in self._sold_items: sale.add_sellable( sellable, quantity, price, # Quantity was already decreased on loan quantity_decreased=quantity) sale.order(user) info( _("Close loan details..."), _("A sale was created from loan items. You can confirm " "that sale in the Till application later.")) else: sale = None for model in self.models: model.sync_stock(api.get_current_user(self.store)) if model.can_close(): model.close() self.retval = self.models self.close() CloseLoanWizardFinishEvent.emit(self.models, sale, self)
def _create_sale(self, store): user = api.get_current_user(store) branch = api.get_current_branch(store) salesperson = user.person.salesperson cfop = api.sysparam(store).DEFAULT_SALES_CFOP group = PaymentGroup(store=store) sale = Sale( store=store, branch=branch, salesperson=salesperson, group=group, cfop=cfop, coupon_id=None, operation_nature=api.sysparam(store).DEFAULT_OPERATION_NATURE) if self._delivery: sale.client = store.fetch(self._delivery.client) sale.storeporter = store.fetch(self._delivery.transporter) delivery = Delivery( store=store, address=store.fetch(self._delivery.address), transporter=store.fetch(self._delivery.transporter), ) else: delivery = None sale.client = self._suggested_client for fake_sale_item in self.sale_items: sale_item = sale.add_sellable( store.fetch(fake_sale_item.sellable), price=fake_sale_item.price, quantity=fake_sale_item.quantity, quantity_decreased=fake_sale_item.quantity_decreased, batch=store.fetch(fake_sale_item.batch)) sale_item.notes = fake_sale_item.notes sale_item.estimated_fix_date = fake_sale_item.estimated_fix_date if delivery and fake_sale_item.deliver: delivery.add_item(sale_item) elif delivery and fake_sale_item == self._delivery_item: delivery.service_item = sale_item return sale
def get_subtitle(self): return _(u'Number: %s - Sale %s on %s') % ( self.order.identifier, Sale.get_status_name(self.order.status), self._get_status_date(self.order.status).strftime('%x'))
def post(self, store): # FIXME: Check branch state and force fail if no override for that product is present. self.ensure_printer() data = request.get_json() client_id = data.get('client_id') products = data['products'] payments = data['payments'] client_category_id = data.get('price_table') document = raw_document(data.get('client_document', '') or '') if document: document = format_document(document) if client_id: client = store.get(Client, client_id) elif document: person = Person.get_by_document(store, document) client = person and person.client else: client = None # Create the sale branch = api.get_current_branch(store) group = PaymentGroup(store=store) user = api.get_current_user(store) sale = Sale( store=store, branch=branch, salesperson=user.person.sales_person, client=client, client_category_id=client_category_id, group=group, open_date=localnow(), coupon_id=None, ) # Add products for p in products: sellable = store.get(Sellable, p['id']) item = sale.add_sellable(sellable, price=currency(p['price']), quantity=decimal.Decimal(p['quantity'])) # XXX: bdil has requested that when there is a special discount, the discount does # not appear on the coupon. Instead, the item wil be sold using the discount price # as the base price. Maybe this should be a parameter somewhere item.base_price = item.price # Add payments sale_total = sale.get_total_sale_amount() money_payment = None payments_total = 0 for p in payments: method_name = p['method'] tef_data = p.get('tef_data', {}) if method_name == 'tef': p['provider'] = tef_data['card_name'] method_name = 'card' method = PaymentMethod.get_by_name(store, method_name) installments = p.get('installments', 1) or 1 due_dates = list(create_date_interval( INTERVALTYPE_MONTH, interval=1, start_date=localnow(), count=installments)) payment_value = currency(p['value']) payments_total += payment_value p_list = method.create_payments( Payment.TYPE_IN, group, branch, payment_value, due_dates) if method.method_name == 'money': # FIXME Frontend should not allow more than one money payment. this can be changed # once https://gitlab.com/stoqtech/private/bdil/issues/75 is fixed? if not money_payment or payment_value > money_payment.value: money_payment = p_list[0] elif method.method_name == 'card': for payment in p_list: card_data = method.operation.get_card_data_by_payment(payment) card_type = p['mode'] # Stoq does not have the voucher comcept, so register it as a debit card. if card_type == 'voucher': card_type = 'debit' device = self._get_card_device(store, 'TEF') provider = self._get_provider(store, p['provider']) if tef_data: card_data.nsu = tef_data['aut_loc_ref'] card_data.auth = tef_data['aut_ext_ref'] card_data.update_card_data(device, provider, card_type, installments) card_data.te.metadata = tef_data # If payments total exceed sale total, we must adjust money payment so that the change is # correctly calculated.. if payments_total > sale_total and money_payment: money_payment.value -= (payments_total - sale_total) assert money_payment.value >= 0 # Confirm the sale group.confirm() sale.order() till = Till.get_last(store) sale.confirm(till) # Fiscal plugins will connect to this event and "do their job" # It's their responsibility to raise an exception in case of # any error, which will then trigger the abort bellow # FIXME: Catch printing errors here and send message to the user. SaleConfirmedRemoteEvent.emit(sale, document) # This will make sure we update any stock or price changes products may # have between sales return True