Beispiel #1
0
    def _create_payment(self):
        group = PaymentGroup()
        group.payer = self.client.person

        method = PaymentMethod.get_by_name(self.store, u'credit')
        branch = api.get_current_branch(self.store)

        if self.model.value < 0:
            payment_type = Payment.TYPE_IN
        else:
            payment_type = Payment.TYPE_OUT

        # Set status to PENDING now, to avoid calling set_pending on
        # on_confirm for payments that shoud not have its status changed.
        payment = Payment(open_date=localtoday(),
                          branch=branch,
                          status=Payment.STATUS_PENDING,
                          description=self.model.description,
                          value=abs(self.model.value),
                          base_value=abs(self.model.value),
                          due_date=localtoday(),
                          method=method,
                          group=group,
                          till=None,
                          category=None,
                          payment_type=payment_type,
                          bill_received=False)
        payment.pay()

        return payment
Beispiel #2
0
    def _create_freight_payment(self):
        store = self.store
        money_method = PaymentMethod.get_by_name(store, u'money')
        # If we have a transporter, the freight payment will be for him
        # (and in another payment group).
        if self.transporter is not None:
            group = PaymentGroup(store=store)
            group.recipient = self.transporter.person
        else:
            group = self.purchase.group

        description = _(u'Freight for purchase %s') % (
                        self.purchase.get_order_number_str(), )
        payment = money_method.create_outpayment(
            group, self.branch, self.freight_total,
            due_date=datetime.datetime.today(),
            description=description)
        payment.set_pending()
        return payment
Beispiel #3
0
    def _create_freight_payment(self):
        store = self.store
        money_method = PaymentMethod.get_by_name(store, u'money')
        # If we have a transporter, the freight payment will be for him
        # (and in another payment group).
        if self.transporter is not None:
            group = PaymentGroup(store=store)
            group.recipient = self.transporter.person
        else:
            group = self.purchase.group

        description = _(u'Freight for purchase %s') % (
            self.purchase.identifier, )
        payment = money_method.create_payment(
            Payment.TYPE_OUT,
            group, self.branch, self.freight_total,
            due_date=localnow(),
            description=description)
        payment.set_pending()
        return payment
Beispiel #4
0
    def _create_receiving_invoice(self):
        # We only let the user get this far if the receivings selected are for the
        # same branch and supplier
        supplier = self.receivings[0].purchase.supplier
        branch_id = self.receivings[0].branch_id

        # If the receiving is for another branch, we need a temporary identifier
        temporary_identifier = None
        if (api.sysparam.get_bool('SYNCHRONIZED_MODE') and
                api.get_current_branch(self.store).id != branch_id):
            temporary_identifier = ReceivingInvoice.get_temporary_identifier(self.store)

        group = PaymentGroup(store=self.store, recipient=supplier.person)
        self.wizard.model = self.model = ReceivingInvoice(
            identifier=temporary_identifier, supplier=supplier, group=group,
            branch_id=branch_id, store=self.store,
            responsible=api.get_current_user(self.store))

        for row in self.receivings:
            self.model.add_receiving(row.order)
Beispiel #5
0
    def create_freight_payment(self, group=None):
        store = self.store
        money_method = PaymentMethod.get_by_name(store, u'money')
        # If we have a transporter, the freight payment will be for him
        if not group:
            if self.transporter:
                recipient = self.transporter.person
            else:
                recipient = self.supplier.person
            group = PaymentGroup(store=store, recipient=recipient)

        description = _(u'Freight for receiving %s') % (self.identifier, )
        payment = money_method.create_payment(Payment.TYPE_OUT,
                                              group,
                                              self.branch,
                                              self.freight_total,
                                              due_date=localnow(),
                                              description=description)
        payment.set_pending()
        return payment
Beispiel #6
0
 def create_model(self, store):
     group = PaymentGroup()
     money = PaymentMethod.get_by_name(store, u'money')
     branch = api.get_current_branch(store)
     # Set status to PENDING now, to avoid calling set_pending on
     # on_confirm for payments that shoud not have its status changed.
     return Payment(store=store,
                    open_date=localtoday().date(),
                    branch=branch,
                    station=api.get_current_station(store),
                    status=Payment.STATUS_PENDING,
                    description=u'',
                    value=currency(0),
                    base_value=currency(0),
                    due_date=None,
                    method=money,
                    group=group,
                    category=None,
                    payment_type=self.payment_type,
                    bill_received=False)
Beispiel #7
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)
Beispiel #8
0
    def _get_purchase_from_quote(self, quote, store):
        quote_purchase = quote.purchase
        real_order = quote_purchase.clone()
        has_selected_items = False
        # add selected items
        for quoted_item in self.quoted_items:
            order = store.fetch(quoted_item.order)
            if order is quote_purchase and quoted_item.selected:
                purchase_item = store.fetch(quoted_item.item).clone()
                purchase_item.order = real_order
                has_selected_items = True

        # override some cloned data
        real_order.group = PaymentGroup(store=store)
        real_order.open_date = localtoday().date()
        real_order.quote_deadline = None
        real_order.status = PurchaseOrder.ORDER_PENDING

        if has_selected_items:
            return real_order
        else:
            store.remove(real_order)
Beispiel #9
0
    def _create_freight_payment(self):
        store = self.store
        money_method = PaymentMethod.get_by_name(store, u'money')
        # If we have a transporter, the freight payment will be for him
        # (and in another payment group).
        purchases = list(self.purchase_orders)
        if len(purchases) == 1 and self.transporter is None:
            group = purchases[0].group
        else:
            if self.transporter:
                recipient = self.transporter.person
            else:
                recipient = self.supplier.person
            group = PaymentGroup(store=store, recipient=recipient)

        description = _(u'Freight for receiving %s') % (self.identifier, )
        payment = money_method.create_payment(Payment.TYPE_OUT,
                                              group,
                                              self.branch,
                                              self.freight_total,
                                              due_date=localnow(),
                                              description=description)
        payment.set_pending()
        return payment
    def process_one(self, data, fields, store):
        person = store.find(Person, name=data.supplier_name).one()
        if person is None or person.supplier is None:
            raise ValueError(u"%s is not a valid supplier" %
                             (data.supplier_name, ))
        supplier = person.supplier

        person = store.find(Person, name=data.transporter_name).one()
        if person is None or person.transporter is None:
            raise ValueError(u"%s is not a valid transporter" %
                             (data.transporter_name, ))
        transporter = person.transporter

        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

        login_user = store.find(LoginUser, username=u'admin').one()
        group = PaymentGroup(store=store)
        purchase = PurchaseOrder(store=store,
                                 status=PurchaseOrder.ORDER_PENDING,
                                 open_date=self.parse_date(data.due_date),
                                 supplier=supplier,
                                 transporter=transporter,
                                 group=group,
                                 responsible=get_current_user(store),
                                 branch=branch)

        for sellable in self.parse_multi(Sellable, data.sellable_list, store):
            if not sellable.product:
                continue
            PurchaseItem(store=store,
                         quantity=int(data.quantity),
                         base_cost=sellable.cost,
                         sellable=sellable,
                         order=purchase)

        method = PaymentMethod.get_by_name(store, data.payment_method)
        method.create_payment(Payment.TYPE_OUT, purchase.group, branch,
                              purchase.purchase_total,
                              self.parse_date(data.due_date))
        purchase.confirm()
        for payment in purchase.payments:
            payment.open_date = purchase.open_date

        receiving_order = ReceivingOrder(responsible=login_user,
                                         supplier=supplier,
                                         invoice_number=int(data.invoice),
                                         transporter=transporter,
                                         branch=branch,
                                         store=store)
        receiving_order.add_purchase(purchase)

        for purchase_item in purchase.get_items():
            ReceivingOrderItem(store=store,
                               cost=purchase_item.sellable.cost,
                               sellable=purchase_item.sellable,
                               quantity=int(data.quantity),
                               purchase_item=purchase_item,
                               receiving_order=receiving_order)
        receiving_order.confirm()
Beispiel #11
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
Beispiel #12
0
 def _create_payment_group(self):
     return PaymentGroup(store=self.store,
                         recipient=self.nfe_supplier.supplier.person,
                         payer=self.branch.person)
Beispiel #13
0
 def create_payment_group(self):
     from stoqlib.domain.payment.group import PaymentGroup
     return PaymentGroup(store=self.store)