trytondo-sale_fast_food/sale.py
2023-09-03 19:38:13 -05:00

346 lines
13 KiB
Python

from trytond.pool import Pool, PoolMeta
from trytond.model import ModelView, fields
from trytond.transaction import Transaction
from trytond.modules.currency.fields import Monetary
from decimal import Decimal
import requests
import json
class Sale(metaclass=PoolMeta):
"Sale Fast Food"
__name__ = 'sale.sale'
pizza_number = fields.Integer("Number pizza")
total_discount = fields.Function(
Monetary(
"Total Discount", digits='currency', currency='currency'),
'get_amount')
total_discount_cache = fields.Numeric("Total Discount 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')
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_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
cls.save(sales)
@classmethod
def get_amount(cls, sales, names):
untaxed_amount = {}
tax_amount = {}
total_amount = {}
total_discount = {}
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
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 for line in sale.lines
if 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,
}
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):
pool = Pool()
ctx = Transaction().context
Shop = pool.get('sale.shop')
shop = Shop.search([('id', '=', ctx["shop"])])[0]
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_address"] = shop.address.street
data['invoice'] = cls.get_invoice(record)
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"] = str(record.total_amount)
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,
"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"] = [{
'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 if not line.impreso]
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.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()
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)),
"ip_printer": str(printer.ip_address),
"user_name": user_name}
headers = {"accept": 'application/json',
'Content-Type': 'application/json'}
response = requests.post(url, data=json.dumps(content), headers=headers)
@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)),
"ip_printer": str(printer.ip_address),
"user_name": user_name}
headers = {"accept": 'application/json',
'Content-Type': 'application/json'}
cls.impreso([record])
response = requests.post(url, data=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)),
"ip_printer": str(printer.ip_address),
"user_name": user_name}
headers = {"accept": 'application/json',
'Content-Type': 'application/json'}
response = 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")
@fields.depends('product', 'unit', 'sale',
'_parent_sale.party', '_parent_sale.invoice_party',
'_parent_sale.pizza_number',
methods=['compute_taxes', 'compute_unit_price',
'on_change_with_amount'])
def on_change_product(self):
super(Line, self).on_change_product()
if self.product and self.product.pizza:
self.pizza = self.sale.pizza_number
def get_production(self):
"Return production for the sale line"
Production = super(Line, self).get_production()
return Production