Source code for stoqlib.reporting.sale

# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4

##
## Copyright (C) 2005, 2006 Async Open Source <http://www.async.com.br>
## All rights reserved
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., or visit: http://www.gnu.org/.
##
##  Author(s): Stoq Team <stoq-devel@async.com.br>
##
##
""" Sales report implementation """

from stoqlib.database.runtime import get_default_store, get_current_branch
from stoqlib.domain.sale import Sale
from stoqlib.lib.formatters import (get_formatted_price,
                                    get_formatted_percentage,
                                    format_quantity)

from stoqlib.reporting.report import ObjectListReport, HTMLReport, TableReport
from stoqlib.lib.translation import stoqlib_gettext, stoqlib_ngettext

_ = stoqlib_gettext


[docs]class SaleOrderReport(HTMLReport): """Transfer Order receipt This class builds the namespace used in template """ template_filename = 'sale/sale.html' title = _("Sale Order") complete_header = True def __init__(self, filename, order): self.order = order HTMLReport.__init__(self, filename) def _get_status_date(self, status): status_date = {Sale.STATUS_INITIAL: 'open_date', Sale.STATUS_ORDERED: 'open_date', Sale.STATUS_CONFIRMED: 'confirm_date', Sale.STATUS_CANCELLED: 'cancel_date', Sale.STATUS_QUOTE: 'open_date', Sale.STATUS_RETURNED: 'return_date', Sale.STATUS_RENEGOTIATED: 'close_date'} return getattr(self.order, status_date[status])
[docs] def get_person_document(self): client = self.order.client if not client: return u'' individual = client.person.individual if individual is not None: return individual.cpf company = client.person.company if company is not None: return company.cnpj
[docs] 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'))
[docs] def get_namespace(self): return {'status_quote': Sale.STATUS_QUOTE}
[docs]class SalesReport(ObjectListReport): title = _("Sales Report") main_object_name = (_("sale"), _("sales")) filter_format_string = _("with status <u>%s</u>") summary = ['total', 'total_quantity']
[docs]class ReturnedSalesReport(ObjectListReport): title = _("Returned Sales Report")
[docs]class ReturnedItemReport(ObjectListReport): title = _("Returned Items Report")
[docs]class SoldItemsByClientReport(ObjectListReport): title = _("Sales By Client Report")
[docs]class SoldItemsByBranchReport(ObjectListReport): """This report show a list of sold items by branch. For each item it show: product code, product description, branch name, sold quantity and total. """ title = _("Sold Items by Branch Report") summary = ['quantity', 'total'] template_filename = 'sale/sold_items_by_branch.html'
[docs] def reset(self): ObjectListReport.reset(self) self.branch_total = {} self.branch_quantity = {}
[docs] def accumulate(self, row): ObjectListReport.accumulate(self, row) # Total by Branch self.branch_total.setdefault(row.branch_name, 0) self.branch_quantity.setdefault(row.branch_name, 0) self.branch_total[row.branch_name] += row.total self.branch_quantity[row.branch_name] += row.quantity
[docs]class SalesPersonReport(TableReport): title = _("Sales") def __init__(self, filename, payments_list, salesperson, *args, **kwargs): branch = get_current_branch(get_default_store()).get_description() self.payments_list = payments_list self._sales_person = salesperson if salesperson: salesperson_name = salesperson.get_description() singular = _("payment for {salesperson} on branch {branch}").format( salesperson=salesperson_name, branch=branch) plural = _("payments for {salesperson} on branch {branch}").format( salesperson=salesperson_name, branch=branch) else: singular = _("payment on branch %s") % branch plural = _("payments on branch %s") % branch self.main_object_name = (singular, plural) self.landscape = (salesperson is None) TableReport.__init__(self, filename, payments_list, self.title, *args, **kwargs)
[docs] def get_columns(self): columns = [dict(title=_("Sale #"), align='right'), dict(title=_("Sale Total"), align='right'), dict(title=_("Payment Value"), align='right'), dict(title=_("Percentage"), align='right'), dict(title=_("Commission Value"), align='right'), dict(title=_("Items"), align='right')] if not self._sales_person: columns.insert(1, dict(title=_('Name'))) return columns
[docs] 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
[docs] def reset(self): self._sales = set() self._total_amount = 0 self._total_payment = 0 self._total_percentage = 0 self._total_value = 0 self._total_sold = 0
[docs] def accumulate(self, obj): # Count sale value only once if obj.id not in self._sales: if not obj.sale_returned: self._total_amount += obj.total_amount self._total_sold += obj.quantity_sold self._total_payment += obj.payment_amount self._total_value += obj.commission_value # payments_list might have multiples items that refers to the # same sale. This will count the right number of sales. self._sales.add(obj.id)
[docs] 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
[docs]def test(): # pragma no cover from kiwi.ui.objectlist import ObjectList from stoqlib.api import api from stoq.gui.sales import SalesApp from stoqlib.domain.sale import SaleView api.prepare_test() store = api.new_store() class Foo(SalesApp): def __init__(self): pass a = Foo() ol = ObjectList(a.get_columns()) data = store.find(SaleView) r = SalesReport('teste.pdf', ol, list(data)) r.save_html('teste.html') r.save()
if __name__ == '__main__': # pragma no cover test()