Пример #1
0
    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
Пример #2
0
 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)
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
    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)
Пример #6
0
    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')
Пример #7
0
 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)
Пример #8
0
    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')
Пример #9
0
    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
Пример #10
0
    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)
Пример #11
0
    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)
Пример #12
0
    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
Пример #13
0
    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
Пример #14
0
    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)
Пример #15
0
    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()
Пример #16
0
    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)
Пример #17
0
    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
Пример #18
0
Файл: sale.py Проект: relsi/stoq
 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'))
Пример #19
0
 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'))
Пример #20
0
    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