20 Commits

Author SHA1 Message Date
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
14 changed files with 434 additions and 188 deletions

View File

@@ -10,6 +10,7 @@ def register():
invoice.InvoiceLine, invoice.InvoiceLine,
sale.Sale, sale.Sale,
sale.Line, sale.Line,
sale.SaleLineDeletedLog,
user.User, user.User,
production.Production, production.Production,
report_close_statement.ReportCloseStatementStart, report_close_statement.ReportCloseStatementStart,

View File

@@ -1,7 +1,5 @@
from trytond.pool import Pool, PoolMeta from trytond.pool import PoolMeta
from trytond.model import ModelView, fields from trytond.pyson import Eval
from trytond.exceptions import UserError
from trytond.pyson import Eval
class InvoiceLine(metaclass=PoolMeta): class InvoiceLine(metaclass=PoolMeta):
@@ -13,4 +11,3 @@ class InvoiceLine(metaclass=PoolMeta):
cls.product.states['required'] = (Eval('type') == 'line') cls.product.states['required'] = (Eval('type') == 'line')
cls.unit_price.domain = [] cls.unit_price.domain = []

View File

@@ -1,6 +1,6 @@
from trytond.pool import Pool, PoolMeta from trytond.pool import PoolMeta
from trytond.model import fields from trytond.model import fields
from trytond.pyson import Eval, Bool from trytond.pyson import Eval
class Product(metaclass=PoolMeta): class Product(metaclass=PoolMeta):

View File

@@ -1,23 +1,21 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of # 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.
from decimal import Decimal from decimal import Decimal
from trytond.pool import Pool, PoolMeta from trytond.pool import Pool, PoolMeta
from trytond.model import fields from trytond.model import fields
from trytond.modules.product import price_digits, round_price
from trytond.exceptions import UserError
BOM_CHANGES = ['bom', 'product', 'quantity', 'uom', 'warehouse', 'location', BOM_CHANGES = ['bom', 'product', 'quantity', 'uom', 'warehouse', 'location',
'company', 'inputs', 'outputs'] 'company', 'inputs', 'outputs']
class Production(metaclass=PoolMeta): class Production(metaclass=PoolMeta):
"Production" "Production"
__name__ = 'production' __name__ = 'production'
@fields.depends(
@fields.depends(*BOM_CHANGES) 'bom', 'product', 'uom', 'quantity', 'company', 'inputs', 'outputs',
methods=['_explode_move_values'])
def explode_bom(self): def explode_bom(self):
pool = Pool() pool = Pool()
Uom = pool.get('product.uom') Uom = pool.get('product.uom')
@@ -25,37 +23,34 @@ class Production(metaclass=PoolMeta):
return return
factor = self.bom.compute_factor(self.product, self.quantity or 0, factor = self.bom.compute_factor(self.product, self.quantity or 0,
self.uom) self.uom)
inputs = [] inputs = []
for input_ in self.bom.inputs: for input_ in self.bom.inputs:
if input_.product.producible: # if input_.product.producible:
for input_ in input_.product.template.boms.inputs: # for input_ in input_.product.template.boms.inputs:
quantity = input_.compute_quantity(factor) quantity = input_.compute_quantity(factor)
move = self._explode_move_values( move = self._explode_move_values('input', input_, quantity)
self.picking_location, self.location, self.company, if move:
input_, quantity) inputs.append(move)
if move: quantity = Uom.compute_qty(
inputs.append(move) input_.uom, quantity,
quantity = Uom.compute_qty(input_.uom, quantity, input_.product.default_uom, round=False)
input_.product.default_uom, round=False) # else:
else: # quantity = input_.compute_quantity(factor)
quantity = input_.compute_quantity(factor) # move = self._explode_move_values('output', input_, quantity)
move = self._explode_move_values( # if move:
self.picking_location, self.location, self.company, # inputs.append(move)
input_, quantity) # quantity = Uom.compute_qty(
if move: # input_.uom, quantity,
inputs.append(move) # input_.product.default_uom, round=False)
quantity = Uom.compute_qty(input_.uom, quantity,
input_.product.default_uom, round=False)
self.inputs = inputs self.inputs = inputs
outputs = [] outputs = []
for output in self.bom.outputs: for output in self.bom.outputs:
quantity = output.compute_quantity(factor) quantity = output.compute_quantity(factor)
move = self._explode_move_values( move = self._explode_move_values('output', output,
self.location, self.output_location, self.company, output, quantity)
quantity)
if move: if move:
move.unit_price = Decimal(0) move.unit_price = Decimal(0)
outputs.append(move) outputs.append(move)

View File

@@ -43,10 +43,11 @@ class ReportCloseStatementStart(ModelView):
@classmethod @classmethod
def default_shop(cls): def default_shop(cls):
context = Transaction().context context = Transaction().context
shop = context['shop'] if context:
shop = context['shop']
if shop: if shop:
return shop return shop
return
class PrintReportCloseStatement(Wizard): class PrintReportCloseStatement(Wizard):
@@ -108,10 +109,10 @@ class CashRegister(Report):
return return
journals = [j.id for j in device.journals] journals = [j.id for j in device.journals]
statements = Statement.search([ statements = Statement.search([
('journal', 'in', journals), ('journal', 'in', journals),
('state', 'in', ['validated', 'posted']), ('state', 'in', ['validated', 'posted']),
('date', '=', date) ('date', '=', date)
]) ])
return statements return statements
def _get_invoices_by_subtype(date, shop): def _get_invoices_by_subtype(date, shop):
@@ -173,7 +174,7 @@ class CashRegister(Report):
amount_tips.append(info_pizzas_sold['amount_tip']) amount_tips.append(info_pizzas_sold['amount_tip'])
total_amount += sale.total_amount total_amount += sale.total_amount
untaxed_amount_for_tax = round((tax_amount * 100)/Decimal('8.0'), 2) untaxed_amount_for_tax = round((tax_amount * 100) / Decimal('8.0'), 2)
statements = cls._get_statements_by_date(data['date']) statements = cls._get_statements_by_date(data['date'])
if statements: if statements:
@@ -184,7 +185,7 @@ class CashRegister(Report):
'total_amount': sum( 'total_amount': sum(
(line.amount for line in statement.lines (line.amount for line in statement.lines
if line.description), Decimal(0)) if line.description), Decimal(0))
} for statement in statements] } for statement in statements]
report_context['total_statements'] = sum( report_context['total_statements'] = sum(
[s['total_amount'] for s in report_context['statements']]) [s['total_amount'] for s in report_context['statements']])

185
sale.py
View File

@@ -2,7 +2,6 @@ from trytond.pool import Pool, PoolMeta
from trytond.model import ModelView, fields from trytond.model import ModelView, fields
from trytond.transaction import Transaction from trytond.transaction import Transaction
from trytond.modules.currency.fields import Monetary from trytond.modules.currency.fields import Monetary
from trytond.pyson import Eval
from decimal import Decimal from decimal import Decimal
import requests import requests
@@ -14,17 +13,13 @@ class Sale(metaclass=PoolMeta):
__name__ = 'sale.sale' __name__ = 'sale.sale'
pizza_number = fields.Integer("Number pizza") pizza_number = fields.Integer("Number pizza")
credito = fields.Boolean("Credito")
total_discount = fields.Function( total_discount = fields.Function(
Monetary( Monetary(
"Total Discount", digits='currency', currency='currency'), "Total Discount", digits='currency', currency='currency'),
'get_amount') 'get_amount')
total_discount_cache = fields.Numeric("Total Discount cache", digits='currency') total_discount_cache = fields.Numeric(
total_tip = fields.Function( "Total Discount cache", digits='currency')
Monetary(
"Total Tip", digits='currency', currency='currency'),
'get_amount')
total_tip_cache = fields.Numeric("Total Tip cache", digits="currency")
@classmethod @classmethod
def __setup__(cls): def __setup__(cls):
@@ -47,7 +42,6 @@ class Sale(metaclass=PoolMeta):
self.tax_amount = Decimal('0.0') self.tax_amount = Decimal('0.0')
self.total_amount = Decimal('0.0') self.total_amount = Decimal('0.0')
self.total_discount = Decimal('0.0') self.total_discount = Decimal('0.0')
self.total_tip = Decimal('0.0')
if self.lines: if self.lines:
for line in self.lines: for line in self.lines:
@@ -58,7 +52,6 @@ class Sale(metaclass=PoolMeta):
self.tax_amount = self.currency.round(self.tax_amount) self.tax_amount = self.currency.round(self.tax_amount)
self.total_amount = self.untaxed_amount + self.tax_amount self.total_amount = self.untaxed_amount + self.tax_amount
if self.currency: if self.currency:
self.total_tip = self.currency.round(self.total_tip)
self.total_discount = self.currency.round(self.total_discount) self.total_discount = self.currency.round(self.total_discount)
self.total_amount = self.currency.round(self.total_amount) self.total_amount = self.currency.round(self.total_amount)
@@ -69,7 +62,6 @@ class Sale(metaclass=PoolMeta):
sale.tax_amount_cache = sale.tax_amount sale.tax_amount_cache = sale.tax_amount
sale.total_amount_cache = sale.total_amount sale.total_amount_cache = sale.total_amount
sale.total_discount_cache = sale.total_discount sale.total_discount_cache = sale.total_discount
sale.total_tip_cache = sale.total_tip
cls.save(sales) cls.save(sales)
@classmethod @classmethod
@@ -78,7 +70,6 @@ class Sale(metaclass=PoolMeta):
tax_amount = {} tax_amount = {}
total_amount = {} total_amount = {}
total_discount = {} total_discount = {}
total_tip = {}
if {'tax_amount', 'total_amount'} & set(names): if {'tax_amount', 'total_amount'} & set(names):
compute_taxes = True compute_taxes = True
else: else:
@@ -91,23 +82,20 @@ class Sale(metaclass=PoolMeta):
if (sale.state in cls._states_cached if (sale.state in cls._states_cached
and sale.untaxed_amount_cache is not None and sale.untaxed_amount_cache is not None
and sale.tax_amount_cache is not None and sale.tax_amount_cache is not None
and sale.total_amount_cache is not None): and sale.total_amount_cache is not None
and sale.total_discount_cache is not None):
untaxed_amount[sale.id] = sale.untaxed_amount_cache untaxed_amount[sale.id] = sale.untaxed_amount_cache
total_discount[sale.id] = sale.total_discount_cache total_discount[sale.id] = sale.total_discount_cache
total_tip[sale.id] = sale.total_tip_cache
if compute_taxes: if compute_taxes:
tax_amount[sale.id] = sale.tax_amount_cache tax_amount[sale.id] = sale.tax_amount_cache
total_amount[sale.id] = sale.total_amount_cache total_amount[sale.id] = sale.total_amount_cache
else: else:
untaxed_amount[sale.id] = round(sum( untaxed_amount[sale.id] = round(sum(
(line.amount for line in sale.lines (line.amount for line in sale.lines
if line.type == 'line'), Decimal(0)),2) if line.type == 'line'), Decimal(0)), 2)
total_discount[sale.id] = round(sum( total_discount[sale.id] = round(sum(
(line.discount_amount * Decimal(line.quantity) for line in sale.lines (line.discount_amount for line in sale.lines
if line.discount_amount and line.type == 'line'), Decimal(0)), 2) if 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: if compute_taxes:
tax_amount[sale.id] = sale.get_tax_amount() tax_amount[sale.id] = sale.get_tax_amount()
total_amount[sale.id] = ( total_amount[sale.id] = (
@@ -118,8 +106,7 @@ class Sale(metaclass=PoolMeta):
'tax_amount': tax_amount, 'tax_amount': tax_amount,
'total_amount': total_amount, 'total_amount': total_amount,
'total_discount': total_discount, 'total_discount': total_discount,
'total_tip' : total_tip }
}
for key in list(result.keys()): for key in list(result.keys()):
if key not in names: if key not in names:
del result[key] del result[key]
@@ -141,10 +128,6 @@ class Sale(metaclass=PoolMeta):
@classmethod @classmethod
def get_invoice(cls, record): def get_invoice(cls, record):
pool = Pool()
ctx = Transaction().context
Shop = pool.get('sale.shop')
shop = Shop.search([('id', '=', ctx["shop"])])[0]
if record.state != 'draft' and record.invoices: if record.state != 'draft' and record.invoices:
invoice = record.invoices[0] invoice = record.invoices[0]
data = {} data = {}
@@ -180,17 +163,18 @@ class Sale(metaclass=PoolMeta):
"product": line.product.name if line.type != 'title' else None, "product": line.product.name if line.type != 'title' else None,
"quantity": line.quantity 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, "uom": line.unit.symbol if line.type != 'title' else None,
"unit_price": str(line.amount_w_tax) if line.type != 'title' else None, "unit_price": str(line.amount_w_tax)
"taxes": str(round(line.taxes[0].rate * 100, 2))+'%' if line.type != 'title' else None,
"taxes": str(round(line.taxes[0].rate * 100, 2)) + '%'
if line.type != 'title' and line.taxes else None if line.type != 'title' and line.taxes else None
} for line in record.lines if line.type == 'line' and not line.product.tip] } for line in record.lines]
data["total_discount"] = str(round(record.total_discount,2)) data["total_discount"] = str(round(record.total_discount, 2))
data["untaxed_amount"] = str(record.untaxed_amount) data["untaxed_amount"] = str(record.untaxed_amount)
data["total_tip"] = str(record.total_tip)
data["tax_amount"] = str(record.tax_amount) data["tax_amount"] = str(record.tax_amount)
data["total"] = str(record.total_amount) data["total"] = str(record.total_amount)
data["state"] = "SUBTOTAL" if record.state == "draft" else "CUENTA FINAL" data["state"] = \
"SUBTOTAL" if record.state == "draft" else "CUENTA FINAL"
if record.payments: if record.payments:
data['payments'] = [{ data['payments'] = [{
@@ -212,20 +196,18 @@ class Sale(metaclass=PoolMeta):
data["city"] = report.invoice_address.subdivision_municipality.name data["city"] = report.invoice_address.subdivision_municipality.name
data["zone"] = report.zone.name if report.zone else "" data["zone"] = report.zone.name if report.zone else ""
data["table"] = report.table.name if report.table 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,
# "quantity": line.quantity if line.type != 'title' else None,
# "uom": line.unit.name if line.type != 'title' else None}
# for line in report.lines]
data["lines"] = [{ data["lines"] = [{
'type': line.type, "type": line.type,
"product": line.product.name if line.type != 'title' else None, "product": line.product.name if line.type != "title" else None,
"description": line.description if line.type != 'title' else None, "description": line.description if line.type != "title" else None,
"quantity": line.quantity 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} "uom": line.unit.name if line.type != "title" else None}
for line in report.lines if not line.impreso] 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 return data
@@ -248,6 +230,10 @@ class Sale(metaclass=PoolMeta):
line.analytic_accounts = tuple() line.analytic_accounts = tuple()
line.impreso = True line.impreso = True
line.save() line.save()
for line in record.delete_lines:
line.printed = True
line.save()
record.save() record.save()
@classmethod @classmethod
@@ -271,13 +257,28 @@ class Sale(metaclass=PoolMeta):
user_name = context['employee.rec_name'] user_name = context['employee.rec_name']
else: else:
user_name = "" user_name = ""
content = {"content": str(json.dumps(bill)),
"ip_printer": str(printer.ip_address), content = {
"user_name": user_name} "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', headers = {"accept": 'application/json',
'Content-Type': 'application/json'} 'Content-Type': 'application/json'}
requests.post(
response = requests.post(url, data=json.dumps(content), headers=headers) url, data=json.dumps(content), headers=headers, timeout=5)
@classmethod @classmethod
@ModelView.button @ModelView.button
@@ -300,14 +301,30 @@ class Sale(metaclass=PoolMeta):
user_name = context['employee.rec_name'] user_name = context['employee.rec_name']
else: else:
user_name = "" user_name = ""
content = {"content": str(json.dumps(customer_order)), content = {"content": str(json.dumps(customer_order)),
"ip_printer": str(printer.ip_address), "printer_type": "",
"user_name": user_name} "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', headers = {"accept": 'application/json',
'Content-Type': 'application/json'} 'Content-Type': 'application/json'}
cls.impreso([record]) cls.impreso([record])
response = requests.post(url, data=json.dumps(content),
headers=headers) requests.post(
url, data=str(json.dumps(content)),
headers=headers)
@classmethod @classmethod
@ModelView.button @ModelView.button
@@ -327,17 +344,34 @@ class Sale(metaclass=PoolMeta):
url = f"http://{printer.api.ip_address}/order_bar" url = f"http://{printer.api.ip_address}/order_bar"
customer_order = cls.report_customer_order(records) customer_order = cls.report_customer_order(records)
cls.impreso([record]) cls.impreso([record])
if 'employee.rec_name' in context.keys(): if 'employee.rec_name' in context.keys():
user_name = context['employee.rec_name'] user_name = context['employee.rec_name']
else: else:
user_name = "" user_name = ""
content = {"content": str(json.dumps(customer_order)),
"ip_printer": str(printer.ip_address), content = {
"user_name": user_name} "content": str(json.dumps(customer_order)),
headers = {"accept": 'application/json', "printer_type": "",
'Content-Type': 'application/json'} "ip_printer": "",
response = requests.post(url, data=json.dumps(content), "user_name": user_name,
headers=headers) "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): class Line(metaclass=PoolMeta):
@@ -347,21 +381,18 @@ class Line(metaclass=PoolMeta):
pizza = fields.Integer("Pizza") pizza = fields.Integer("Pizza")
impreso = fields.Boolean("Impreso") impreso = fields.Boolean("Impreso")
bought_pizza = fields.Boolean("Sold pizza") bought_pizza = fields.Boolean("Sold pizza")
rate = fields.Numeric(
"Rate", digits=(16, 4),
states={
'invisible': Eval('type') != 'line',
'readonly': Eval('sale_state') != 'draft',
},
depends=['type', 'sale_state'])
@classmethod @classmethod
def default_rate(cls): def delete(cls, lines):
return 0 for line in lines:
if line.impreso:
cls._create_sale_line_deleted_log(line)
super(Line, cls).delete(lines)
@fields.depends('product', 'unit', 'sale', @fields.depends('product', 'unit', 'sale',
'_parent_sale.party', '_parent_sale.invoice_party', '_parent_sale.party', '_parent_sale.invoice_party',
'_parent_sale.pizza_number', '_parent_sale.pizza_number',
'_parent_product.pizza',
methods=['compute_taxes', 'compute_unit_price', methods=['compute_taxes', 'compute_unit_price',
'on_change_with_amount']) 'on_change_with_amount'])
def on_change_product(self): def on_change_product(self):
@@ -372,13 +403,15 @@ class Line(metaclass=PoolMeta):
else: else:
self.bought_pizza = False self.bought_pizza = False
def get_production(self): def get_production(self, product_quantities):
"Return production for the sale line" "Return production for the sale line"
Production = super(Line, self).get_production() Production = super(Line, self).get_production(product_quantities)
return Production return Production
@fields.depends('discount_rate')
def on_change_discount_rate(self): class SaleLineDeletedLog(metaclass=PoolMeta):
if self.discount_rate: """Sale Line Deleted Log"""
self.rate = self.discount_rate __name__ = 'sale.line_deleted'
printed = fields.Boolean("Printed")

104
sale.xml
View File

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

View File

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

View File

@@ -0,0 +1,209 @@
=============================
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"

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,17 +1,20 @@
[tryton] [tryton]
version=6.4 version=6.8.0
depends: depends:
ir ir
res res
product product
sale sale
sale_discount
sale_supply_production sale_supply_production
#sale_printer sale_line_delete_log
sale_printer
production production
account_invoice account_invoice
sale_shop sale_shop
sale_pos_table
xml: xml:
product.xml product.xml
sale.xml sale.xml
user.xml user.xml
report_close_statement.xml report_close_statement.xml

View File

@@ -1,5 +1,6 @@
from trytond.model import fields from trytond.model import fields
from trytond.pool import Pool, PoolMeta from trytond.pool import PoolMeta
class User(metaclass=PoolMeta): class User(metaclass=PoolMeta):
"User" "User"

View File

@@ -12,11 +12,11 @@ this repository contains the full copyright notices and license terms. -->
</group> </group>
<newline/> <newline/>
</xpath> </xpath>
<xpath expr="/form/notebook/page[@id='sale']/group[@id='amount']/field[@name='tax_amount']" position="after"> <xpath expr="/form/notebook/page[@id='sale']/group[@id='amount']/field[@name='tax_amount']"
<label name="total_discount"/> position="after">
<field name="total_discount"/> <label name="total_discount"/>
<label name="total_tip"/> <field name="total_discount"/>
<field name="total_tip"/> <label name="credito"/>
<field name="credito"/>
</xpath> </xpath>
</data> </data>

View File

@@ -10,8 +10,4 @@
<label name="bought_pizza"/> <label name="bought_pizza"/>
<field name="bought_pizza"/> <field name="bought_pizza"/>
</xpath> </xpath>
<xpath expr="//field[@name='discount_rate']" position="after">
<label name="discount_rate"/>
<field name="discount_rate" factor="100"/>
</xpath>
</data> </data>