forked from Mapan/odoo17e
281 lines
12 KiB
Python
281 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import models, fields, api
|
|
from odoo.exceptions import UserError
|
|
from odoo.tools.translate import _
|
|
from datetime import datetime
|
|
|
|
|
|
class PosOrder(models.Model):
|
|
_inherit = "pos.order"
|
|
|
|
blackbox_date = fields.Char(
|
|
"Fiscal Data Module date",
|
|
help="Date returned by the Fiscal Data Module.",
|
|
readonly=True,
|
|
)
|
|
blackbox_time = fields.Char(
|
|
"Fiscal Data Module time",
|
|
help="Time returned by the Fiscal Data Module.",
|
|
readonly=True,
|
|
)
|
|
blackbox_pos_receipt_time = fields.Datetime("Receipt time", readonly=True)
|
|
blackbox_ticket_counters = fields.Char(
|
|
"Fiscal Data Module ticket counters",
|
|
help="Ticket counter returned by the Fiscal Data Module (format: counter / total event type)",
|
|
readonly=True,
|
|
)
|
|
blackbox_unique_fdm_production_number = fields.Char(
|
|
"Fiscal Data Module ID",
|
|
help="Unique ID of the blackbox that handled this order",
|
|
readonly=True,
|
|
)
|
|
blackbox_vsc_identification_number = fields.Char(
|
|
"VAT Signing Card ID",
|
|
help="Unique ID of the VAT signing card that handled this order",
|
|
readonly=True,
|
|
)
|
|
blackbox_signature = fields.Char(
|
|
"Electronic signature",
|
|
help="Electronic signature returned by the Fiscal Data Module",
|
|
readonly=True,
|
|
)
|
|
blackbox_tax_category_a = fields.Monetary(
|
|
readonly=True,
|
|
string="Total tax for category A",
|
|
help="This is the total amount of the 21% tax",
|
|
)
|
|
blackbox_tax_category_b = fields.Monetary(
|
|
readonly=True,
|
|
string="Total tax for category B",
|
|
help="This is the total amount of the 12% tax",
|
|
)
|
|
blackbox_tax_category_c = fields.Monetary(
|
|
readonly=True,
|
|
string="Total tax for category C",
|
|
help="This is the total amount of the 6% tax",
|
|
)
|
|
blackbox_tax_category_d = fields.Monetary(
|
|
readonly=True,
|
|
string="Total tax for category D",
|
|
help="This is the total amount of the 0% tax",
|
|
)
|
|
plu_hash = fields.Char(help="Eight last characters of PLU hash")
|
|
pos_version = fields.Char(help="Version of Odoo that created the order")
|
|
|
|
def _create_log_description(self, blackbox_order_sequence, custom_data=None):
|
|
currency = self.currency_id
|
|
lines = []
|
|
total = 0
|
|
rounding_applied = 0
|
|
hash_string = ''
|
|
title = ''
|
|
|
|
if custom_data:
|
|
for line in custom_data['lines']:
|
|
line = line[2]
|
|
product_name = self.env['product.product'].browse(line['product_id']).name
|
|
line_description = "{qty} x {product_name}: {price}".format(
|
|
qty=line['qty'],
|
|
product_name=product_name,
|
|
price=round(line['price_subtotal_incl'], currency.decimal_places)
|
|
)
|
|
|
|
if line['discount']:
|
|
line_description += " (disc: {discount}%)".format(discount=line['discount'])
|
|
|
|
lines.append(line_description)
|
|
total = round(custom_data['amount_total'], currency.decimal_places) if self.state == "draft" else round(custom_data['amount_paid'], currency.decimal_places)
|
|
rounding_applied = 0 if self.state == "draft" else round(custom_data['amount_total'] - custom_data['amount_paid'], currency.decimal_places)
|
|
hash_string = custom_data['blackbox_plu_hash']
|
|
sale_type = ""
|
|
if round(custom_data['amount_total'], currency.decimal_places) > 0:
|
|
sale_type = " SALES"
|
|
elif round(custom_data['amount_total'], currency.decimal_places) < 0:
|
|
sale_type = " REFUNDS"
|
|
else:
|
|
if len(custom_data['lines']) and custom_data['lines'][0][2]['qty'] >= 0:
|
|
sale_type = " SALES"
|
|
else:
|
|
sale_type = " REFUNDS"
|
|
title = ("PRO FORMA" if self.state == "draft" else "NORMAL") + sale_type
|
|
else:
|
|
for line in self.lines:
|
|
line_description = f"{line.qty} x {line.product_id.name}: {round(line.price_subtotal_incl, currency.decimal_places)}"
|
|
|
|
if line.discount:
|
|
line_description += f" (disc: {line.discount}%)"
|
|
|
|
lines.append(line_description)
|
|
total = round(self.amount_total, currency.decimal_places) if self.state == "draft" else round(self.amount_paid, currency.decimal_places)
|
|
rounding_applied = 0 if self.state == "draft" else round(self.amount_total - self.amount_paid, currency.decimal_places)
|
|
hash_string = self.plu_hash
|
|
|
|
sale_type = ""
|
|
rounded_total_amount = round(self.amount_total, currency.decimal_places)
|
|
if rounded_total_amount > 0:
|
|
sale_type = " SALES"
|
|
elif rounded_total_amount < 0:
|
|
sale_type = " REFUNDS"
|
|
else:
|
|
if len(self.lines) and self.lines[0].qty >= 0:
|
|
sale_type = " SALES"
|
|
else:
|
|
sale_type = " REFUNDS"
|
|
|
|
title = ("PRO FORMA" if self.state == "draft" else "NORMAL") + sale_type
|
|
|
|
order_type = self.config_id.name + (' Pro Forma/' if self.state == 'draft' else ' Pos Order/')
|
|
|
|
description = """
|
|
{title}
|
|
Date: {create_date}
|
|
Internal Ref: {pos_reference}
|
|
Sequence: {blackbox_sequence}
|
|
Cashier: {cashier_name}
|
|
Order lines: {lines}
|
|
Total: {total}
|
|
Rounding: {rounding_applied}
|
|
Ticket Counter: {ticket_counters}
|
|
Hash: {hash}
|
|
POS Version: {pos_version}
|
|
FDM ID: {fdm_id}
|
|
POS ID: {config_name}
|
|
FDM Identifier: {fdmIdentifier}
|
|
""".format(
|
|
title=title,
|
|
create_date=self.create_date,
|
|
cashier_name=self.employee_id.name or self.user_id.name,
|
|
lines="\n* " + "\n* ".join(lines),
|
|
total=total,
|
|
pos_reference=self.pos_reference,
|
|
blackbox_sequence=order_type + f"{blackbox_order_sequence:05}",
|
|
hash=hash_string,
|
|
pos_version=self.pos_version,
|
|
ticket_counters=custom_data['blackbox_ticket_counters'] if custom_data else self.blackbox_ticket_counters,
|
|
fdm_id=custom_data['blackbox_unique_fdm_production_number'] if custom_data else self.blackbox_unique_fdm_production_number,
|
|
config_name=self.config_id.name,
|
|
fdmIdentifier=self.config_id.certified_blackbox_identifier,
|
|
rounding_applied=rounding_applied,
|
|
)
|
|
|
|
return description
|
|
|
|
@api.ondelete(at_uninstall=False)
|
|
def unlink_if_blackboxed(self):
|
|
for order in self:
|
|
if order.config_id.iface_fiscal_data_module:
|
|
raise UserError(_("Deleting of registered orders is not allowed."))
|
|
|
|
def write(self, values):
|
|
for order in self:
|
|
if order.config_id.iface_fiscal_data_module and order.state != "draft":
|
|
white_listed_fields = [
|
|
"state",
|
|
"account_move",
|
|
"picking_id",
|
|
"invoice_id",
|
|
"last_order_preparation_change",
|
|
"partner_id",
|
|
"to_invoice"
|
|
]
|
|
|
|
for field in values:
|
|
if field not in white_listed_fields:
|
|
raise UserError(_("Modifying registered orders is not allowed."))
|
|
|
|
return super(PosOrder, self).write(values)
|
|
|
|
@api.model
|
|
def create_from_ui(self, orders, draft=False):
|
|
res = super().create_from_ui(orders, draft)
|
|
if self.env['pos.session'].browse(orders[0]['data']['pos_session_id']).config_id.iface_fiscal_data_module:
|
|
for order in orders:
|
|
for order_res in res:
|
|
if not order['data'].get('server_id') and order_res['pos_reference'] == order['data']['name']:
|
|
order['data']['server_id'] = order_res['id']
|
|
self.create_log(orders)
|
|
return res
|
|
|
|
@api.model
|
|
def create_log(self, orders, custom_data=False):
|
|
order_ids = self.env['pos.order'].browse([order['data']['server_id'] for order in orders])
|
|
orders_bb_sequence = {order['data']['name']: order['data']['blackbox_order_sequence'] for order in orders if order['data'].get('blackbox_order_sequence')}
|
|
for order in order_ids:
|
|
if order.config_id.iface_fiscal_data_module:
|
|
custom_order = order._get_custom_data(order, orders) if custom_data else None
|
|
self.env["pos_blackbox_be.log"].sudo().create([{
|
|
"action": "create",
|
|
"model_name": order._name,
|
|
"record_name": order.pos_reference,
|
|
"description": order._create_log_description(orders_bb_sequence[order.pos_reference], custom_data=custom_order),
|
|
}])
|
|
if custom_order:
|
|
order.session_id._update_pro_forma(order, custom_order)
|
|
else:
|
|
order.session_id._update_pro_forma(order)
|
|
|
|
def _get_custom_data(self, order, orders):
|
|
custom_data = {}
|
|
for order_data in orders:
|
|
if order_data['data']['name'] == order.pos_reference:
|
|
custom_data = order_data['data']
|
|
break
|
|
return custom_data
|
|
|
|
@api.model
|
|
def _order_fields(self, ui_order):
|
|
fields = super()._order_fields(ui_order)
|
|
|
|
config_id = self.env["pos.session"].browse(fields["session_id"]).config_id
|
|
|
|
if config_id.certified_blackbox_identifier:
|
|
date = ui_order.get("blackbox_date")
|
|
time = ui_order.get("blackbox_time")
|
|
|
|
update_fields = {
|
|
"blackbox_date": date,
|
|
"blackbox_time": time,
|
|
"blackbox_pos_receipt_time": datetime.strptime(
|
|
date + " " + time, "%d-%m-%Y %H:%M:%S"
|
|
) if date else False,
|
|
"blackbox_ticket_counters": ui_order.get("blackbox_ticket_counters"),
|
|
"blackbox_unique_fdm_production_number": ui_order.get("blackbox_unique_fdm_production_number"),
|
|
"blackbox_vsc_identification_number": ui_order.get("blackbox_vsc_identification_number"),
|
|
"blackbox_signature": ui_order.get("blackbox_signature"),
|
|
"blackbox_tax_category_a": ui_order.get("blackbox_tax_category_a"),
|
|
"blackbox_tax_category_b": ui_order.get("blackbox_tax_category_b"),
|
|
"blackbox_tax_category_c": ui_order.get("blackbox_tax_category_c"),
|
|
"blackbox_tax_category_d": ui_order.get("blackbox_tax_category_d"),
|
|
"plu_hash": ui_order.get("blackbox_plu_hash"),
|
|
"pos_version": ui_order.get("blackbox_pos_version"),
|
|
}
|
|
|
|
fields.update(update_fields)
|
|
|
|
return fields
|
|
|
|
def _refund(self):
|
|
for order in self:
|
|
if order.config_id.iface_fiscal_data_module:
|
|
for line in self.lines:
|
|
if line.product_id in [self.env.ref('pos_blackbox_be.product_product_work_in', raise_if_not_found=False), self.env.ref('pos_blackbox_be.product_product_work_out', raise_if_not_found=False)]:
|
|
raise UserError(_("Refunding of WORK IN/WORK OUT orders is not allowed."))
|
|
return super()._refund()
|
|
|
|
|
|
class PosOrderLine(models.Model):
|
|
_inherit = "pos.order.line"
|
|
|
|
vat_letter = fields.Selection(
|
|
[("A", "A"), ("B", "B"), ("C", "C"), ("D", "D")],
|
|
help="The VAT letter is related to the amount of the tax. A=21%, B=12%, C=6% and D=0%.",
|
|
)
|
|
|
|
def write(self, values):
|
|
if values.get("vat_letter"):
|
|
raise UserError(_("Can't modify fields related to the Fiscal Data Module."))
|
|
|
|
return super(PosOrderLine, self).write(values)
|