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 . import product, sale, production, invoice, user, report_close_statement
|
||||
from . import (
|
||||
product, sale, production, invoice, user, report_close_statement, report)
|
||||
|
||||
__all__ = ['register']
|
||||
|
||||
@ -14,6 +15,8 @@ def register():
|
||||
user.User,
|
||||
production.Production,
|
||||
report_close_statement.ReportCloseStatementStart,
|
||||
report.ReportSaleProduct,
|
||||
report.ReportSaleContext,
|
||||
module='sale_fast_food', type_='model')
|
||||
Pool.register(
|
||||
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.type = 'goods'
|
||||
>>> template.salable = True
|
||||
>>> template.pizza = True
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.account_category = account_category_tax
|
||||
>>> template.save()
|
||||
|
@ -18,3 +18,4 @@ xml:
|
||||
sale.xml
|
||||
user.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