Пример #1
0
    def log_sale_discount(cls, store, sale_number, user_name, discount_value,
                          original_price, new_price):
        """
        Log the discount authorized by an user

        This will log on the event system when a user authorizes a discount
        greater than what is allowed on a sale

        :param store: a store
        :param sale_number: the sale's id that the discount was applied
        :param user_name: the user that authorized the discount
        :param discount_value: the percentage of discount applied
        :param original_price: the original price of product
        :param new_price: the price of product after discount
        """

        description = _(
            u"sale {sale_number}: User {user_name} authorized "
            u"{discount_value} of discount changing the value from "
            u"{original_price} to {new_price}.").format(
                sale_number=sale_number,
                user_name=user_name,
                discount_value=get_formatted_percentage(discount_value),
                original_price=get_formatted_price(original_price,
                                                   symbol=True),
                new_price=get_formatted_price(new_price, symbol=True))

        cls(event_type=cls.TYPE_SALE, description=description, store=store)
Пример #2
0
    def log_sale_discount(cls, store, sale_number, user_name, discount_value,
                          original_price, new_price):
        """
        Log the discount authorized by an user

        This will log on the event system when a user authorizes a discount
        greater than what is allowed on a sale

        :param store: a store
        :param sale_number: the sale's id that the discount was applied
        :param user_name: the user that authorized the discount
        :param discount_value: the percentage of discount applied
        :param original_price: the original price of product
        :param new_price: the price of product after discount
        """

        description = _(u"sale {sale_number}: User {user_name} authorized "
                        u"{discount_value} of discount changing the value from "
                        u"{original_price} to {new_price}.").format(
            sale_number=sale_number,
            user_name=user_name,
            discount_value=get_formatted_percentage(discount_value),
            original_price=get_formatted_price(original_price, symbol=True),
            new_price=get_formatted_price(new_price, symbol=True))

        cls(event_type=cls.TYPE_SALE,
            description=description,
            store=store)
Пример #3
0
    def get_summary_row(self):
        total_sales = len(self._sales)
        if self._total_amount > 0:
            total_percentage = self._total_value * 100 / self._total_payment
            average_sale = self._total_amount / total_sales
        else:
            total_percentage = 0
            average_sale = 0

        sales_label = stoqlib_ngettext('%d sale', '%d sales',
                                       total_sales) % total_sales
        # TODO: Create a better way to add more lines to the summary row
        total_sales_label = get_formatted_price(self._total_amount)
        if self._sales_person:
            total_sales_label += ' (' + _("%s/sale") % (get_formatted_price(
                average_sale, )) + ')'

        summary_row = [
            sales_label, total_sales_label,
            get_formatted_price(self._total_payment),
            get_formatted_percentage(total_percentage),
            get_formatted_price(self._total_value),
            format_quantity(self._total_sold)
        ]
        if not self._sales_person:
            summary_row.insert(1, '')
        return summary_row
Пример #4
0
Файл: sale.py Проект: relsi/stoq
    def get_summary_row(self):
        total_sales = len(self._sales)
        if self._total_amount > 0:
            total_percentage = self._total_value * 100 / self._total_payment
            average_sale = self._total_amount / total_sales
        else:
            total_percentage = 0
            average_sale = 0

        sales_label = stoqlib_ngettext('%d sale', '%d sales',
                                       total_sales) % total_sales
        # TODO: Create a better way to add more lines to the summary row
        total_sales_label = get_formatted_price(self._total_amount)
        if self._sales_person:
            total_sales_label += ' (' + _("%s/sale") % (
                get_formatted_price(average_sale, )) + ')'

        summary_row = [sales_label,
                       total_sales_label,
                       get_formatted_price(self._total_payment),
                       get_formatted_percentage(total_percentage),
                       get_formatted_price(self._total_value),
                       format_quantity(self._total_sold)]
        if not self._sales_person:
            summary_row.insert(1, '')
        return summary_row
Пример #5
0
 def get_row(self, obj):
     data = [unicode(obj.identifier),
             get_formatted_price(obj.get_total_amount()),
             get_formatted_price(obj.get_payment_amount()),
             get_formatted_percentage(obj.commission_percentage),
             get_formatted_price(obj.commission_value),
             format_quantity(obj.quantity_sold())]
     if not self._sales_person:
         data.insert(1, obj.salesperson_name)
     return data
Пример #6
0
Файл: sale.py Проект: relsi/stoq
 def get_row(self, obj):
     data = [unicode(obj.identifier),
             get_formatted_price(obj.total_amount),
             get_formatted_price(obj.payment_amount),
             get_formatted_percentage(obj.commission_percentage),
             get_formatted_price(obj.commission_value),
             format_quantity(obj.quantity_sold)]
     if not self._sales_person:
         data.insert(1, obj.salesperson_name)
     return data
Пример #7
0
 def _setup_table(self):
     total_value = sum([item.value for item in self._payments],
                       Decimal(0))
     total_fee_calc = sum([item.fee_calc for item in self._payments],
                          Decimal(0))
     self.add_summary_by_column(_(u'Value'),
                                get_formatted_price(total_value))
     self.add_summary_by_column(_(u'Fee'),
                                get_formatted_price(total_fee_calc))
     self.add_object_table(self._payments, self.get_columns(),
                           summary_row=self.get_summary_row())
Пример #8
0
    def _update_summary(self, results):
        payments = sales = 0
        sale_ids = set()
        for obj in results:
            payments += obj.payment_amount
            # Each sale may appear more than once in the results (once for each payment)
            if obj.id not in sale_ids:
                # If the sale was returned, Dont include it in the summary
                if not obj.sale_returned:
                    sales += obj.total_amount
                sale_ids.add(obj.id)

        self.payments_label.set_label(_(u'Total payments: %s') % get_formatted_price(payments))
        self.sales_label.set_label(_(u'Total sales: %s') % get_formatted_price(sales))
Пример #9
0
    def _update_summary(self, results):
        payments = sales = 0
        sale_ids = set()
        for obj in results:
            payments += obj.payment_amount
            # Each sale may appear more than once in the results (once for each payment)
            if obj.id not in sale_ids:
                # If the sale was returned, Dont include it in the summary
                if not obj.sale_returned:
                    sales += obj.total_amount
                sale_ids.add(obj.id)

        self.payments_label.set_label(_(u'Total payments: %s') % get_formatted_price(payments))
        self.sales_label.set_label(_(u'Total sales: %s') % get_formatted_price(sales))
Пример #10
0
    def _update_change(self):
        # XXX: The 'validate' signal was not emitted when there's no
        # proxy attaching widget/model. By calling the validate method
        # works as shortcut to emit the signal properly:
        value = self.received_value.validate(force=True)
        if value is ValueUnset:
            value = '0.0'

        sale_amount = (self.wizard.get_total_amount() -
                       self.wizard.get_total_paid())
        change_value = currency(value) - sale_amount
        self.change_value_lbl.set_text(get_formatted_price(change_value))

        # There is some change for the clientchange, but we cannot edit the
        # received value. This means that the client has already paid more than
        # the total sale amount.
        if change_value > 0 and not self.received_value.get_sensitive():
            self.credit_checkbutton.set_visible(True)
            policy = sysparam.get_int('RETURN_POLICY_ON_SALES')
            self.credit_checkbutton.set_sensitive(
                policy == ReturnPolicy.CLIENT_CHOICE)
            self.credit_checkbutton.set_active(
                policy == ReturnPolicy.RETURN_CREDIT)
        else:
            self.credit_checkbutton.set_visible(False)
Пример #11
0
    def get_received_freight(self):
        if not self.receiving_orders:
            return None

        freight_names = PurchaseOrder.freight_types
        freight_type_map = {
            ReceivingInvoice.FREIGHT_FOB_PAYMENT: PurchaseOrder.FREIGHT_FOB,
            ReceivingInvoice.FREIGHT_FOB_INSTALLMENTS: PurchaseOrder.FREIGHT_FOB,
            ReceivingInvoice.FREIGHT_CIF_UNKNOWN: PurchaseOrder.FREIGHT_CIF,
            ReceivingInvoice.FREIGHT_CIF_INVOICE: PurchaseOrder.FREIGHT_CIF
        }
        freight_types = set()

        freight = 0
        for receiving in self.receiving_orders:
            if receiving.receiving_invoice:
                freight += receiving.receiving_invoice.freight_total
            freight_types.add(freight_type_map.get(receiving.freight_type,
                                                   self.order.freight_type))

        freight_value = get_formatted_price(freight)
        if len(freight_types) == 1:
            received_freight = _(u"%s (%s)") % (freight_names[freight_types.pop()],
                                                freight_value)
        else:
            received_freight = _(u'Mixed (%s)') % freight_value
        return received_freight
Пример #12
0
    def get_received_freight(self):
        if not self.receiving_orders:
            return None

        freight_names = PurchaseOrder.freight_types
        freight_type_map = {
            ReceivingOrder.FREIGHT_FOB_PAYMENT: PurchaseOrder.FREIGHT_FOB,
            ReceivingOrder.FREIGHT_FOB_INSTALLMENTS: PurchaseOrder.FREIGHT_FOB,
            ReceivingOrder.FREIGHT_CIF_UNKNOWN: PurchaseOrder.FREIGHT_CIF,
            ReceivingOrder.FREIGHT_CIF_INVOICE: PurchaseOrder.FREIGHT_CIF
        }
        freight_types = []

        freight = 0
        for order in self.receiving_orders:
            freight += order.freight_total

            # If first time used, append to the list of used types
            if freight_type_map[order.freight_type] not in freight_types:
                freight_types.append(freight_type_map[order.freight_type])

        freight_value = get_formatted_price(freight)
        if len(freight_types) == 1:
            received_freight = _(u"%s (%s)") % (
                freight_names[freight_types[0]], freight_value)
        else:
            received_freight = _(u'Mixed (%s)') % freight_value
        return received_freight
Пример #13
0
    def get_received_freight(self):
        if not self.receiving_orders:
            return None

        freight_names = PurchaseOrder.freight_types
        freight_type_map = {
            ReceivingOrder.FREIGHT_FOB_PAYMENT: PurchaseOrder.FREIGHT_FOB,
            ReceivingOrder.FREIGHT_FOB_INSTALLMENTS: PurchaseOrder.FREIGHT_FOB,
            ReceivingOrder.FREIGHT_CIF_UNKNOWN: PurchaseOrder.FREIGHT_CIF,
            ReceivingOrder.FREIGHT_CIF_INVOICE: PurchaseOrder.FREIGHT_CIF,
        }
        freight_types = []

        freight = 0
        for order in self.receiving_orders:
            freight += order.freight_total

            # If first time used, append to the list of used types
            if freight_type_map[order.freight_type] not in freight_types:
                freight_types.append(freight_type_map[order.freight_type])

        freight_value = get_formatted_price(freight)
        if len(freight_types) == 1:
            received_freight = _(u"%s (%s)") % (freight_names[freight_types[0]], freight_value)
        else:
            received_freight = _(u"Mixed (%s)") % freight_value
        return received_freight
Пример #14
0
    def get_received_freight(self):
        if not self.receiving_orders:
            return None

        freight_names = PurchaseOrder.freight_types
        freight_type_map = {
            ReceivingInvoice.FREIGHT_FOB_PAYMENT: PurchaseOrder.FREIGHT_FOB,
            ReceivingInvoice.FREIGHT_FOB_INSTALLMENTS:
            PurchaseOrder.FREIGHT_FOB,
            ReceivingInvoice.FREIGHT_CIF_UNKNOWN: PurchaseOrder.FREIGHT_CIF,
            ReceivingInvoice.FREIGHT_CIF_INVOICE: PurchaseOrder.FREIGHT_CIF
        }
        freight_types = set()

        freight = 0
        for receiving in self.receiving_orders:
            if receiving.receiving_invoice:
                freight += receiving.receiving_invoice.freight_total
            freight_types.add(
                freight_type_map.get(receiving.freight_type,
                                     self.order.freight_type))

        freight_value = get_formatted_price(freight)
        if len(freight_types) == 1:
            received_freight = _(u"%s (%s)") % (
                freight_names[freight_types.pop()], freight_value)
        else:
            received_freight = _(u'Mixed (%s)') % freight_value
        return received_freight
Пример #15
0
    def _update_on_price_label(self):
        if self._sellable.is_on_sale():
            text = _("Currently on sale for %s") % (
                get_formatted_price(self._sellable.on_sale_price), )
        else:
            text = ''

        self.on_sale_lbl.set_text(text)
Пример #16
0
 def purchase_total(self):
     subtotal = self.purchase_subtotal
     total = subtotal - self.discount_value + self.surcharge_value
     if total < 0:
         raise ValueError(_(u'Purchase total can not be lesser than zero'))
     # XXX: Since the purchase_total value must have two digits
     # (at the moment) we need to format the value to a 2-digit number and
     # then convert it to currency data type, because the subtotal value
     # may return a 3-or-more-digit value, depending on COST_PRECISION_DIGITS
     # parameters.
     return currency(get_formatted_price(total))
Пример #17
0
 def purchase_total(self):
     subtotal = self.purchase_subtotal
     total = subtotal - self.discount_value + self.surcharge_value
     if total < 0:
         raise ValueError(_(u'Purchase total can not be lesser than zero'))
     # XXX: Since the purchase_total value must have two digits
     # (at the moment) we need to format the value to a 2-digit number and
     # then convert it to currency data type, because the subtotal value
     # may return a 3-or-more-digit value, depending on COST_PRECISION_DIGITS
     # parameters.
     return currency(get_formatted_price(total))
Пример #18
0
    def _update_change(self):
        # XXX: The 'validate' signal was not emitted when there's no
        # proxy attaching widget/model. By calling the validate method
        # works as shortcut to emit the signal properly:
        value = self.received_value.validate(force=True)
        if value is ValueUnset:
            value = '0.0'

        sale_amount = (self.wizard.get_total_amount() -
                       self.wizard.get_total_paid())
        change_value = currency(value) - sale_amount
        self.change_value_lbl.set_text(get_formatted_price(change_value))
Пример #19
0
    def _update_change(self):
        # XXX: The 'validate' signal was not emitted when there's no
        # proxy attaching widget/model. By calling the validate method
        # works as shortcut to emit the signal properly:
        value = self.received_value.validate(force=True)
        if value is ValueUnset:
            value = '0.0'

        sale_amount = (self.wizard.get_total_amount() -
                       self.wizard.get_total_paid())
        change_value = currency(value) - sale_amount
        self.change_value_lbl.set_text(get_formatted_price(change_value))
Пример #20
0
    def _update_summary(self, results):
        total_quantity = reserved_quantity = total_price = 0
        for obj in results:
            total_quantity += obj.quantity
            reserved_quantity += obj.quantity_decreased
            total_price += obj.total

        self.quantity_label.set_label(_(u'Quantity: %s') %
                                      format_quantity(total_quantity))
        self.reserved_label.set_label(_(u'Delivered: %s') %
                                      format_quantity(reserved_quantity))
        self.total_label.set_label(_(u'Total: %s') %
                                   get_formatted_price(total_price))
Пример #21
0
    def _update_summary(self, results):
        total_quantity = reserved_quantity = total_price = 0
        for obj in results:
            total_quantity += obj.quantity
            reserved_quantity += obj.quantity_decreased
            total_price += obj.total

        self.quantity_label.set_label(
            _(u'Quantity: %s') % format_quantity(total_quantity))
        self.reserved_label.set_label(
            _(u'Delivered: %s') % format_quantity(reserved_quantity))
        self.total_label.set_label(
            _(u'Total: %s') % get_formatted_price(total_price))
Пример #22
0
    def _update_summary(self, results):
        total_quantity = total = 0
        for obj in results:
            total_quantity += obj.quantity
            total += obj.total

        queries, having = self.search.parse_states()
        sale_results = self.store.using(*self.search_spec.tables)
        sale_results = sale_results.find(Count(Sale.id, distinct=True))
        if queries:
            sale_results = sale_results.find(And(*queries))

        sales = sale_results.one()
        items_per_sale = total_quantity / sales if sales > 0 else 0

        self.items_label.set_label(_(u'Sales: %s') % format_quantity(sales))
        self.quantity_label.set_label(
            _(u'Quantity: %s') % format_quantity(total_quantity))
        self.items_per_sale_label.set_label(
            _(u'Items per sale: %s') % format_quantity(items_per_sale))
        self.total_label.set_label(
            _(u'Total: %s') % get_formatted_price(total))
Пример #23
0
    def _update_summary(self, results):
        total_quantity = total = 0
        for obj in results:
            total_quantity += obj.quantity
            total += obj.total

        queries, having = self.search.parse_states()
        sale_results = self.store.using(*self.search_spec.tables)
        sale_results = sale_results.find(Count(Sale.id, distinct=True))
        if queries:
            sale_results = sale_results.find(And(*queries))

        sales = sale_results.one()
        items_per_sale = total_quantity / sales if sales > 0 else 0

        self.items_label.set_label(_(u'Sales: %s') %
                                   format_quantity(sales))
        self.quantity_label.set_label(_(u'Quantity: %s') %
                                      format_quantity(total_quantity))
        self.items_per_sale_label.set_label(_(u'Items per sale: %s') %
                                            format_quantity(items_per_sale))
        self.total_label.set_label(_(u'Total: %s') %
                                   get_formatted_price(total))
Пример #24
0
    def _update_change(self):
        # XXX: The 'validate' signal was not emitted when there's no
        # proxy attaching widget/model. By calling the validate method
        # works as shortcut to emit the signal properly:
        value = self.received_value.validate(force=True)
        if value is ValueUnset:
            value = '0.0'

        sale_amount = (self.wizard.get_total_amount() -
                       self.wizard.get_total_paid())
        change_value = currency(value) - sale_amount
        self.change_value_lbl.set_text(get_formatted_price(change_value))

        # There is some change for the clientchange, but we cannot edit the
        # received value. This means that the client has already paid more than
        # the total sale amount.
        if change_value > 0 and not self.received_value.get_sensitive():
            self.credit_checkbutton.set_visible(True)
            policy = sysparam.get_int('RETURN_POLICY_ON_SALES')
            self.credit_checkbutton.set_sensitive(policy == ReturnPolicy.CLIENT_CHOICE)
            self.credit_checkbutton.set_active(policy == ReturnPolicy.RETURN_CREDIT)
        else:
            self.credit_checkbutton.set_visible(False)
Пример #25
0
 def get_agreed_freight(self):
     freight_names = PurchaseOrder.freight_types
     freight_value = get_formatted_price(self.order.expected_freight)
     return _(u"%s (%s)") % (freight_names[self.order.freight_type],
                             freight_value)
Пример #26
0
 def update_total_sale_amount(self, value):
     if value < 0:
         # Setting this to 0 will make it be considered a change,
         # since the client can't pay a negative amount of money
         value = 0
     self.received_value.set_text(get_formatted_price(value))
Пример #27
0
 def get_subtitle(self):
     total_value = get_formatted_price(self.payment.value)
     return _('Receipt: %s - Value: %s - Date: %s') % (
         self.payment.identifier, get_formatted_price(total_value),
         self.receipt_date.strftime('%x'))
Пример #28
0
    def _show_report(self):
        self._generate_dailymovement_data(self.store)

        # Sale data
        self.sales_list.clear()
        for sale, payments in self.sales.items():
            self.sales_list.append(None, sale)
            for details, values in payments.items():
                value = '%s (%sx)' % (get_formatted_price(values[0]), values[1])
                payment_data = Settable(identifier=None,
                                        salesperson=details[0],
                                        client=details[1],
                                        value=value)
                self.sales_list.append(sale, payment_data)

        # Lonely in payments
        self._show_lonely_payments(self.lonely_in_payments,
                                   self.inpayments_list)

        # Purchase data
        self.purchases_list.clear()
        for purchase, payments in self.purchases.items():
            self.purchases_list.append(None, purchase)
            for payment in payments:
                # TODO Add details refering to Bank, Agency later
                payment_data = Settable(identifier=payment.identifier,
                                        notes=payment.method.get_description())
                self.purchases_list.append(purchase, payment_data)

        # Lonely out payments
        self._show_lonely_payments(self.lonely_out_payments,
                                   self.outpayments_list)

        # Return sales
        self.return_sales_list.clear()
        for sale, payments in self.return_sales.items():
            self.return_sales_list.append(None, sale)
            for payment in payments:
                payment_data = Settable(identifier=payment.identifier,
                                        salesperson=payment.method.get_description(),
                                        client=payment.description,
                                        value=get_formatted_price(payment.value))
                self.return_sales_list.append(sale, payment_data)

        # Supplies
        self.supplies_list.clear()
        self.supplies_list.add_list(self.till_supplies)

        # Removals
        self.removals_list.clear()
        self.removals_list.add_list(self.till_removals)

        # Summary's per payment method data
        self.permethod_list.clear()
        self.model.in_subtotal = self.model.out_subtotal = 0
        self.model.in_credit = self.model.out_credit = currency(0)
        for method in self.method_summary:
            method_data = Settable(method=_(method[0].description),
                                   in_value=method[1],
                                   out_value=method[2])
            self.permethod_list.append(method_data)
            self.model.in_subtotal += method[1]
            self.model.out_subtotal += method[2]
            if method[0].method_name == 'credit':
                self.model.in_credit = currency(method[1])
                self.model.out_credit = currency(method[2])

        self.model.in_subtotal = currency(self.model.in_subtotal)
        self.model.out_subtotal = currency(self.model.out_subtotal)
        self.model.in_total = currency(self.model.in_subtotal -
                                       self.model.in_credit)
        self.model.out_total = currency(self.model.out_subtotal -
                                        self.model.out_credit)

        # Summary's per card provider data
        self.percard_list.clear()
        keys = list(self.card_summary.keys())
        for key in sorted(keys):
            card_summary_data = Settable(provider=key[0] + ' ' + key[1],
                                         income=self.card_summary[key])
            self.percard_list.append(card_summary_data)

        self._update_summary_labels()
Пример #29
0
    def _generate_dailymovement_data(self, store):
        query = And(Payment.status.is_in([Payment.STATUS_PENDING,
                                          Payment.STATUS_PAID]),
                    self._get_query(Payment.open_date, Payment.branch))

        # Keys are the sale objects, and values are lists with all payments
        self.sales = collections.OrderedDict()

        # Keys are the returned sale objects, and values are lists with all payments
        self.return_sales = collections.OrderedDict()
        self.purchases = collections.OrderedDict()

        # lonely input and output payments
        self.lonely_in_payments = []
        self.lonely_out_payments = []

        # values are lists with the first element the summary of the input, and
        # the second the summary of the output
        method_summary = {}
        self.card_summary = {}

        result = store.find(DailyInPaymentView, query)
        for p in result.order_by(Sale.identifier, Payment.identifier):
            if p.sale:
                subtotal = p.sale_subtotal
                total = p.sale.get_total_sale_amount(subtotal)
                salesperson = p.salesperson_name or _('Not Specified')
                client = p.client_name or _('Not Specified')
                sale = DailyMovementSale(identifier=p.sale.identifier,
                                         salesperson=salesperson,
                                         client=client,
                                         branch=p.branch_name,
                                         value=get_formatted_price(total))
                sale_payments = self.sales.setdefault(sale,
                                                      collections.OrderedDict())
                details = ''
                method_desc = p.method.get_description()
                if p.check_data:
                    account = p.check_data.bank_account
                    numbers = sorted(
                        payment.payment_number for payment
                        in p.sale.payments if bool(payment.payment_number))
                    # Ensure that the check numbers are ordered
                    parts = []
                    if account.bank_number:
                        parts.append(_(u'Bank: %s') % account.bank_number)
                    if account.bank_branch:
                        parts.append(_(u'Agency: %s') % account.bank_branch)
                    if account.bank_account:
                        parts.append(_(u'Account: %s') % account.bank_account)
                    if numbers:
                        parts.append(_(u'Numbers: %s') % ', '.join(numbers))
                    details = ' / '.join(parts)

                if p.card_data:
                    if p.card_data.card_type == CreditCardData.TYPE_DEBIT:
                        method_desc += ' ' + _('Debit')
                    else:
                        method_desc += ' ' + _(u'Credit')
                    details = '%s - %s - %s' % (p.card_data.auth,
                                                p.card_data.provider.short_name or '',
                                                p.card_data.device.description or '')

                key = (method_desc, details)
                item = sale_payments.setdefault(key, [0, 0])
                item[0] += p.value
                item[1] += 1

            else:
                self.lonely_in_payments.append(p)

            method_summary.setdefault(p.method, [0, 0])
            method_summary[p.method][0] += p.value
            if p.card_data:
                type_desc = p.card_data.short_desc[p.card_data.card_type]
                key = (p.card_data.provider.short_name, type_desc)
                self.card_summary.setdefault(key, 0)
                self.card_summary[key] += p.value

        result = store.find(DailyOutPaymentView, query)
        for p in result.order_by(Payment.identifier):
            if p.purchase:
                purchase_payments = self.purchases.setdefault(p.purchase, [])
                purchase_payments.append(p)
            elif p.sale:
                subtotal = p.sale_subtotal
                value = p.sale.get_total_sale_amount(subtotal)
                salesperson = p.salesperson_name or _('Not Specified')
                client = p.client_name or _('Not Specified')
                sale = DailyMovementSale(identifier=p.sale.identifier,
                                         salesperson=salesperson,
                                         client=client,
                                         return_date=p.sale.return_date,
                                         branch=p.branch_name,
                                         value=value)
                return_sales_payment = self.return_sales.setdefault(sale, [])
                return_sales_payment.append(p)
            else:
                self.lonely_out_payments.append(p)

            method_summary.setdefault(p.method, [0, 0])
            method_summary[p.method][1] += p.value

        self.method_summary = []
        for method, (in_value, out_value) in method_summary.items():
            self.method_summary.append((method,
                                        in_value,
                                        out_value))
        self.method_summary.sort(key=lambda m: _(m[0].description))

        # Till removals
        query = And(Eq(TillEntry.payment_id, None),
                    self._get_query(TillEntry.date, TillEntry.branch),
                    TillEntry.value < 0)
        self.till_removals = store.find(TillEntry, query)

        # Till supply
        query = And(Eq(TillEntry.payment_id, None),
                    self._get_query(TillEntry.date, TillEntry.branch),
                    TillEntry.value > 0)
        self.till_supplies = store.find(TillEntry, query)
Пример #30
0
    def confirm(self, sale, store, savepoint=None, subtotal=None):
        """Confirms a |sale| on fiscalprinter and database

        If the sale is confirmed, the store will be committed for you.
        There's no need for the callsite to call store.confirm().
        If the sale is not confirmed, for instance the user cancelled the
        sale or there was a problem with the fiscal printer, then the
        store will be rolled back.

        :param sale: the |sale| to be confirmed
        :param trans: a store
        :param savepoint: if specified, a database savepoint name that
            will be used to rollback to if the sale was not confirmed.
        :param subtotal: the total value of all the items in the sale
        """
        # Actually, we are confirming the sale here, so the sale
        # confirmation process will be available to others applications
        # like Till and not only to the POS.
        payments_total = sale.group.get_total_confirmed_value()
        sale_total = sale.get_total_sale_amount()

        payment = get_formatted_price(payments_total)
        amount = get_formatted_price(sale_total)
        msg = _(u"Payment value (%s) is greater than sale's total (%s). "
                "Do you want to confirm it anyway?") % (payment, amount)
        if (sale_total < payments_total and not
            yesno(msg, gtk.RESPONSE_NO, _(u"Confirm Sale"), _(u"Don't Confirm"))):
            return False

        model = run_dialog(ConfirmSaleWizard, self._parent, store, sale,
                           subtotal=subtotal, total_paid=payments_total,
                           current_document=self._current_document)

        if not model:
            CancelPendingPaymentsEvent.emit()
            store.rollback(name=savepoint, close=False)
            return False

        if sale.client and not self.is_customer_identified():
            self.identify_customer(sale.client.person)

        try:
            if not self.totalize(sale):
                store.rollback(name=savepoint, close=False)
                return False

            if not self.setup_payments(sale):
                store.rollback(name=savepoint, close=False)
                return False

            if not self.close(sale, store):
                store.rollback(name=savepoint, close=False)
                return False

            if not self.print_receipts(sale):
                store.rollback(name=savepoint, close=False)
                return False

            # FIXME: This used to be done inside sale.confirm. Maybe it would
            # be better to do a proper error handling
            till = Till.get_current(store)
            assert till
            sale.confirm(till=till)

            # Only finish the transaction after everything passed above.
            store.confirm(model)
        except Exception as e:
            warning(_("An error happened while trying to confirm the sale. "
                      "Cancelling the coupon now..."), str(e))
            self.cancel()
            store.rollback(name=savepoint, close=False)
            return False

        print_cheques_for_payment_group(store, sale.group)

        # Try to print only after the transaction is commited, to prevent
        # losing data if something fails while printing
        group = sale.group
        booklets = list(group.get_payments_by_method_name(u'store_credit'))
        bills = list(group.get_payments_by_method_name(u'bill'))

        if (booklets and
            yesno(_("Do you want to print the booklets for this sale?"),
                  gtk.RESPONSE_YES, _("Print booklets"), _("Don't print"))):
            try:
                print_report(BookletReport, booklets)
            except ReportError:
                warning(_("Could not print booklets"))

        if (bills and BillReport.check_printable(bills) and
            yesno(_("Do you want to print the bills for this sale?"),
                  gtk.RESPONSE_YES, _("Print bills"), _("Don't print"))):
            try:
                print_report(BillReport, bills)
            except ReportError:
                # TRANSLATORS: bills here refers to "boletos" in pt_BR
                warning(_("Could not print bills"))

        return True
Пример #31
0
 def get_subtitle(self):
     total_value = get_formatted_price(self.payment.value)
     return _('Receipt: %s - Value: %s - Date: %s') % (
              self.payment.get_payment_number_str(),
              get_formatted_price(total_value),
              self.receipt_date.strftime('%x'))
Пример #32
0
 def update_total_sale_amount(self, value):
     if value < 0:
         # Setting this to 0 will make it be considered a change,
         # since the client can't pay a negative amount of money
         value = 0
     self.received_value.set_text(get_formatted_price(value))
Пример #33
0
    def confirm(self, sale, store, savepoint=None, subtotal=None):
        """Confirms a |sale| on fiscalprinter and database

        If the sale is confirmed, the store will be committed for you.
        There's no need for the callsite to call store.confirm().
        If the sale is not confirmed, for instance the user cancelled the
        sale or there was a problem with the fiscal printer, then the
        store will be rolled back.

        :param sale: the |sale| to be confirmed
        :param trans: a store
        :param savepoint: if specified, a database savepoint name that
            will be used to rollback to if the sale was not confirmed.
        :param subtotal: the total value of all the items in the sale
        """
        # Actually, we are confirming the sale here, so the sale
        # confirmation process will be available to others applications
        # like Till and not only to the POS.
        payments_total = sale.group.get_total_confirmed_value()
        sale_total = sale.get_total_sale_amount()

        payment = get_formatted_price(payments_total)
        amount = get_formatted_price(sale_total)
        msg = _(u"Payment value (%s) is greater than sale's total (%s). "
                "Do you want to confirm it anyway?") % (payment, amount)
        if (sale_total < payments_total
                and not yesno(msg, gtk.RESPONSE_NO, _(u"Confirm Sale"),
                              _(u"Don't Confirm"))):
            return False

        model = run_dialog(ConfirmSaleWizard,
                           self._parent,
                           store,
                           sale,
                           subtotal=subtotal,
                           total_paid=payments_total)

        if not model:
            CancelPendingPaymentsEvent.emit()
            store.rollback(name=savepoint, close=False)
            return False

        if sale.client and not self.is_customer_identified():
            self.identify_customer(sale.client.person)

        if not self.totalize(sale):
            store.rollback(name=savepoint, close=False)
            return False

        if not self.setup_payments(sale):
            store.rollback(name=savepoint, close=False)
            return False

        if not self.close(sale, store):
            store.rollback(name=savepoint, close=False)
            return False

        # FIXME: This used to be done inside sale.confirm. Maybe it would be
        # better to do a proper error handling
        till = Till.get_current(store)
        assert till

        try:
            sale.confirm(till=till)
        except SellError as err:
            warning(str(err))
            store.rollback(name=savepoint, close=False)
            return False

        if not self.print_receipts(sale):
            warning(_("The sale was cancelled"))
            sale.cancel(force=True)

        print_cheques_for_payment_group(store, sale.group)

        # Only finish the transaction after everything passed above.
        store.confirm(model)

        # Try to print only after the transaction is commited, to prevent
        # losing data if something fails while printing
        group = sale.group
        booklets = list(group.get_payments_by_method_name(u'store_credit'))
        bills = list(group.get_payments_by_method_name(u'bill'))

        if (booklets and yesno(
                _("Do you want to print the booklets for this sale?"),
                gtk.RESPONSE_YES, _("Print booklets"), _("Don't print"))):
            try:
                print_report(BookletReport, booklets)
            except ReportError:
                warning(_("Could not print booklets"))

        if (bills and BillReport.check_printable(bills) and yesno(
                _("Do you want to print the bills for this sale?"),
                gtk.RESPONSE_YES, _("Print bills"), _("Don't print"))):
            try:
                print_report(BillReport, bills)
            except ReportError:
                # TRANSLATORS: bills here refers to "boletos" in pt_BR
                warning(_("Could not print bills"))

        return True
Пример #34
0
 def get_agreed_freight(self):
     freight_names = PurchaseOrder.freight_types
     freight_value = get_formatted_price(self.order.expected_freight)
     return _(u"%s (%s)") % (freight_names[self.order.freight_type], freight_value)