Compare commits

...

87 Commits

Author SHA1 Message Date
7d081ee7c0 fix: Machete Calzabana 2025-07-27 00:13:08 -03:00
0dac9f1ba9 fix: Update 7.6 2025-07-23 13:26:30 -03:00
316d0fe62d Add field Not Restaurant in user 2025-07-13 11:35:20 -05:00
b51c12eeb9 update 7.6 2025-06-06 23:32:40 -03:00
e81f8f44d3 Fix: Venta por Zona traduccion 2024-10-21 14:14:53 -05:00
83dcdddf1f Feat: Report Sale by Zone 2024-10-21 14:01:03 -05:00
535befbf4b Feat: Informe de Ventas Por Usuario 2024-10-21 12:16:07 -05:00
f05acd6484 Fix: Test expected_report 2024-10-21 09:46:20 -05:00
ec834ff7d9 Feat: Traducciones, Cambio en el Menu 2024-10-20 21:19:16 -05:00
c34f782480 Feat: Sale Fast Food Product by Pizza 2024-10-20 20:03:09 -05:00
2480d43167 Fix: SaleLineDelete para lineas de tipo line 2024-10-20 16:22:05 -05:00
18ffd2458c Feat: Impresion fe_qrcode y cufe 2024-10-20 16:15:03 -05:00
501d0ff776 Feat: credito view 2024-10-20 14:26:11 -05:00
047fce94d3 Feat: total_tip view 2024-10-20 14:22:34 -05:00
cec192af36 Feat: Se agrega total_tip 2024-10-20 14:20:12 -05:00
9cc0828696 Fix: ip_address 2024-10-20 13:55:48 -05:00
6d97f92fcd Fix: string ip_addres 2024-10-20 13:43:00 -05:00
6157328b80 Feat: Lineas eliminadas 2024-10-20 12:51:19 -05:00
0b49554eb5 Feat(WIP): Impresion de Lineas Eliminadas 2024-10-20 12:47:33 -05:00
77d626374f Feat: Se agrega impresion de lineas 2024-08-28 16:21:54 -05:00
11532d780c Fix: test 2024-08-28 15:28:16 -05:00
b7a63e73f2 Fix: Se agrega dependencias a sale_line_deleted_log 2024-08-28 15:26:22 -05:00
Mongar28
d00294e487 Se agregan las pruebas 2024-08-22 11:46:10 -05:00
798a25683c Fix: setup.py 2024-06-26 14:52:02 -05:00
04ada1d22c Add credito sale 2024-01-12 22:27:02 +00:00
root
4756c4468b Se corrieron las pruebas de estilo y de tryton 2024-01-04 21:24:33 +00:00
b23374955d fix: Se elimina Exception 2023-12-22 11:40:53 -05:00
60f1eca39a fix: Se añaden impresiones para USB 2023-12-22 10:06:37 -05:00
rodia
522a502268 feat: Se añade content para impresora pos de Tipo Usb 2023-12-22 07:45:50 -05:00
d8a6752bf7 fix: Se corrigen errores en 6.8 2023-12-11 21:53:57 -05:00
eb934a3de9 fix: Se corrigen errores en 6.8 2023-12-11 20:41:19 -05:00
741d8f4ad3 fix: Se actualiza a 6.8 2023-12-10 19:42:38 -05:00
6c3052902d fix: Se añade parametro 'product_quantities' a get_productions 2023-11-20 01:06:32 +00:00
e2400b75e3 fix: Se añada total_discount_cahce in get_amount 2023-11-19 23:15:52 +00:00
cbee1f4815 fix: Se incrementa version a 6.8.0 2023-11-12 09:56:02 -05:00
07390de74a Se añade base gravada 2023-09-20 12:11:50 -05:00
808c94cf47 Se modifica plantilla reporte 2023-09-19 15:53:38 -05:00
0382a15ab7 Se Añade excepción si no se encuentran ventas 2023-09-19 15:39:42 -05:00
2d15aa389f Se añade rango de resolución, formato de moneda 2023-09-19 15:34:53 -05:00
39351c2640 Se añade ventas por pizzas 2023-09-17 23:53:24 -05:00
4b837318e3 Se adiciona lógica de extractos 2023-09-17 20:31:47 -05:00
50c40c0a1c chore: Se agregan traducciones y se organizan vistas 2023-09-17 19:02:00 -05:00
f45043af7e feat: Se crea reporte de extracto de ventas 2023-09-17 13:12:32 -05:00
cb12fe5e0c Se añade descripcion en la linea 2023-09-05 17:45:45 +00:00
ee13006322 Merge branch '6.4' of https://gitea.onecluster.org/OneTeam/trytondo-sale_fast_food into 6.4 2023-09-03 19:57:53 -05:00
c9e50bb844 se agrega subtotal 2023-09-03 19:57:00 -05:00
cosmos
de95b5c996 Infinite search bug fix 2023-09-03 19:38:13 -05:00
3b46ae9c78 Se añade redondeo al descuento total 2023-09-03 19:15:20 -05:00
2c9bcc82ce Merge branch '6.4' of https://gitea.onecluster.org/OneTeam/trytondo-sale_fast_food into 6.4 2023-09-03 17:15:07 -05:00
b8c9db77f4 total_discount 2023-09-03 17:14:11 -05:00
cosmos
2bf689ef87 Add field Waiter in res.user and transate 2023-09-03 16:53:37 -05:00
cosmos
94279af9b8 Final changes have the total discount field and translate 2023-09-03 13:51:17 -05:00
cosmos
f6a968535d Add fields total_discuont and total_discount_cache 2023-08-31 13:27:25 -05:00
03d8711ab3 Se limpia la casa 2023-08-28 13:38:23 -05:00
d60c932b45 Se limpia la casa 2023-08-28 13:34:37 -05:00
0e7694b347 feat: Se agregan traducciones a botones 2023-08-15 11:26:34 -05:00
7556fd3789 fix se corrige vistas de botones del restaurante 2023-08-14 14:10:20 -05:00
b737a14857 fix: clean home 2023-08-13 15:14:22 -05:00
cosmos
4e0c39fd78 Add fields kitchen and bar in form product 2023-08-11 18:05:25 -05:00
root
e18d857ed6 change impreso buttons 2023-08-02 21:17:53 +00:00
cosmos
3b058e0e4a Add button Impreso 2023-08-02 15:45:55 -05:00
a4a4481312 fix: se corrige error en on_change_product linea 230 2023-08-02 02:12:27 +00:00
a244f18bf9 chore: Se agrega Total de la venta a la vista tree de la venta 2023-07-31 10:43:37 -05:00
aca4b9e1b4 chore: Se agrega zona y mesa a la vista tree de la venta 2023-07-31 10:27:53 -05:00
693f2d2e04 Error Bug 2023-07-27 07:33:36 -05:00
2ab5993a90 finish bill ticket 2023-07-26 13:09:21 -05:00
7b244fa0da add information for print bill ticket 2023-07-26 00:36:00 -05:00
1c65c9da81 add button bill 2023-07-25 23:06:21 -05:00
5bb58622c3 field shop to sale 2023-07-25 22:20:50 -05:00
4f378cbae9 add printer by zone 2023-07-22 11:27:17 -05:00
a118d64c71 Add field Tip 2023-07-19 02:04:57 +00:00
root
d0bde61593 update print buttons 2023-07-11 19:37:12 +00:00
root
8f079d4f65 add bar button 2023-07-11 19:26:23 +00:00
62144b60ca add decode method to customer_order 2023-07-11 12:10:30 -05:00
bfdffca9e3 Merge branch '6.4' of https://gitea.onecluster.org/OneTeam/trytondo-sale_fast_food into 6.4
add report customer_order
2023-07-10 14:38:08 -05:00
69966b529a add report 2023-07-10 14:37:53 -05:00
root
55cefcb8ca add button kitchen 2023-07-10 19:32:48 +00:00
b38ac4cb3e Merge branch '6.4' of https://gitea.onecluster.org/OneTeam/trytondo-sale_fast_food into 6.4 2023-07-09 10:02:04 -05:00
2494b0b906 add print button kitchen 2023-07-09 10:01:00 -05:00
5054666e40 No requirido lineas de typo = Titulo 2023-06-28 20:01:20 +00:00
d9df054288 No requirido lineas de typo = Titulo 2023-06-28 20:00:31 +00:00
a723842c36 No requirido lineas de typo = Titulo 2023-06-28 19:58:33 +00:00
24da82aa41 add line of title to the sale 2023-06-28 10:18:35 -05:00
0bfc36b7c2 update production 2023-06-25 01:50:26 -05:00
8049d555f2 add production 2023-06-24 23:02:37 -05:00
e170c152ab delete element expand in label product template 2023-06-25 02:26:56 +00:00
975b64f44f add boms to template product 2023-06-24 10:29:11 -05:00
29 changed files with 4766 additions and 51 deletions

View File

@ -1,5 +1,6 @@
from trytond.pool import Pool
from . import product, sale
from . import (
product, sale, production, invoice, user, report_close_statement, report)
__all__ = ['register']
@ -7,10 +8,21 @@ __all__ = ['register']
def register():
Pool.register(
product.Product,
invoice.InvoiceLine,
sale.Sale,
sale.Line,
sale.SaleLineDeletedLog,
user.User,
production.Production,
report_close_statement.ReportCloseStatementStart,
report.ReportSaleProduct,
report.ReportSaleByUser,
report.ReportSaleByZone,
report.ReportSaleContext,
module='sale_fast_food', type_='model')
Pool.register(
report_close_statement.PrintReportCloseStatement,
module='sale_fast_food', type_='wizard')
Pool.register(
report_close_statement.CashRegister,
module='sale_fast_food', type_='report')

13
invoice.py Normal file
View File

@ -0,0 +1,13 @@
from trytond.pool import PoolMeta
from trytond.pyson import Eval
class InvoiceLine(metaclass=PoolMeta):
__name__ = 'account.invoice.line'
@classmethod
def __setup__(cls):
super(InvoiceLine, cls).__setup__()
cls.product.states['required'] = (Eval('type') == 'line')
cls.unit_price.domain = []

View File

@ -6,6 +6,158 @@ msgctxt "field:product.template,pizza:"
msgid "Pizza"
msgstr "Pizza"
msgctxt "field:product.template,pizza:"
msgctxt "field:product.template,pizza_topping:"
msgid "Topping Pizza"
msgstr "Adiciónes"
msgctxt "field:product.template,boms:"
msgid "Boms"
msgstr "Lista de Materiales"
msgctxt "field:product.template,tip:"
msgid "Tip"
msgstr "Propina"
msgctxt "field:product.template,kitchen:"
msgid "Kitchen"
msgstr "Cocina"
msgctxt "model:ir.model.button,string:sale_add_pizza_button"
msgid "Add Pizza"
msgstr "Agregar Pizza"
msgctxt "model:ir.model.button,string:sale_order_kitchen_button"
msgid "Kitchen"
msgstr "Cocina"
msgctxt "model:ir.model.button,string:sale_order_bar_button"
msgid "Bar"
msgstr "Bar"
msgctxt "model:ir.model.button,string:sale_print_bill_button"
msgid "Bill"
msgstr "Subtotal"
msgctxt "field:sale.sale,total_discount:"
msgid "Total Discount"
msgstr "Total Descuento"
msgctxt "field:res.user,waiter:"
msgid "Waiter"
msgstr "Mesero"
msgctxt "model:ir.ui.menu,name:menu_print_cash_register"
msgid "Print cash register"
msgstr "Imprimir arqueo de caja"
msgctxt "field:sale.print_cash_register.start,date:"
msgid "Date"
msgstr "Fecha"
msgctxt "field:sale.print_cash_register.start,shop:"
msgid "Shop"
msgstr "Tienda"
msgctxt "field:sale_fast_food.report.context,from_date:"
msgid "From Date"
msgstr "Desde la Fecha"
msgctxt "field:sale_fast_food.report.context,to_date:"
msgid "To Date"
msgstr "Hasta la Fecha"
msgctxt "model:ir.action,name:act_report_sale_fast_food_product_pizza"
msgid "Pizzas Sold by Product"
msgstr "Pizzas Vendidas Por Producto"
msgctxt "model:ir.ui.menu,name:menu_sale_fast_food_pizza"
msgid "Pizzas Sold by Product"
msgstr "Pizzas Vendidas Por Producto"
msgctxt "model:ir.action,name:act_report_sale_fast_food_by_user"
msgid "Sales by User"
msgstr "Ventas Por Usuario"
msgctxt "model:ir.ui.menu,name:menu_sale_fast_food_by_user"
msgid "Sales by User"
msgstr "Ventas Por Usuario"
msgctxt "model:ir.action,name:act_report_sale_fast_food_zone"
msgid "Sales by Zone"
msgstr "Ventas Por Zona"
msgctxt "model:ir.ui.menu,name:menu_sale_fast_food_zone"
msgid "Sales by Zone"
msgstr "Ventas Por Zona"
msgctxt "field:sale_fast_food.reporting.product,product_pizza:"
msgid "Product"
msgstr "Pizza"
msgctxt "field:sale_fast_food.reporting.product,quantity:"
msgid "Quantity"
msgstr "Cantidad"
msgctxt "field:sale_fast_food.reporting.by_user,user:"
msgid "User"
msgstr "Usuario"
msgctxt "field:sale_fast_food.reporting.by_user,completed_sales:"
msgid "Completed Sales"
msgstr "# Ventas"
msgctxt "field:sale_fast_food.reporting.by_user,untaxed_amount:"
msgid "Untaxed Amount"
msgstr "Base Imponible"
msgctxt "field:sale_fast_food.reporting.by_user,tax_amount:"
msgid "Tax Amount"
msgstr "Impuestos"
msgctxt "field:sale_fast_food.reporting.by_user,total_amount:"
msgid "Total Amount"
msgstr "Total"
msgctxt "field:sale_fast_food.reporting.by_user,total_tip_amount:"
msgid "Total Tip Amount"
msgstr "Propinas"
msgctxt "field:sale_fast_food.reporting.zone,zone:"
msgid "Zone"
msgstr "Zona"
msgctxt "field:sale_fast_food.reporting.zone,table:"
msgid "Table"
msgstr "Mesa"
msgctxt "field:sale_fast_food.reporting.zone,completed_sales:"
msgid "Completed Sales"
msgstr "# Ventas"
msgctxt "field:sale_fast_food.reporting.zone,untaxed_amount:"
msgid "Untaxed Amount"
msgstr "Base Imponible"
msgctxt "field:sale_fast_food.reporting.zone,tax_amount:"
msgid "Tax Amount"
msgstr "Impuestos"
msgctxt "field:sale_fast_food.reporting.zone,total_amount:"
msgid "Total Amount"
msgstr "Total"
msgctxt "field:sale_fast_food.reporting.zone,total_tip_amount:"
msgid "Total Tip Amount"
msgstr "Propinas"
msgctxt "wizard_button:sale.print_cash_register,start,end:"
msgid "Cancel"
msgstr "Cancelar"
msgctxt "wizard_button:sale.print_cash_register,start,print_cash_register:"
msgid "Print Cash Register"
msgstr "Imprimir"
msgctxt "model:ir.action,name:wizard_print_cash_register"
msgid "Print cash register"
msgstr "Imprimir arqueo de caja"

View File

@ -1,5 +1,6 @@
from trytond.pool import Pool, PoolMeta
from trytond.pool import PoolMeta
from trytond.model import fields
from trytond.pyson import Eval
class Product(metaclass=PoolMeta):
@ -7,4 +8,9 @@ class Product(metaclass=PoolMeta):
__name__ = 'product.template'
pizza = fields.Boolean("Pizza")
Pizza_topping = fields.Boolean("Topping Pizza")
pizza_topping = fields.Boolean("Topping Pizza")
tip = fields.Boolean("Tip")
kitchen = fields.Boolean("Kitchen")
bar = fields.Boolean("Bar")
boms = fields.Many2One('production.bom', "Boms",
states={'required': Eval('producible', True)})

View File

@ -4,14 +4,14 @@
<tryton>
<data>
<record model="ir.ui.view" id="product_view_tree">
<field name="model">product.template</field>
<field name="inherit" ref="product.template_view_tree"/>
<field name="name">product_tree</field>
<field name="model">product.template</field>
<field name="inherit" ref="product.template_view_tree"/>
<field name="name">product_tree</field>
</record>
<record model="ir.ui.view" id="product_view_form">
<field name="model">product.template</field>
<field name="inherit" ref="product.template_view_form"/>
<field name="name">product_form</field>
<field name="model">product.template</field>
<field name="inherit" ref="product.template_view_form"/>
<field name="name">product_form</field>
</record>
</data>
</tryton>

59
production.py Normal file
View File

@ -0,0 +1,59 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
# from decimal import Decimal
from trytond.pool import PoolMeta
# from trytond.model import fields
BOM_CHANGES = ['bom', 'product', 'quantity', 'uom', 'warehouse', 'location',
'company', 'inputs', 'outputs']
class Production(metaclass=PoolMeta):
"Production"
__name__ = 'production'
"""
@fields.depends(
'bom', 'product', 'uom', 'quantity', 'company', 'inputs', 'outputs',
methods=['_explode_move_values'])
def explode_bom(self):
pool = Pool()
Uom = pool.get('product.uom')
if not (self.bom and self.product and self.uom):
return
factor = self.bom.compute_factor(self.product, self.quantity or 0,
self.uom)
inputs = []
for input_ in self.bom.inputs:
# if input_.product.producible:
# for input_ in input_.product.template.boms.inputs:
quantity = input_.compute_quantity(factor)
move = self._explode_move_values('input', input_, quantity)
if move:
inputs.append(move)
quantity = Uom.compute_qty(
input_.uom, quantity,
input_.product.default_uom, round=False)
# else:
# quantity = input_.compute_quantity(factor)
# move = self._explode_move_values('output', input_, quantity)
# if move:
# inputs.append(move)
# quantity = Uom.compute_qty(
# input_.uom, quantity,
# input_.product.default_uom, round=False)
self.inputs = inputs
outputs = []
for output in self.bom.outputs:
quantity = output.compute_quantity(factor)
move = self._explode_move_values('output', output,
quantity)
if move:
move.unit_price = Decimal(0)
outputs.append(move)
self.outputs = outputs
"""

280
report.py Normal file
View File

@ -0,0 +1,280 @@
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, Count
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
class ReportSaleByUser(ReportSaleAbstract, ModelView):
"""Report Sale Group by User"""
__name__ = 'sale_fast_food.reporting.by_user'
user = fields.Many2One('res.user', "User")
completed_sales = fields.Integer("Completed Sales")
untaxed_amount = fields.Numeric(
"Untaxed Amount", digits='currency', readonly=True)
tax_amount = fields.Numeric(
"Tax Amount", digits='currency', readonly=True)
total_amount = fields.Numeric(
"Total Amount", digits='currency', readonly=True)
total_tip_amount = fields.Numeric(
"Total Tip Amount", digits='currency', readonly=True)
currency = fields.Many2One(
'currency.currency', 'Currency', required=True)
@classmethod
def _joins(cls):
pool = Pool()
tables = {}
Sale = pool.get('sale.sale')
tables['sale.sale'] = sale = Sale.__table__()
from_item = sale
return from_item, tables
@classmethod
def _columns(cls, tables):
sale = tables['sale.sale']
return super(ReportSaleByUser, cls)._columns(tables) + [
sale.create_uid.as_('user'),
Count(Literal(1)).as_('completed_sales'),
Sum(sale.untaxed_amount_cache).as_('untaxed_amount'),
Sum(sale.tax_amount_cache).as_('tax_amount'),
Sum(sale.total_amount_cache).as_('total_amount'),
Sum(sale.total_tip_cache).as_('total_tip_amount'),
sale.currency.as_('currency'),
]
@classmethod
def _group_by(cls, tables):
sale = tables['sale.sale']
return [
sale.create_uid,
sale.currency
]
@classmethod
def _column_id(cls, tables):
sale = tables['sale.sale']
return Min(sale.id)
class ReportSaleByZone(ReportSaleAbstract, ModelView):
"""Report Sale Group by Zone"""
__name__ = 'sale_fast_food.reporting.zone'
zone = fields.Many2One('sale.zone', "Zone")
table = fields.Many2One('sale.table', "Table")
completed_sales = fields.Integer("Completed Sales")
untaxed_amount = fields.Numeric(
"Untaxed Amount", digits='currency', readonly=True)
tax_amount = fields.Numeric(
"Tax Amount", digits='currency', readonly=True)
total_amount = fields.Numeric(
"Total Amount", digits='currency', readonly=True)
total_tip_amount = fields.Numeric(
"Total Tip Amount", digits='currency', readonly=True)
currency = fields.Many2One(
'currency.currency', 'Currency', required=True)
@classmethod
def _joins(cls):
pool = Pool()
tables = {}
Sale = pool.get('sale.sale')
tables['sale.sale'] = sale = Sale.__table__()
Table = pool.get('sale.table')
tables['sale.table'] = table = Table.__table__()
Zone = pool.get('sale.zone')
tables['sale.table'] = zone = Zone.__table__()
from_item = sale.left_join(
table,
condition=table.id == sale.table
).left_join(
zone,
condition=zone.id == table.zone
)
return from_item, tables
@classmethod
def _columns(cls, tables):
sale = tables['sale.sale']
return super(ReportSaleByZone, cls)._columns(tables) + [
sale.zone.as_('zone'),
sale.table.as_('table'),
Count(Literal(1)).as_('completed_sales'),
Sum(sale.untaxed_amount_cache).as_('untaxed_amount'),
Sum(sale.tax_amount_cache).as_('tax_amount'),
Sum(sale.total_amount_cache).as_('total_amount'),
Sum(sale.total_tip_cache).as_('total_tip_amount'),
sale.currency.as_('currency'),
]
@classmethod
def _group_by(cls, tables):
sale = tables['sale.sale']
return [
sale.zone,
sale.table,
sale.currency
]
@classmethod
def _column_id(cls, tables):
sale = tables['sale.sale']
return Min(sale.id)

103
report.xml Normal file
View File

@ -0,0 +1,103 @@
<?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>
<!-- Report by Product-->
<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">Pizzas 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>
<!-- Report by Product-->
<record model="ir.ui.view" id="report_sale_fast_food_by_user_view_list">
<field name="model">sale_fast_food.reporting.by_user</field>
<field name="type">tree</field>
<field name="name">sales_by_user_list</field>
</record>
<record model="ir.action.act_window" id="act_report_sale_fast_food_by_user">
<field name="name">Sales by User</field>
<field name="res_model">sale_fast_food.reporting.by_user</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_by_user_view1">
<field name="sequence" eval="20"/>
<field name="view" ref="report_sale_fast_food_by_user_view_list"/>
<field name="act_window" ref="act_report_sale_fast_food_by_user"/>
</record>
<!-- Report by Zone-->
<record model="ir.ui.view" id="report_sale_fast_food_zone_view_list">
<field name="model">sale_fast_food.reporting.zone</field>
<field name="type">tree</field>
<field name="name">sales_by_zone_list</field>
</record>
<record model="ir.action.act_window" id="act_report_sale_fast_food_zone">
<field name="name">Sales by Zone</field>
<field name="res_model">sale_fast_food.reporting.zone</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_zone_view1">
<field name="sequence" eval="20"/>
<field name="view" ref="report_sale_fast_food_zone_view_list"/>
<field name="act_window" ref="act_report_sale_fast_food_zone"/>
</record>
<menuitem
name="Pizzas Sold by Product"
parent="sale.menu_reporting"
sequence="10"
id="menu_sale_fast_food_pizza"
icon="tryton-graph"/>
<menuitem
name="Sales by User"
parent="sale.menu_reporting"
sequence="20"
id="menu_sale_fast_food_by_user"
icon="tryton-graph"/>
<menuitem
name="Sales by Zone"
parent="sale.menu_reporting"
sequence="30"
id="menu_sale_fast_food_zone"
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_pizza"/>
<field name="action" ref="act_report_sale_fast_food_product_pizza"/>
</record>
<record model="ir.action.keyword" id="act_report_sale_fast_food_by_user_keyword1">
<field name="keyword">tree_open</field>
<field name="model" ref="menu_sale_fast_food_by_user"/>
<field name="action" ref="act_report_sale_fast_food_by_user"/>
</record>
<record model="ir.action.keyword" id="act_report_sale_fast_food_zone_keyword1">
<field name="keyword">tree_open</field>
<field name="model" ref="menu_sale_fast_food_zone"/>
<field name="action" ref="act_report_sale_fast_food_zone"/>
</record>
</data>
</tryton>

2061
report/close_statement.fodt Normal file

File diff suppressed because it is too large Load Diff

1206
report/customer_order.fodt Normal file

File diff suppressed because it is too large Load Diff

213
report_close_statement.py Normal file
View File

@ -0,0 +1,213 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.model import ModelView, fields
from trytond.wizard import Wizard, StateView, Button, StateReport
from trytond.transaction import Transaction
from trytond.pool import Pool
from trytond.report import Report
from trytond.exceptions import UserError
from decimal import Decimal
from datetime import date
__all__ = ['ReportCloseStatementStart', 'PrintReportCloseStatement',
'CashRegister']
class ReportCloseStatementStart(ModelView):
"Vista inicial de reporte de extracto"
__name__ = 'sale.print_cash_register.start'
company = fields.Many2One(
'company.company', "Company", readonly=True, required=True)
currency = fields.Many2One('currency.currency', 'Currency', required=True)
date = fields.Date('Date', required=True)
shop = fields.Many2One('sale.shop', 'Shop', required=True)
@staticmethod
def default_company():
return Transaction().context.get('company')
@staticmethod
def default_currency():
Company = Pool().get('company.company')
if Transaction().context.get('company'):
company = Company(Transaction().context['company'])
return company.currency.id
@classmethod
def default_date(cls):
return date.today()
@classmethod
def default_shop(cls):
context = Transaction().context
if context:
shop = context['shop']
if shop:
return shop
return
class PrintReportCloseStatement(Wizard):
"Asistente para imprimir extracto"
__name__ = 'sale.print_cash_register'
start = StateView(
'sale.print_cash_register.start',
'sale_fast_food.print_cash_register_start_view_form', [
Button("Cancel", 'end', 'tryton-cancel'),
Button("Print Cash Register",
'print_cash_register', 'tryton-ok', default=True)])
print_cash_register = StateReport('sale.cash_register')
def do_print_cash_register(self, action):
data = {
'lang': self.start.company.party.lang,
'date': self.start.date,
'shop': self.start.shop.id,
'currency': self.start.currency.id,
}
return action, data
def transition_print_cash_register(self):
return 'end'
class CashRegister(Report):
"Extracto"
__name__ = 'sale.cash_register'
def _get_info_pizzas_sold(lines):
pizzas = 0
amount_w_tax = 0
amount_tip = 0
for line in lines:
if line.bought_pizza:
pizzas += line.quantity
amount_w_tax += line.amount_w_tax
if line.product and line.product.template.tip:
amount_tip += line.amount
return {
'amount_tip': amount_tip,
'amount_w_tax': amount_w_tax,
'pizzas': pizzas,
}
def _get_statements_by_date(date):
pool = Pool()
User = pool.get('res.user')
Statement = pool.get('account.statement')
user = Transaction().user
user = User(user)
device = user.sale_device
if not device:
return
journals = [j.id for j in device.journals]
statements = Statement.search([
('journal', 'in', journals),
('state', 'in', ['validated', 'posted']),
('date', '=', date)
])
return statements
def _get_invoices_by_subtype(date, shop):
pool = Pool()
Invoice = pool.get('account.invoice')
Shop = pool.get('sale.shop')
fe_pos_subtype = Shop(shop).fe_pos_subtype.id
pos_subtype = Shop(shop).pos_subtype.id
ranges = {}
invoices_fe = Invoice.search([('invoice_date', '=', date),
('subtype', '=', fe_pos_subtype)])
if invoices_fe:
ranges['range_fe'] = \
[invoices_fe[0].number, invoices_fe[-1].number]
invoices_pos = Invoice.search([('invoice_date', '=', date),
('subtype', '=', pos_subtype)])
if invoices_pos:
ranges['range_pos'] = \
[invoices_pos[0].number, invoices_pos[-1].number]
return ranges
@classmethod
def get_context(cls, records, header, data):
report_context = super(
CashRegister, cls).get_context(records, header, data)
pool = Pool()
Shop = pool.get('sale.shop')
Sale = pool.get('sale.sale')
Currency = pool.get('currency.currency')
currency = Currency(data['currency'])
date = data['date']
shop = data['shop']
today_sales_domain = [('state', 'in', ['processing', 'done']),
('sale_date', '=', date),
('shop', '=', shop)]
today_sales = Sale.search(today_sales_domain,
order=[('id', 'ASC')])
if not today_sales:
raise UserError(str("No se han encontrado ventas para este día."))
return
untaxed_amount = 0
tax_amount = 0
total_amount = 0
total_pizzas = 0
amount_w_tax_pizzas = []
amount_tips = []
for sale in today_sales:
untaxed_amount += sale.untaxed_amount
tax_amount += sale.tax_amount
info_pizzas_sold = cls._get_info_pizzas_sold(sale.lines)
total_pizzas += info_pizzas_sold['pizzas']
amount_w_tax_pizzas.append(info_pizzas_sold['amount_w_tax'])
amount_tips.append(info_pizzas_sold['amount_tip'])
total_amount += sale.total_amount
untaxed_amount_for_tax = round((tax_amount * 100) / Decimal('8.0'), 2)
statements = cls._get_statements_by_date(data['date'])
if statements:
report_context['statements'] = [{
'name': statement.journal.name,
'start_balance': statement.start_balance,
'end_balance': statement.end_balance,
'total_amount': sum(
(line.amount for line in statement.lines
if line.description), Decimal(0))
} for statement in statements]
report_context['total_statements'] = sum(
[s['total_amount'] for s in report_context['statements']])
ranges = cls._get_invoices_by_subtype(date, shop)
ranges_keys = ranges.keys()
if 'range_fe' in ranges_keys:
report_context['range_fe'] = ranges['range_fe']
else:
report_context['range_fe'] = []
if 'range_pos' in ranges:
report_context['range_pos'] = ranges['range_pos']
else:
report_context['range_pos'] = []
report_context['shop'] = Shop(shop).name
report_context['date'] = date
report_context['currency'] = currency
report_context['amount_w_tax_pizzas'] = sum(amount_w_tax_pizzas)
report_context['tips'] = sum(amount_tips)
report_context['untaxed_amount'] = untaxed_amount
report_context['untaxed_amount_for_tax'] = untaxed_amount_for_tax
report_context['tax_amount'] = tax_amount
report_context['total_amount'] = total_amount
report_context['number_pizzas_sold'] = total_pizzas
return report_context

View File

@ -0,0 +1,27 @@
<?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.action.report" id="report_close_statement">
<field name="name">Close statement</field>
<field name="report_name">sale.cash_register</field>
<field name="report">sale_fast_food/report/close_statement.fodt</field>
<field name="template_extension">odt</field>
</record>
<record model="ir.ui.view" id="print_cash_register_start_view_form">
<field name="model">sale.print_cash_register.start</field>
<field name="type">form</field>
<field name="name">print_cash_register_start_form</field>
</record>
<record model="ir.action.wizard" id="wizard_print_cash_register">
<field name="name">Print cash register</field>
<field name="wiz_name">sale.print_cash_register</field>
</record>
<menuitem
parent="sale.menu_sale"
action="wizard_print_cash_register"
id="menu_print_cash_register"
icon="tryton-print"/>
</data>
</tryton>

411
sale.py
View File

@ -1,6 +1,11 @@
from trytond.pool import Pool, PoolMeta
from trytond.model import ModelView, fields
from trytond.exceptions import UserError
from trytond.transaction import Transaction
from trytond.modules.currency.fields import Monetary
from decimal import Decimal
import requests
import json
class Sale(metaclass=PoolMeta):
@ -8,39 +13,429 @@ class Sale(metaclass=PoolMeta):
__name__ = 'sale.sale'
pizza_number = fields.Integer("Number pizza")
credito = fields.Boolean("Credito")
total_discount = fields.Function(
Monetary(
"Total Discount", digits='currency', currency='currency'),
'get_amount')
total_discount_cache = fields.Numeric(
"Total Discount cache", digits='currency')
total_tip = fields.Function(
Monetary(
"Total Tip", digits='currency', currency='currency'),
'get_amount')
total_tip_cache = fields.Numeric(
"Total Tip cache", digits="currency")
@classmethod
def __setup__(cls):
super(Sale, cls).__setup__()
cls._buttons.update({
'add_pizza': {},
'kitchen': {},
'bar': {},
'print_bill': {},
'impreso': {},
})
@classmethod
def default_pizza_number(cls):
return 0
@fields.depends('lines', 'currency', methods=['get_tax_amount'])
def on_change_lines(self):
self.untaxed_amount = Decimal('0.0')
self.tax_amount = Decimal('0.0')
self.total_amount = Decimal('0.0')
self.total_discount = Decimal('0.0')
self.total_tip = Decimal('0.0')
if self.lines:
for line in self.lines:
self.untaxed_amount += getattr(line, 'amount', None) or 0
self.tax_amount = self.get_tax_amount()
if self.currency:
self.untaxed_amount = self.currency.round(self.untaxed_amount)
self.tax_amount = self.currency.round(self.tax_amount)
self.total_amount = self.untaxed_amount + self.tax_amount
if self.currency:
self.total_tip = self.currency.round(self.total_tip)
self.total_discount = self.currency.round(self.total_discount)
self.total_amount = self.currency.round(self.total_amount)
@classmethod
def store_cache(cls, sales):
for sale in sales:
sale.untaxed_amount_cache = sale.untaxed_amount
sale.tax_amount_cache = sale.tax_amount
sale.total_amount_cache = sale.total_amount
sale.total_discount_cache = sale.total_discount
sale.total_tip_cache = sale.total_tip
cls.save(sales)
@classmethod
def get_amount(cls, sales, names):
untaxed_amount = {}
tax_amount = {}
total_amount = {}
total_discount = {}
total_tip = {}
if {'tax_amount', 'total_amount'} & set(names):
compute_taxes = True
else:
compute_taxes = False
# Sort cached first and re-instanciate to optimize cache management
sales = sorted(sales, key=lambda s: s.state in cls._states_cached,
reverse=True)
sales = cls.browse(sales)
for sale in sales:
if (sale.state in cls._states_cached
and sale.untaxed_amount_cache is not None
and sale.tax_amount_cache is not None
and sale.total_amount_cache is not None):
untaxed_amount[sale.id] = sale.untaxed_amount_cache
total_discount[sale.id] = sale.total_discount_cache
total_tip[sale.id] = sale.total_tip_cache
if compute_taxes:
tax_amount[sale.id] = sale.tax_amount_cache
total_amount[sale.id] = sale.total_amount_cache
else:
untaxed_amount[sale.id] = round(sum(
(line.amount for line in sale.lines
if line.type == 'line'), Decimal(0)), 2)
total_discount[sale.id] = round(sum(
(line.discount_amount * Decimal(
line.quantity) for line in sale.lines
if line.discount_amount and line.type == 'line'
), Decimal(0)), 2)
total_tip[sale.id] = round(
sum((
line.amount for line in sale.lines
if line.product and line.product.tip and (
line.type == 'line')
), Decimal(0)), 2)
if compute_taxes:
tax_amount[sale.id] = sale.get_tax_amount()
total_amount[sale.id] = (
untaxed_amount[sale.id] + tax_amount[sale.id])
result = {
'untaxed_amount': untaxed_amount,
'tax_amount': tax_amount,
'total_amount': total_amount,
'total_discount': total_discount,
'total_tip': total_tip
}
for key in list(result.keys()):
if key not in names:
del result[key]
return result
def get_invoice_resolution(subtype):
if subtype:
resolution = subtype.sequence.invoice_resolution
if resolution:
return dict([
('resolution_number', resolution.resolution_number),
('resolution_prefix', resolution.prefix),
('valid_date_time_from', str(
resolution.valid_date_time_from)),
('valid_date_time_to', str(resolution.valid_date_time_to)),
('from_number', resolution.from_number),
('to_number', resolution.to_number)])
@classmethod
def get_invoice(cls, record):
if record.state != 'draft' and record.invoices:
invoice = record.invoices[0]
data = {}
data['invoice_number'] = invoice.number
#subtype = invoice.subtype
#data['resolution'] = cls.get_invoice_resolution(subtype)
return data
@classmethod
def report_bill(cls, records):
if not records:
return
pool = Pool()
ctx = Transaction().context
record = records[0]
Shop = pool.get('sale.shop')
data = {}
shop = Shop.search([('id', '=', ctx["shop"])])[0]
data["shop_name"] = shop.name
data["shop_nit"] = shop.company.party.tax_identifier.code
data["shop_address"] = shop.address.street
data['invoice'] = cls.get_invoice(record)
# data['fe_cufe'] = record.fe_qrcode
# data['cufe'] = record.fe_cufe
data["party"] = record.party.name
data["tax_identifier_type"] = record.party.tax_identifier.type_string
data["tax_identifier_code"] = record.party.tax_identifier.code
data["address"] = record.invoice_address.street
data["city"] = record.invoice_address.subdivision_municipality.name
data["zone"] = record.zone.name if record.zone else ""
data["table"] = record.table.name if record.table else ""
data["lines"] = [{
'type': line.type,
"product": line.product.name if line.type != 'title' else None,
"quantity": line.quantity if line.type != 'title' else None,
"uom": line.unit.symbol if line.type != 'title' else None,
"unit_price": str(line.amount_w_tax)
if line.type != 'title' else None,
"taxes": str(round(line.taxes[0].rate * 100, 2)) + '%'
if line.type != 'title' and line.taxes else None
} for line in record.lines]
data["total_discount"] = str(round(record.total_discount, 2))
data["untaxed_amount"] = str(record.untaxed_amount)
data["tax_amount"] = str(record.tax_amount)
data["total_tip"] = str(record.total_tip)
data["total"] = str(record.total_amount)
data["state"] = \
"SUBTOTAL" if record.state == "draft" else "CUENTA FINAL"
if record.payments:
data['payments'] = [{
"statement": payment.statement.journal.name,
"amount": str(payment.amount)} for payment in record.payments]
return data
def report_customer_order(records):
if not records:
return
report = records[0]
data = {}
data["party"] = report.party.name
data["tax_identifier_type"] = report.party.tax_identifier.type_string
data["tax_identifier_code"] = report.party.tax_identifier.code
data["address"] = report.invoice_address.street
data["city"] = report.invoice_address.subdivision_municipality.name
data["zone"] = report.zone.name if report.zone else ""
data["table"] = report.table.name if report.table else ""
data["lines"] = [{
"type": line.type,
"product": line.product.name if line.type != "title" else None,
"description": line.description if line.type != "title" else None,
"quantity": line.quantity if line.type != "title" else None,
"uom": line.unit.name if line.type != "title" else None}
for line in report.lines if not line.impreso]
data["deleted_lines"] = [{
"product": line.product.name,
"quantity": str(-1 * line.quantity),
"unit": line.unit.symbol
} for line in report.delete_lines if not line.printed]
return data
@classmethod
@ModelView.button
def add_pizza(cls, records):
pool = Pool()
saleLine = pool.get('sale.line')
for record in records:
record.pizza_number +=1
record.pizza_number += 1
record.lines += (saleLine(type="title",
description="Pizza Combinada"),)
record.save()
@classmethod
@ModelView.button
def impreso(cls, records):
record = records[0]
for line in record.lines:
line.analytic_accounts = tuple()
line.impreso = True
line.save()
for line in record.delete_lines:
line.printed = True
line.save()
record.save()
@classmethod
@ModelView.button
def print_bill(cls, records):
pool = Pool()
context = Transaction().context
shop = context['shop']
Printer = pool.get('sale.printer')
printers = Printer.search([
('zone', '=', 'reception'),
('shop', '=', shop)])
if not printers:
return
printer = printers[0]
url = f"http://{printer.api.ip_address}/print_bill"
bill = cls.report_bill(records)
if 'employee.rec_name' in context.keys():
user_name = context['employee.rec_name']
else:
user_name = ""
content = {
"content": str(json.dumps(bill)),
"printer_type": "",
"ip_printer": "",
"user_name": user_name,
"idVendor": "",
"idProduct": ""}
if printer.type_ == 'network':
content["printer_type"] = "Network"
content["ip_printer"] = str(printer.ip_address)
else:
if printer.type_ == 'usb':
content["printer_type"] = "USB"
content["idVendor"] = str(printer.idVendor)
content["idProduct"] = str(printer.idProduct)
headers = {"accept": 'application/json',
'Content-Type': 'application/json'}
requests.post(
url, data=json.dumps(content), headers=headers, timeout=5)
@classmethod
@ModelView.button
def kitchen(cls, records):
pool = Pool()
context = Transaction().context
shop = context['shop']
Printer = pool.get('sale.printer')
printers = Printer.search([('zone', '=', 'kitchen'),
('shop', '=', shop)])
record = records[0]
if not printers:
return
printer = printers[0]
url = f"http://{printer.api.ip_address}/order_kitchen"
customer_order = cls.report_customer_order(records)
if 'employee.rec_name' in context.keys():
user_name = context['employee.rec_name']
else:
user_name = ""
content = {"content": str(json.dumps(customer_order)),
"printer_type": "",
"ip_printer": "",
"user_name": user_name,
"idVendor": "",
"idProduct": ""}
if printer.type_ == 'network':
content["printer_type"] = "Network"
content["ip_printer"] = str(printer.ip_address)
else:
if printer.type_ == 'usb':
content["printer_type"] = "USB"
content["idVendor"] = str(printer.idVendor)
content["idProduct"] = str(printer.idProduct)
headers = {"accept": 'application/json',
'Content-Type': 'application/json'}
cls.impreso([record])
requests.post(
url, data=str(json.dumps(content)),
headers=headers)
@classmethod
@ModelView.button
def bar(cls, records):
pool = Pool()
context = Transaction().context
shop = context['shop']
Printer = pool.get('sale.printer')
printers = Printer.search([('zone', '=', 'bar'),
('shop', '=', shop)])
record = records[0]
if not printers:
return
printer = printers[0]
url = f"http://{printer.api.ip_address}/order_bar"
customer_order = cls.report_customer_order(records)
cls.impreso([record])
if 'employee.rec_name' in context.keys():
user_name = context['employee.rec_name']
else:
user_name = ""
content = {
"content": str(json.dumps(customer_order)),
"printer_type": "",
"ip_printer": "",
"user_name": user_name,
"idVendor": "",
"idProduct": ""}
if printer.type_ == 'network':
content["printer_type"] = "Network"
content["ip_printer"] = str(printer.ip_address)
else:
if printer.type_ == 'usb':
content["printer_type"] = "USB"
content["idVendor"] = str(printer.idVendor)
content["idProduct"] = str(printer.idProduct)
headers = {
"accept": 'application/json',
'Content-Type': 'application/json'}
requests.post(url, data=json.dumps(content),
headers=headers)
class Line(metaclass=PoolMeta):
"Sale Line Fast Food"
__name__ = 'sale.line'
pizza = fields.Integer("Pizza")
impreso = fields.Boolean("Impreso")
bought_pizza = fields.Boolean("Sold pizza")
@classmethod
def delete(cls, lines):
for line in lines:
if line.impreso and line.type == 'line':
cls._create_sale_line_deleted_log(line)
super(Line, cls).delete(lines)
@fields.depends('product', 'unit', 'sale',
'_parent_sale.party', '_parent_sale.invoice_party',
'_parent_sale.party', '_parent_sale.invoice_party',
'_parent_sale.pizza_number',
methods=['compute_taxes', 'compute_unit_price',
'on_change_with_amount'])
'_parent_product.template',
'_parent_product._parent_template.pizza',
methods=['compute_taxes', 'compute_unit_price',
'on_change_with_amount'])
def on_change_product(self):
super(Line, self).on_change_product()
if self.product.pizza:
if self.product and self.product.template.pizza:
self.pizza = self.sale.pizza_number
self.bought_pizza = True
else:
self.bought_pizza = False
def get_production(self, product_quantities):
"Return production for the sale line"
Production = super(Line, self).get_production(product_quantities)
return Production
class SaleLineDeletedLog(metaclass=PoolMeta):
"""Sale Line Deleted Log"""
__name__ = 'sale.line_deleted'
printed = fields.Boolean("Printed")

View File

@ -2,24 +2,57 @@
<!--This file file is part of Tryton. The COPYRIGHT file at the top level
of this repository contains the full copyright notices and license terms. -->
<tryton>
<record model="ir.ui.view" id="sale_view_tree">
<field name="model">sale.sale</field>
<field name="inherit" ref="sale.sale_view_tree"/>
<field name="name">sale_tree</field>
</record>
<record model="ir.ui.view" id="sale_view_form">
<field name="model">sale.sale</field>
<field name="inherit" ref="sale.sale_view_form"/>
<field name="name">sale_form</field>
</record>
<record model="ir.ui.view" id="sale_line_view_form">
<field name="model">sale.line</field>
<field name="inherit" ref="sale.sale_line_view_form"/>
<field name="name">sale_line_form</field>
</record>
<record model="ir.model.button" id="sale_add_pizza_button">
<field name="name">add_pizza</field>
<field name="string">Add Pizza</field>
<field name="model" search="[('model', '=', 'sale.sale')]"/>
</record>
<data>
<record model="ir.ui.view" id="sale_view_tree">
<field name="model">sale.sale</field>
<field name="inherit" ref="sale.sale_view_tree"/>
<field name="name">sale_tree</field>
</record>
<record model="ir.ui.view" id="sale_view_form">
<field name="model">sale.sale</field>
<field name="inherit" ref="sale.sale_view_form"/>
<field name="name">sale_form</field>
</record>
<record model="ir.ui.view" id="sale_line_view_form">
<field name="model">sale.line</field>
<field name="inherit" ref="sale.sale_line_view_form"/>
<field name="name">sale_line_form</field>
</record>
<record model="ir.model.button" id="sale_add_pizza_button">
<field name="name">add_pizza</field>
<field name="string">Add Pizza</field>
<field name="model">sale.sale</field>
</record>
<record model="ir.model.button" id="sale_order_kitchen_button">
<field name="name">kitchen</field>
<field name="string">Kitchen</field>
<field name="model">sale.sale</field>
</record>
<record model="ir.model.button" id="sale_order_bar_button">
<field name="name">bar</field>
<field name="string">Bar</field>
<field name="model">sale.sale</field>
</record>
<record model="ir.model.button" id="sale_print_bill_button">
<field name="name">print_bill</field>
<field name="string">Bill</field>
<field name="model">sale.sale</field>
</record>
<record model="ir.model.button" id="sale_impreso_button">
<field name="name">impreso</field>
<field name="string">Impreso</field>
<field name="model">sale.sale</field>
</record>
<record model="ir.action.report" id="report_customer_order">
<field name="name">Customer Order</field>
<field name="model">sale.sale</field>
<field name="report_name">sale.customer_order</field>
<field name="report">sale_fast_food/report/customer_order.fodt</field>
</record>
<record model="ir.action.keyword" id="report_customer_order_keyword">
<field name="keyword">form_print</field>
<field name="model">sale.sale,-1</field>
<field name="action" ref="report_customer_order"/>
</record>
</data>
</tryton>

View File

@ -127,7 +127,7 @@ setup(name=name,
],
license='GPL-3',
python_requires='>=3.7',
install_requires=requires,
# install_requires=requires,
extras_require={
'test': tests_require,
},

8
tests/test_scenario.py Normal file
View File

@ -0,0 +1,8 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.tests.test_tryton import load_doc_tests
def load_tests(*args, **kwargs):
return load_doc_tests(__name__, __file__, *args, **kwargs)

View File

@ -1,9 +1,21 @@
[tryton]
version=6.4
version=7.6.0
depends:
ir
res
product
sale
sale_discount
sale_supply_production
sale_line_delete_log
sale_printer
production
account_invoice
sale_shop
sale_pos_table
xml:
product.xml
sale.xml
user.xml
report_close_statement.xml
report.xml

10
user.py Normal file
View File

@ -0,0 +1,10 @@
from trytond.model import fields
from trytond.pool import PoolMeta
class User(metaclass=PoolMeta):
"User"
__name__ = 'res.user'
waiter = fields.Boolean('Waiter')
not_restaurant = fields.Boolean('Not Restaurant')

13
user.xml Normal file
View File

@ -0,0 +1,13 @@
<?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="user_view_form" >
<field name="name">user_form</field>
<field name="inherit" ref="res.user_view_form"/>
<field name="model">res.user</field>
</record>
</data>
</tryton>

View 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>

View File

@ -0,0 +1,15 @@
<?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 col="6">
<label name="company"/>
<field name="company"/>
<label name="currency"/>
<field name="currency"/>
<newline/>
<label name="date"/>
<field name="date"/>
<label name="shop"/>
<field name="shop"/>
</form>

View File

@ -2,10 +2,22 @@
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="//field[@name='salable']" position="after">
<label name="pizza"/>
<field name="pizza"/>
<label name="pizza_topping"/>
<field name="pizza_topping"/>
</xpath>
<xpath expr="//field[@name='salable']" position="after">
<label name="pizza"/>
<field name="pizza"/>
<label name="pizza_topping"/>
<field name="pizza_topping"/>
<label name="tip"/>
<field name="tip"/>
<label name="kitchen"/>
<field name="kitchen"/>
<label name="bar"/>
<field name="bar"/>
</xpath>
<xpath expr="//field[@name='default_uom']" position="after">
<group id="boms">
<label name="boms"/>
<field name="boms"/>
</group>
</xpath>
</data>

View 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>

View File

@ -1,10 +1,27 @@
<?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. -->
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="//field[@name='reference']" position="after">
<label name="pizza_number"/>
<field name="pizza_number"/>
<button name="add_pizza"/>
<xpath expr="//field[@name='lines']" position="after">
<group col="-1" colspan="5" id="restaturant_buttons">
<button name="kitchen" icon="tryton-print"/>
<button name="bar" icon="tryton-print"/>
<button name="print_bill" icon="tryton-print"/>
<button name="add_pizza"/>
<button name="impreso"/>
</group>
<newline/>
</xpath>
<xpath expr="/form/notebook/page[@id='sale']/group[@id='amount']/field[@name='tax_amount']"
position="after">
<label name="total_discount"/>
<field name="total_discount"/>
<label name="total_tip"/>
<field name="total_tip"/>
</xpath>
<xpath expr="/form/notebook/page[@id='sale']/group[@id='amount']/field[@name='total_amount']"
position="after">
<label name="credito"/>
<field name="credito"/>
</xpath>
</data>

View File

@ -5,5 +5,9 @@
<xpath expr="//field[@name='product']" position="after">
<label name="pizza"/>
<field name="pizza"/>
<label name="impreso"/>
<field name="impreso"/>
<label name="bought_pizza"/>
<field name="bought_pizza"/>
</xpath>
</data>

12
view/sale_tree.xml Normal file
View File

@ -0,0 +1,12 @@
<?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. -->
<data>
<xpath expr="//field[@name='shop']" position="after">
<field name="zone" string="Zona"/>
<field name="table" string="Mesa"/>
</xpath>
<xpath expr="//field[@name='untaxed_amount']" position="after">
<field name="total_amount"/>
</xpath>
</data>

View 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. -->
<tree>
<field name="user"/>
<field name="completed_sales" sum="1"/>
<field name="untaxed_amount" sum="1"/>
<field name="tax_amount" sum="1"/>
<field name="total_amount" sum="1"/>
<field name="total_tip_amount" sum="1"/>
</tree>

View File

@ -0,0 +1,12 @@
<?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="zone"/>
<field name="table"/>
<field name="completed_sales" sum="1"/>
<field name="untaxed_amount" sum="1"/>
<field name="tax_amount" sum="1"/>
<field name="total_amount" sum="1"/>
<field name="total_tip_amount" sum="1"/>
</tree>

11
view/user_form.xml Normal file
View 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. -->
<data>
<xpath expr="//field[@name='name']" position="after">
<label name="waiter"/>
<field name="waiter"/>
<label name="not_restaurant"/>
<field name="not_restaurant"/>
</xpath>
</data>