15 Commits

20 changed files with 643 additions and 406 deletions

View File

@@ -1,23 +0,0 @@
from trytond.pool import Pool
from . import product, sale, production, invoice, user, report_close_statement
__all__ = ['register']
def register():
Pool.register(
product.Product,
invoice.InvoiceLine,
sale.Sale,
sale.Line,
sale.SaleLineDeletedLog,
user.User,
production.Production,
report_close_statement.ReportCloseStatementStart,
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')

View File

@@ -58,6 +58,98 @@ 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"
@@ -68,4 +160,4 @@ msgstr "Imprimir"
msgctxt "model:ir.action,name:wizard_print_cash_register"
msgid "Print cash register"
msgstr "Imprimir arqueo de caja"
msgstr "Imprimir arqueo de caja"

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>

View File

@@ -1,8 +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 decimal import Decimal
from trytond.pool import Pool, PoolMeta
from trytond.model import fields
# from decimal import Decimal
from trytond.pool import PoolMeta
# from trytond.model import fields
BOM_CHANGES = ['bom', 'product', 'quantity', 'uom', 'warehouse', 'location',
@@ -13,6 +13,7 @@ class Production(metaclass=PoolMeta):
"Production"
__name__ = 'production'
"""
@fields.depends(
'bom', 'product', 'uom', 'quantity', 'company', 'inputs', 'outputs',
methods=['_explode_move_values'])
@@ -55,3 +56,4 @@ class Production(metaclass=PoolMeta):
move.unit_price = Decimal(0)
outputs.append(move)
self.outputs = outputs
"""

62
pyproject.toml Normal file
View File

@@ -0,0 +1,62 @@
[build-system]
requires = ['hatchling >= 1', 'hatch-tryton']
build-backend = 'hatchling.build'
[project]
name = 'trytondo_sale_fast_food'
dynamic = ['version', 'dependencies', 'optional-dependencies', 'authors', 'readme']
requires-python = '>=3.10'
maintainers = [
{name = "OneCluster", email = "info@onecluster.org"},
]
description = "Fast food point of sale management (products, sales and closing reports)"
license = 'GPL-3.0-or-later'
license-files = ['LICENSE', 'icons/LICENSE', 'COPYRIGHT']
keywords = ["tryton", "sale", "point of sale", "fast food", "restaurant"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Plugins",
"Framework :: Tryton",
"Topic :: Office/Business",
"Topic :: Office/Business :: Financial :: Point-Of-Sale",
"Topic :: Software Development :: Libraries :: Python Modules",
]
[project.entry-points.'trytond.modules']
sale_fast_food = 'trytond.modules.sale_fast_food'
[project.urls]
homepage = "https://www.onecluster.org/"
documentation = "https://docs.tryton.org/"
forum = "https://www.tryton.org/forum"
issues = "https://bugs.tryton.org/tryton"
funding = "https://www.tryton.org/donate"
[tool.hatch.build]
include = [
'**/tryton.cfg',
'**/*.py',
'**/*.xml',
'view/**/*.xml',
'locale/**/*.po',
'**/*.fodt',
'icons/**/*.svg',
'tests/**/*.rst',
'tests/**/*.json',
]
exclude = ['doc']
[tool.hatch.build.targets.wheel.sources]
"" = "trytond/modules/sale_fast_food"
[tool.hatch.metadata.hooks.tryton]
dependencies = [
'python-sql >= 1.8',
'qrcode',
'requests',
]
copyright = 'COPYRIGHT'
readme = 'README.rst'
[tool.hatch.metadata.hooks.tryton.tryton-optional-dependencies]
test = ['proteus']

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>

View File

@@ -5,7 +5,6 @@ this repository contains the full copyright notices and license terms. -->
<data>
<record model="ir.action.report" id="report_close_statement">
<field name="name">Close statement</field>
<field name="model"></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>
@@ -25,4 +24,4 @@ this repository contains the full copyright notices and license terms. -->
id="menu_print_cash_register"
icon="tryton-print"/>
</data>
</tryton>
</tryton>

View File

@@ -171,6 +171,8 @@ class Sale(metaclass=PoolMeta):
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
@@ -406,7 +408,7 @@ class Line(metaclass=PoolMeta):
@classmethod
def delete(cls, lines):
for line in lines:
if line.impreso:
if line.impreso and line.type == 'line':
cls._create_sale_line_deleted_log(line)
super(Line, cls).delete(lines)

View File

@@ -21,27 +21,27 @@
<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')]"/>
<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" search="[('model', '=', 'sale.sale')]"/>
<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" search="[('model', '=', 'sale.sale')]"/>
<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" search="[('model', '=', 'sale.sale')]"/>
<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" search="[('model', '=', 'sale.sale')]"/>
<field name="model">sale.sale</field>
</record>
<record model="ir.action.report" id="report_customer_order">
<field name="name">Customer Order</field>

140
setup.py
View File

@@ -1,140 +0,0 @@
#!/usr/bin/env python3
import io
import os
import re
from configparser import ConfigParser
from setuptools import find_packages, setup
MODULE2PREFIX = {}
def read(fname):
content = io.open(
os.path.join(os.path.dirname(__file__), fname),
'r', encoding='utf-8').read()
content = re.sub(
r'(?m)^\.\. toctree::\r?\n((^$|^\s.*$)\r?\n)*', '', content)
return content
def get_require_version(name):
if minor_version % 2:
require = '%s >= %s.%s.dev0, < %s.%s'
else:
require = '%s >= %s.%s, < %s.%s'
require %= (name, major_version, minor_version,
major_version, minor_version + 1)
return require
config = ConfigParser()
config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
info = dict(config.items('tryton'))
for key in ('depends', 'extras_depend', 'xml'):
if key in info:
info[key] = info[key].strip().splitlines()
version = info.get('version', '0.0.1')
major_version, minor_version, _ = version.split('.', 2)
major_version = int(major_version)
minor_version = int(minor_version)
name = 'trytondo-sale_fast_food'
local_version = []
if os.environ.get('CI_JOB_ID'):
local_version.append(os.environ['CI_JOB_ID'])
else:
for build in ['CI_BUILD_NUMBER', 'CI_JOB_NUMBER']:
if os.environ.get(build):
local_version.append(os.environ[build])
else:
local_version = []
break
if local_version:
version += '+' + '.'.join(local_version)
requires = []
for dep in info.get('depends', []):
if not re.match(r'(ir|res)(\W|$)', dep):
prefix = MODULE2PREFIX.get(dep, 'trytond')
requires.append(get_require_version('%s_%s' % (prefix, dep)))
requires.append(get_require_version('trytond'))
tests_require = []
dependency_links = []
if minor_version % 2:
dependency_links.append(
'https://trydevpi.tryton.org/?local_version='
+ '.'.join(local_version)
+ '&mirror=github')
setup(name=name,
version=version,
description='This module allowed admin product and sale with fast food',
long_description=read('README.rst'),
author='One Cluster S.A.S',
author_email='info@onecluster.org',
url='http://www.tryton.org/',
keywords='',
package_dir={'trytond.modules.sale_fast_food': '.'},
packages=(
['trytond.modules.sale_fast_food']
+ ['trytond.modules.sale_fast_food.%s' % p
for p in find_packages()]
),
package_data={
'trytond.modules.sale_fast_food': (info.get('xml', [])
+ ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
'icons/*.svg', 'tests/*.rst']),
},
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Plugins',
'Framework :: Tryton',
'Intended Audience :: Developers',
'Intended Audience :: Financial and Insurance Industry',
'Intended Audience :: Legal Industry',
'License :: OSI Approved :: '
'GNU General Public License v3 or later (GPLv3+)',
'Natural Language :: Bulgarian',
'Natural Language :: Catalan',
'Natural Language :: Chinese (Simplified)',
'Natural Language :: Czech',
'Natural Language :: Dutch',
'Natural Language :: English',
'Natural Language :: Finnish',
'Natural Language :: French',
'Natural Language :: German',
'Natural Language :: Hungarian',
'Natural Language :: Indonesian',
'Natural Language :: Italian',
'Natural Language :: Persian',
'Natural Language :: Polish',
'Natural Language :: Portuguese (Brazilian)',
'Natural Language :: Romanian',
'Natural Language :: Russian',
'Natural Language :: Slovenian',
'Natural Language :: Spanish',
'Natural Language :: Turkish',
'Natural Language :: Ukrainian',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: Implementation :: CPython',
'Topic :: Office/Business',
],
license='GPL-3',
python_requires='>=3.7',
# install_requires=requires,
extras_require={
'test': tests_require,
},
dependency_links=dependency_links,
zip_safe=False,
entry_points="""
[trytond.modules]
sale_fast_food = trytond.modules.sale_fast_food
""", # noqa: E501
)

View File

@@ -1,209 +0,0 @@
=============================
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')
Initial data::
>>> 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.list_price = Decimal('10')
>>> template.account_category = account_category_tax
>>> template.save()
>>> product, = 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)
>>> 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
>>> sale_line.quantity = 2.0
>>> sale_line.impreso = True
>>> sale_line = SaleLine()
>>> sale.lines.append(sale_line)
>>> sale_line.type = 'comment'
>>> sale_line.description = 'Comment'
>>> sale_line = SaleLine()
>>> sale.lines.append(sale_line)
>>> sale_line.product = product
>>> sale_line.quantity = 3.0
>>> sale.save()
>>> len(sale.lines)
3
>>> sale.untaxed_amount, sale.tax_amount, sale.total_amount
(Decimal('50.00'), Decimal('5.00'), Decimal('55.00'))
Create a sale line delete log it's was printed::
>>> sale.reload()
>>> sale.lines[0].delete()
>>> sale.lines[1].delete()
>>> sale.save()
>>> len(sale.lines)
1
>>> sale.reload()
>>> len(sale.delete_lines)
1
>>> sale.delete_lines[0]
proteus.Model.get('sale.line_deleted')(1)
>>> assert isinstance(sale.delete_lines[0], Model.get('sale.line_deleted')), "it's not instance SaleLineDeleted"

View File

@@ -1,5 +1,5 @@
[tryton]
version=6.8.0
version=8.0.0
depends:
ir
res
@@ -18,3 +18,25 @@ xml:
sale.xml
user.xml
report_close_statement.xml
report.xml
[register]
model:
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
wizards:
report_close_statement.PrintReportCloseStatement
report:
report_close_statement.CashRegister

View File

@@ -7,3 +7,4 @@ class User(metaclass=PoolMeta):
__name__ = 'res.user'
waiter = fields.Boolean('Waiter')
not_restaurant = fields.Boolean('Not Restaurant')

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

@@ -2,19 +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"/>
<label name="tip"/>
<field name="tip"/>
<label name="kitchen"/>
<field name="kitchen"/>
<label name="bar"/>
<field name="bar"/>
<newline/>
<label name="boms"/>
<field name="boms" xexpand="1"/>
</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

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

View File

@@ -5,5 +5,7 @@
<xpath expr="//field[@name='name']" position="after">
<label name="waiter"/>
<field name="waiter"/>
<label name="not_restaurant"/>
<field name="not_restaurant"/>
</xpath>
</data>