forked from Mapan/odoo17e
230 lines
9.8 KiB
Python
230 lines
9.8 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.exceptions import ValidationError
|
|
from odoo.tools.translate import _
|
|
from odoo.osv.expression import OR
|
|
from odoo.service.common import exp_version
|
|
|
|
|
|
class PosConfig(models.Model):
|
|
_inherit = "pos.config"
|
|
|
|
iface_fiscal_data_module = fields.Many2one(
|
|
"iot.device",
|
|
domain="[('type', '=', 'fiscal_data_module'), '|', ('company_id', '=', False), ('company_id', '=', company_id)]",
|
|
)
|
|
certified_blackbox_identifier = fields.Char(
|
|
"Blackbox Identifier",
|
|
store=True,
|
|
compute="_compute_certified_pos",
|
|
readonly=True,
|
|
)
|
|
pos_version = fields.Char('Odoo Version', compute='_compute_odoo_version')
|
|
|
|
def _compute_odoo_version(self):
|
|
self.pos_version = exp_version()['server_serie']
|
|
|
|
@api.depends("iface_fiscal_data_module")
|
|
def _compute_certified_pos(self):
|
|
if self.iface_fiscal_data_module:
|
|
self.certified_blackbox_identifier = self.iface_fiscal_data_module.name[
|
|
-14:
|
|
]
|
|
self.env["pos_blackbox_be.log"].sudo().create([{
|
|
"action": "create",
|
|
"model_name": self._name,
|
|
"record_name": self.name,
|
|
"description": "Session started with: %s" % self.certified_blackbox_identifier,
|
|
}])
|
|
if not self.env['ir.sequence'].search([('code', '=', f'pos_blackbox_be.NS_blackbox_{self.certified_blackbox_identifier}')]):
|
|
self.env['ir.sequence'].sudo().create({
|
|
'name': _("NS Order by blackbox"),
|
|
'padding': 4,
|
|
'code': f'pos_blackbox_be.NS_blackbox_{self.certified_blackbox_identifier}',
|
|
'company_id': self.company_id.id,
|
|
})
|
|
self.env['ir.sequence'].sudo().create({
|
|
'name': _("PS Order by blackbox"),
|
|
'padding': 4,
|
|
'code': f'pos_blackbox_be.PS_blackbox_{self.certified_blackbox_identifier}',
|
|
'company_id': self.company_id.id,
|
|
})
|
|
|
|
def _check_is_certified_pos(self):
|
|
if self.certified_blackbox_identifier and not self.iface_fiscal_data_module:
|
|
raise UserError(
|
|
_("Forbidden to start a certified Point of sale without blackbox")
|
|
)
|
|
|
|
@api.depends("iface_fiscal_data_module")
|
|
def _compute_iot_device_ids(self):
|
|
super(PosConfig, self)._compute_iot_device_ids()
|
|
for config in self:
|
|
if config.is_posbox:
|
|
config.iot_device_ids += config.iface_fiscal_data_module
|
|
|
|
def _check_before_creating_new_session(self):
|
|
self._check_is_certified_pos()
|
|
if self.iface_fiscal_data_module:
|
|
self._check_self_order()
|
|
self._check_loyalty()
|
|
self._check_insz_user()
|
|
self._check_company_address()
|
|
self._check_work_product_taxes()
|
|
self._check_employee_insz_or_bis_number()
|
|
self._check_pos_category()
|
|
self._check_cash_rounding()
|
|
self._check_printer_connected()
|
|
self._check_floor_plan_ids()
|
|
self._check_is_table()
|
|
return super(PosConfig, self)._check_before_creating_new_session()
|
|
|
|
def _check_self_order(self):
|
|
for config in self:
|
|
if (
|
|
self.env['ir.module.module'].search([('name', '=', 'pos_self_order'), ('state', '=', 'installed')]) and config.self_ordering_mode not in ['nothing', 'consultation']
|
|
):
|
|
raise UserError(
|
|
_(
|
|
'Certified blackbox are not compatible with the self-ordering mode ("QR menu + Ordering" and "Kiosk") for the moment. Please disable it.'
|
|
)
|
|
)
|
|
|
|
def _check_loyalty(self):
|
|
for config in self:
|
|
if (
|
|
self.env['ir.module.module'].search([('name', '=', 'pos_loyalty'), ('state', '=', 'installed')]) and config._get_program_ids()
|
|
):
|
|
raise UserError(
|
|
_(
|
|
"Loyalty programs and gift card cannot be used on a PoS associated with a blackbox."
|
|
)
|
|
)
|
|
|
|
def _check_work_product_taxes(self):
|
|
work_in = self.env.ref("pos_blackbox_be.product_product_work_in")
|
|
work_out = self.env.ref("pos_blackbox_be.product_product_work_out")
|
|
if (
|
|
not work_in.taxes_id
|
|
or work_in.taxes_id.amount != 0
|
|
or not work_out.taxes_id
|
|
or work_out.taxes_id.amount != 0
|
|
):
|
|
raise ValidationError(
|
|
_("The WORK IN/OUT products must have a taxes with 0%.")
|
|
)
|
|
|
|
def _check_insz_user(self):
|
|
if not self.env.user.insz_or_bis_number:
|
|
raise ValidationError(_("The user must have a INSZ or BIS number."))
|
|
|
|
def _check_company_address(self):
|
|
if not self.company_id.street:
|
|
raise ValidationError(_("The address of the company must be filled."))
|
|
if not self.company_id.company_registry:
|
|
raise ValidationError(_("The VAT number of the company must be filled."))
|
|
|
|
def _check_pos_category(self):
|
|
if self.limit_categories:
|
|
if (
|
|
self.env.ref("pos_blackbox_be.pos_category_fdm").id
|
|
not in self.iface_available_categ_ids.ids
|
|
):
|
|
raise ValidationError(
|
|
_(
|
|
"You have to add the fiscal category to the limited category in order to use the fiscal data module"
|
|
)
|
|
)
|
|
|
|
def _check_is_table(self):
|
|
if self.iface_fiscal_data_module and self.module_pos_restaurant:
|
|
if not self.floor_ids:
|
|
raise ValidationError(_("You must link at least 1 floor to the configuration in order to use the fiscal data module."))
|
|
for floor in self.floor_ids:
|
|
if floor.table_ids:
|
|
return
|
|
raise ValidationError(_("You must link at least 1 table to the configuration in order to use the fiscal data module."))
|
|
|
|
@api.constrains("iface_fiscal_data_module", "fiscal_position_ids")
|
|
def _check_posbox_fp_tax_code(self):
|
|
invalid_tax_lines = [
|
|
(fp.name, tax_line.tax_dest_id.name)
|
|
for config in self
|
|
for fp in config.fiscal_position_ids
|
|
for tax_line in fp.tax_ids
|
|
if (
|
|
tax_line.tax_src_id.identification_letter
|
|
and not tax_line.tax_dest_id.identification_letter
|
|
)
|
|
]
|
|
|
|
if invalid_tax_lines:
|
|
raise ValidationError(
|
|
"Fiscal Position %s (tax %s) has an invalid tax amount. Only 21%%, 12%%, 6%% and 0%% are allowed." %
|
|
invalid_tax_lines[0]
|
|
)
|
|
|
|
@api.constrains('iface_fiscal_data_module', 'floor_ids')
|
|
def _check_floor_plan_ids(self):
|
|
if self.iface_fiscal_data_module and self.floor_ids:
|
|
for floor in self.floor_ids:
|
|
if len(floor.pos_config_ids) > 1:
|
|
raise ValidationError("Floor plans cannot be shared in different POS configurations when using the Blackbox module.")
|
|
|
|
def _check_employee_insz_or_bis_number(self):
|
|
for config in self:
|
|
if config.module_pos_hr:
|
|
all_employee_ids = self.env['hr.employee'].search(self._employee_domain(self.env.uid))
|
|
emp_names = [emp.name for emp in all_employee_ids if not emp.sudo().insz_or_bis_number] + ([self.env.user.name] if not self.env.user.employee_id.insz_or_bis_number else [])
|
|
|
|
if len(emp_names) > 0:
|
|
raise ValidationError(
|
|
_("%s must have an INSZ or BIS number.", ", ".join(emp_names))
|
|
)
|
|
|
|
def _check_cash_rounding(self):
|
|
if not self.cash_rounding:
|
|
raise ValidationError(_("Cash rounding must be enabled"))
|
|
if (
|
|
self.rounding_method.rounding != 0.05
|
|
or self.rounding_method.rounding_method != "HALF-UP"
|
|
):
|
|
raise ValidationError(
|
|
_("The rounding method must be set to 0.5 and HALF-UP")
|
|
)
|
|
|
|
def _check_printer_connected(self):
|
|
epson_printer = False
|
|
if hasattr(self, "epson_printer_ip"):
|
|
epson_printer = self.epson_printer_ip
|
|
if not self.iface_printer_id and not epson_printer:
|
|
raise ValidationError(_("A printer must be connected"))
|
|
if not self.iface_print_auto:
|
|
raise ValidationError(_("Automatic Receipt Printing must be activated"))
|
|
if not self.iface_print_skip_screen:
|
|
raise ValidationError(_("Skip Preview Screen must be activated"))
|
|
|
|
def _get_work_products(self):
|
|
empty_product = self.env['product.product']
|
|
work_in_product = self.env.ref('pos_blackbox_be.product_product_work_in', raise_if_not_found=False) or empty_product
|
|
work_out_product = self.env.ref('pos_blackbox_be.product_product_work_out', raise_if_not_found=False) or empty_product
|
|
return work_in_product | work_out_product
|
|
|
|
def _get_special_products(self):
|
|
return super()._get_special_products() | self._get_work_products()
|
|
|
|
def _get_available_product_domain(self):
|
|
domain = super()._get_available_product_domain()
|
|
if work_products := self._get_work_products():
|
|
return OR([domain, [('id', 'in', work_products.ids)]])
|
|
return domain
|
|
|
|
def get_NS_sequence_next(self):
|
|
return self.env['ir.sequence'].next_by_code(f'pos_blackbox_be.NS_blackbox_{self.certified_blackbox_identifier}')
|
|
|
|
def get_PS_sequence_next(self):
|
|
return self.env['ir.sequence'].next_by_code(f'pos_blackbox_be.PS_blackbox_{self.certified_blackbox_identifier}')
|