Feat: Sale Fast Food Product by Pizza
This commit is contained in:
parent
2480d43167
commit
c34f782480
@ -1,5 +1,6 @@
|
|||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from . import product, sale, production, invoice, user, report_close_statement
|
from . import (
|
||||||
|
product, sale, production, invoice, user, report_close_statement, report)
|
||||||
|
|
||||||
__all__ = ['register']
|
__all__ = ['register']
|
||||||
|
|
||||||
@ -14,6 +15,8 @@ def register():
|
|||||||
user.User,
|
user.User,
|
||||||
production.Production,
|
production.Production,
|
||||||
report_close_statement.ReportCloseStatementStart,
|
report_close_statement.ReportCloseStatementStart,
|
||||||
|
report.ReportSaleProduct,
|
||||||
|
report.ReportSaleContext,
|
||||||
module='sale_fast_food', type_='model')
|
module='sale_fast_food', type_='model')
|
||||||
Pool.register(
|
Pool.register(
|
||||||
report_close_statement.PrintReportCloseStatement,
|
report_close_statement.PrintReportCloseStatement,
|
||||||
|
151
report.py
Normal file
151
report.py
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
from trytond.model import ModelSQL, ModelView, fields
|
||||||
|
from trytond.pool import Pool
|
||||||
|
from trytond.pyson import If, Eval
|
||||||
|
from sql import Literal, Null
|
||||||
|
from sql.aggregate import Min, Sum
|
||||||
|
from sql.functions import CurrentTimestamp
|
||||||
|
from trytond.transaction import Transaction
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class ReportSaleContext(ModelView):
|
||||||
|
"""Contexto de reportes de miembros de familia"""
|
||||||
|
__name__ = 'sale_fast_food.report.context'
|
||||||
|
|
||||||
|
from_date = fields.Date(
|
||||||
|
"From Date",
|
||||||
|
domain=[
|
||||||
|
If(Eval('to_date') & Eval('from_date'),
|
||||||
|
('from_date', '<=', Eval('to_date')),
|
||||||
|
()),
|
||||||
|
If(Eval('from_date'),
|
||||||
|
('from_date', '<=', datetime.date.today()))
|
||||||
|
])
|
||||||
|
|
||||||
|
to_date = fields.Date(
|
||||||
|
"To Date",
|
||||||
|
domain=[
|
||||||
|
If(Eval('from_date') & Eval('to_date'),
|
||||||
|
('to_date', '>=', Eval('from_date')),
|
||||||
|
()),
|
||||||
|
If(Eval('to_date'),
|
||||||
|
('to_date', '<=', datetime.date.today()))
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
class ReportSaleAbstract(ModelSQL):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def table_query(cls):
|
||||||
|
from_item, tables = cls._joins()
|
||||||
|
|
||||||
|
final_query = from_item.select(
|
||||||
|
*cls._columns(tables),
|
||||||
|
where=cls._where(tables),
|
||||||
|
group_by=cls._group_by(tables)
|
||||||
|
)
|
||||||
|
|
||||||
|
return final_query
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _joins(cls):
|
||||||
|
pool = Pool()
|
||||||
|
tables = {}
|
||||||
|
|
||||||
|
Sale = pool.get('sale.sale')
|
||||||
|
tables['sale.sale'] = sale = Sale.__table__()
|
||||||
|
|
||||||
|
SaleLine = pool.get('sale.line')
|
||||||
|
tables['sale.line'] = sale_line = SaleLine.__table__()
|
||||||
|
|
||||||
|
ProductTemplate = pool.get('product.template')
|
||||||
|
tables[
|
||||||
|
'product.template'
|
||||||
|
] = product_template = ProductTemplate.__table__()
|
||||||
|
|
||||||
|
ProductProduct = pool.get('product.product')
|
||||||
|
tables['product.product'] = product = ProductProduct.__table__()
|
||||||
|
|
||||||
|
from_item = sale_line.left_join(
|
||||||
|
product,
|
||||||
|
condition=product.id == sale_line.product
|
||||||
|
).left_join(
|
||||||
|
product_template,
|
||||||
|
condition=product.template == product_template.id
|
||||||
|
).left_join(
|
||||||
|
sale,
|
||||||
|
condition=sale.id == sale_line.sale
|
||||||
|
)
|
||||||
|
|
||||||
|
return from_item, tables
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _columns(cls, tables):
|
||||||
|
columns = [
|
||||||
|
cls._column_id(tables).as_('id'),
|
||||||
|
Literal(0).as_('create_uid'),
|
||||||
|
CurrentTimestamp().as_('create_date'),
|
||||||
|
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
|
||||||
|
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
|
||||||
|
]
|
||||||
|
|
||||||
|
return columns
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _where(cls, tables):
|
||||||
|
context = Transaction().context
|
||||||
|
where = Literal(True)
|
||||||
|
|
||||||
|
from_date = context.get('from_date')
|
||||||
|
to_date = context.get('to_date')
|
||||||
|
|
||||||
|
sale = tables['sale.sale']
|
||||||
|
if from_date:
|
||||||
|
where &= sale.sale_date >= from_date
|
||||||
|
|
||||||
|
if to_date:
|
||||||
|
where &= sale.sale_date <= to_date
|
||||||
|
|
||||||
|
return where
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _group_by(cls, tables):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _column_id(cls, tables):
|
||||||
|
sale_line = tables['sale.line']
|
||||||
|
return Min(sale_line.id)
|
||||||
|
|
||||||
|
|
||||||
|
class ReportSaleProduct(ReportSaleAbstract, ModelView):
|
||||||
|
"""Report Sale Group by Product"""
|
||||||
|
__name__ = 'sale_fast_food.reporting.product'
|
||||||
|
|
||||||
|
product_pizza = fields.Many2One('product.product', "Product")
|
||||||
|
quantity = fields.Float("Quantity")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _columns(cls, tables):
|
||||||
|
sale_line = tables['sale.line']
|
||||||
|
|
||||||
|
return super(ReportSaleProduct, cls)._columns(tables) + [
|
||||||
|
sale_line.product.as_('product_pizza'),
|
||||||
|
Sum(sale_line.quantity).as_('quantity')
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _group_by(cls, tables):
|
||||||
|
sale_line = tables['sale.line']
|
||||||
|
|
||||||
|
return [
|
||||||
|
sale_line.product
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _where(cls, tables):
|
||||||
|
where = super(ReportSaleProduct, cls)._where(tables)
|
||||||
|
product_template = tables['product.template']
|
||||||
|
where &= product_template.pizza == Literal(True)
|
||||||
|
|
||||||
|
return where
|
48
report.xml
Normal file
48
report.xml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
this repository contains the full copyright notices and license terms. -->
|
||||||
|
<tryton>
|
||||||
|
<data>
|
||||||
|
<record model="ir.ui.view" id="sale_fast_food_report_view_form">
|
||||||
|
<field name="model">sale_fast_food.report.context</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">sale_fast_food_report_context_form</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Family Members Per State -->
|
||||||
|
<record model="ir.ui.view" id="report_sale_fast_food_product_pizza_view_list">
|
||||||
|
<field name="model">sale_fast_food.reporting.product</field>
|
||||||
|
<field name="type">tree</field>
|
||||||
|
<field name="name">pizzas_sold_by_product_list</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.action.act_window" id="act_report_sale_fast_food_product_pizza">
|
||||||
|
<field name="name">Pizza Sold by Product</field>
|
||||||
|
<field name="res_model">sale_fast_food.reporting.product</field>
|
||||||
|
<field name="context_model">sale_fast_food.report.context</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.action.act_window.view" id="act_report_sale_fast_food_product_pizza_view1">
|
||||||
|
<field name="sequence" eval="10"/>
|
||||||
|
<field name="view" ref="report_sale_fast_food_product_pizza_view_list"/>
|
||||||
|
<field name="act_window" ref="act_report_sale_fast_food_product_pizza"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem
|
||||||
|
name="Reporting"
|
||||||
|
parent="sale.menu_sale"
|
||||||
|
sequence="999"
|
||||||
|
id="menu_sale_fast_food_reporting"/>
|
||||||
|
<menuitem
|
||||||
|
name="Sale Fast Food Pizza"
|
||||||
|
parent="menu_sale_fast_food_reporting"
|
||||||
|
sequence="10"
|
||||||
|
id="menu_sale_fast_food_pizza"
|
||||||
|
icon="tryton-graph"/>
|
||||||
|
<record model="ir.action.keyword" id="act_report_sale_fast_food_product_pizza_keyword1">
|
||||||
|
<field name="keyword">tree_open</field>
|
||||||
|
<field name="model" ref="menu_sale_fast_food_reporting"/>
|
||||||
|
<field name="action" ref="act_report_sale_fast_food_product_pizza"/>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</tryton>
|
206
tests/scenario_report_pizza.rst
Normal file
206
tests/scenario_report_pizza.rst
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
=============================
|
||||||
|
Sale Line Delete Log Scenario
|
||||||
|
=============================
|
||||||
|
|
||||||
|
Imports::
|
||||||
|
>>> from decimal import Decimal
|
||||||
|
>>> from proteus import Model, Wizard
|
||||||
|
>>> from trytond.tests.tools import activate_modules
|
||||||
|
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||||
|
>>> from trytond.modules.account.tests.tools import (
|
||||||
|
... create_chart, create_fiscalyear, create_tax, get_accounts)
|
||||||
|
>>> from trytond.modules.account_invoice.tests.tools import (
|
||||||
|
... create_payment_term, set_fiscalyear_invoice_sequences)
|
||||||
|
>>> import datetime as dt
|
||||||
|
>>> today = dt.date.today()
|
||||||
|
>>> from trytond.tests.tools import set_user
|
||||||
|
>>> from trytond.modules.sale_shop.tests.tools import create_shop
|
||||||
|
>>> from trytond.modules.sale_line_delete_log.sale import SaleLineDeleted
|
||||||
|
|
||||||
|
|
||||||
|
Activate modules::
|
||||||
|
|
||||||
|
>>> config = activate_modules('sale_fast_food')
|
||||||
|
|
||||||
|
|
||||||
|
>>> User = Model.get('res.user')
|
||||||
|
>>> Party = Model.get('party.party')
|
||||||
|
>>> Employee = Model.get('company.employee')
|
||||||
|
>>> Journal = Model.get('account.journal')
|
||||||
|
>>> PaymentMethod = Model.get('account.invoice.payment.method')
|
||||||
|
>>> Party = Model.get('party.party')
|
||||||
|
>>> ProductUom = Model.get('product.uom')
|
||||||
|
>>> ProductTemplate = Model.get('product.template')
|
||||||
|
>>> Sale = Model.get('sale.sale')
|
||||||
|
>>> SaleLine = Model.get('sale.line')
|
||||||
|
|
||||||
|
Create company::
|
||||||
|
|
||||||
|
>>> _ = create_company()
|
||||||
|
>>> company = get_company()
|
||||||
|
|
||||||
|
Set employee::
|
||||||
|
|
||||||
|
>>> employee_party = Party(name="Employee")
|
||||||
|
>>> employee_party.save()
|
||||||
|
>>> employee = Employee(party=employee_party)
|
||||||
|
>>> employee.save()
|
||||||
|
>>> user = User(config.user)
|
||||||
|
>>> user.employees.append(employee)
|
||||||
|
>>> user.employee = employee
|
||||||
|
>>> user.save()
|
||||||
|
>>> set_user(user.id)
|
||||||
|
|
||||||
|
Create fiscal year::
|
||||||
|
|
||||||
|
>>> fiscalyear = set_fiscalyear_invoice_sequences(create_fiscalyear(company, today))
|
||||||
|
>>> fiscalyear.click('create_period')
|
||||||
|
|
||||||
|
Create chart of accounts::
|
||||||
|
|
||||||
|
>>> _ = create_chart(company)
|
||||||
|
>>> accounts = get_accounts(company)
|
||||||
|
>>> revenue = accounts['revenue']
|
||||||
|
>>> expense = accounts['expense']
|
||||||
|
>>> cash = accounts['cash']
|
||||||
|
|
||||||
|
>>> cash_journal, = Journal.find([('type', '=', 'cash')])
|
||||||
|
>>> cash_journal.save()
|
||||||
|
>>> payment_method = PaymentMethod()
|
||||||
|
>>> payment_method.name = 'Cash'
|
||||||
|
>>> payment_method.journal = cash_journal
|
||||||
|
>>> payment_method.credit_account = cash
|
||||||
|
>>> payment_method.debit_account = cash
|
||||||
|
>>> payment_method.save()
|
||||||
|
|
||||||
|
Create tax::
|
||||||
|
|
||||||
|
>>> tax = create_tax(Decimal('.10'))
|
||||||
|
>>> tax.save()
|
||||||
|
|
||||||
|
Create parties::
|
||||||
|
|
||||||
|
>>> supplier = Party(name='Supplier')
|
||||||
|
>>> supplier.save()
|
||||||
|
>>> customer = Party(name='Customer')
|
||||||
|
>>> customer.save()
|
||||||
|
|
||||||
|
Create account categories::
|
||||||
|
|
||||||
|
>>> ProductCategory = Model.get('product.category')
|
||||||
|
>>> account_category = ProductCategory(name="Account Category")
|
||||||
|
>>> account_category.accounting = True
|
||||||
|
>>> account_category.account_expense = expense
|
||||||
|
>>> account_category.account_revenue = revenue
|
||||||
|
>>> account_category.save()
|
||||||
|
|
||||||
|
>>> account_category_tax, = account_category.duplicate()
|
||||||
|
>>> account_category_tax.customer_taxes.append(tax)
|
||||||
|
>>> account_category_tax.save()
|
||||||
|
|
||||||
|
Create product::
|
||||||
|
|
||||||
|
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||||
|
|
||||||
|
>>> template = ProductTemplate()
|
||||||
|
>>> template.name = 'product'
|
||||||
|
>>> template.default_uom = unit
|
||||||
|
>>> template.type = 'goods'
|
||||||
|
>>> template.salable = True
|
||||||
|
>>> template.pizza = True
|
||||||
|
>>> template.list_price = Decimal('10')
|
||||||
|
>>> template.account_category = account_category_tax
|
||||||
|
>>> template.save()
|
||||||
|
>>> product_pizza, = template.products
|
||||||
|
|
||||||
|
>>> template = ProductTemplate()
|
||||||
|
>>> template.name = 'service'
|
||||||
|
>>> template.default_uom = unit
|
||||||
|
>>> template.type = 'service'
|
||||||
|
>>> template.salable = True
|
||||||
|
>>> template.list_price = Decimal('30')
|
||||||
|
>>> template.account_category = account_category
|
||||||
|
>>> template.save()
|
||||||
|
>>> service, = template.products
|
||||||
|
|
||||||
|
Create payment term::
|
||||||
|
|
||||||
|
>>> payment_term = create_payment_term()
|
||||||
|
>>> payment_term.save()
|
||||||
|
|
||||||
|
Create product price list::
|
||||||
|
|
||||||
|
>>> ProductPriceList = Model.get('product.price_list')
|
||||||
|
>>> product_price_list = ProductPriceList()
|
||||||
|
>>> product_price_list.name = 'Price List'
|
||||||
|
>>> product_price_list.company = company
|
||||||
|
>>> product_price_list.save()
|
||||||
|
|
||||||
|
Create an Inventory::
|
||||||
|
|
||||||
|
>>> Inventory = Model.get('stock.inventory')
|
||||||
|
>>> Location = Model.get('stock.location')
|
||||||
|
>>> storage, = Location.find([
|
||||||
|
... ('code', '=', 'STO'),
|
||||||
|
... ])
|
||||||
|
>>> inventory = Inventory()
|
||||||
|
>>> inventory.location = storage
|
||||||
|
>>> inventory_line = inventory.lines.new(product=product_pizza)
|
||||||
|
>>> inventory_line.quantity = 100.0
|
||||||
|
>>> inventory_line.expected_quantity = 0.0
|
||||||
|
>>> inventory.click('confirm')
|
||||||
|
>>> inventory.state
|
||||||
|
'done'
|
||||||
|
|
||||||
|
Create Sale Shop::
|
||||||
|
|
||||||
|
>>> shop = create_shop(payment_term, product_price_list)
|
||||||
|
>>> shop.save()
|
||||||
|
|
||||||
|
Save Sale Shop User::
|
||||||
|
|
||||||
|
>>> User = Model.get('res.user')
|
||||||
|
>>> user, = User.find([])
|
||||||
|
>>> user.shops.append(shop)
|
||||||
|
>>> user.shop = shop
|
||||||
|
>>> user.save()
|
||||||
|
>>> set_user(user)
|
||||||
|
|
||||||
|
Sale 5 products::
|
||||||
|
|
||||||
|
>>> sale = Sale()
|
||||||
|
>>> sale.party = customer
|
||||||
|
>>> sale.payment_term = payment_term
|
||||||
|
>>> sale.invoice_method = 'order'
|
||||||
|
|
||||||
|
>>> sale_line = SaleLine()
|
||||||
|
>>> sale.lines.append(sale_line)
|
||||||
|
|
||||||
|
>>> sale_line.product = product_pizza
|
||||||
|
>>> sale_line.quantity = 2.0
|
||||||
|
>>> sale_line.impreso = True
|
||||||
|
|
||||||
|
>>> sale_line = SaleLine()
|
||||||
|
>>> sale.lines.append(sale_line)
|
||||||
|
>>> sale_line.product = product_pizza
|
||||||
|
>>> sale_line.quantity = 3.0
|
||||||
|
|
||||||
|
>>> sale_line = SaleLine()
|
||||||
|
>>> sale.lines.append(sale_line)
|
||||||
|
>>> sale_line.product = service
|
||||||
|
>>> sale_line.quantity = 5.0
|
||||||
|
|
||||||
|
>>> sale.save()
|
||||||
|
>>> len(sale.lines)
|
||||||
|
3
|
||||||
|
|
||||||
|
Sale Fast Food Pizzas Sell by Product::
|
||||||
|
>>> ReportSellPizzas = Model.get('sale_fast_food.reporting.product')
|
||||||
|
>>> reports = ReportSellPizzas.find([])
|
||||||
|
|
||||||
|
>>> expected_report = {
|
||||||
|
... (product_pizza, 2)
|
||||||
|
... }
|
||||||
|
|
||||||
|
>>> actual_report = {(r.product_pizza, r.quantity) for r in reports}
|
||||||
|
>>> assert expected_report == actual_report, f"\n Expect: {expected_report} \n Actual: {actual_report}"
|
@ -107,6 +107,7 @@ Create product::
|
|||||||
>>> template.default_uom = unit
|
>>> template.default_uom = unit
|
||||||
>>> template.type = 'goods'
|
>>> template.type = 'goods'
|
||||||
>>> template.salable = True
|
>>> template.salable = True
|
||||||
|
>>> template.pizza = True
|
||||||
>>> template.list_price = Decimal('10')
|
>>> template.list_price = Decimal('10')
|
||||||
>>> template.account_category = account_category_tax
|
>>> template.account_category = account_category_tax
|
||||||
>>> template.save()
|
>>> template.save()
|
||||||
|
@ -18,3 +18,4 @@ xml:
|
|||||||
sale.xml
|
sale.xml
|
||||||
user.xml
|
user.xml
|
||||||
report_close_statement.xml
|
report_close_statement.xml
|
||||||
|
report.xml
|
||||||
|
7
view/pizzas_sold_by_product_list.xml
Normal file
7
view/pizzas_sold_by_product_list.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
this repository contains the full copyright notices and license terms. -->
|
||||||
|
<tree>
|
||||||
|
<field name="product_pizza"/>
|
||||||
|
<field name="quantity" sum="1"/>
|
||||||
|
</tree>
|
11
view/sale_fast_food_report_context_form.xml
Normal file
11
view/sale_fast_food_report_context_form.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
this repository contains the full copyright notices and license terms. -->
|
||||||
|
<form>
|
||||||
|
<label name="from_date"/>
|
||||||
|
<group id="dates" col="-1">
|
||||||
|
<field name="from_date"/>
|
||||||
|
<label name="to_date"/>
|
||||||
|
<field name="to_date"/>
|
||||||
|
</group>
|
||||||
|
</form>
|
Loading…
Reference in New Issue
Block a user