pos_self_order/models/res_config_settings.py

186 lines
8.4 KiB
Python
Raw Permalink Normal View History

# -*- coding: utf-8 -*-
import qrcode
import zipfile
from io import BytesIO
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
from odoo.tools.misc import split_every
from werkzeug.urls import url_unquote
class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"
pos_self_ordering_takeaway = fields.Boolean(related="pos_config_id.self_ordering_takeaway", readonly=False)
pos_self_ordering_service_mode = fields.Selection(related="pos_config_id.self_ordering_service_mode", readonly=False, required=True)
pos_self_ordering_mode = fields.Selection(related="pos_config_id.self_ordering_mode", readonly=False, required=True)
pos_self_ordering_alternative_fp_id = fields.Many2one(related="pos_config_id.self_ordering_alternative_fp_id", readonly=False)
pos_self_ordering_default_language_id = fields.Many2one(related="pos_config_id.self_ordering_default_language_id", readonly=False)
pos_self_ordering_available_language_ids = fields.Many2many(related="pos_config_id.self_ordering_available_language_ids", readonly=False)
pos_self_ordering_image_home_ids = fields.Many2many(related="pos_config_id.self_ordering_image_home_ids", readonly=False)
pos_self_ordering_image_brand = fields.Image(related="pos_config_id.self_ordering_image_brand", readonly=False)
pos_self_ordering_image_brand_name = fields.Char(related="pos_config_id.self_ordering_image_brand_name", readonly=False)
pos_self_ordering_pay_after = fields.Selection(related="pos_config_id.self_ordering_pay_after", readonly=False, required=True)
pos_self_ordering_default_user_id = fields.Many2one(related="pos_config_id.self_ordering_default_user_id", readonly=False)
@api.onchange("pos_self_ordering_default_user_id")
def _onchange_default_user(self):
self.ensure_one()
if self.pos_self_ordering_default_user_id and self.pos_self_ordering_mode == 'mobile':
user_id = self.pos_self_ordering_default_user_id
if not user_id.has_group("point_of_sale.group_pos_user") and not user_id.has_group("point_of_sale.group_pos_manager"):
raise ValidationError(_("The user must be a POS user"))
@api.onchange("pos_self_ordering_service_mode")
def _onchange_pos_self_order_service_mode(self):
if self.pos_self_ordering_service_mode == 'counter':
self.pos_self_ordering_pay_after = "each"
@api.onchange("pos_self_ordering_default_language_id", "pos_self_ordering_available_language_ids")
def _onchange_pos_self_order_kiosk_default_language(self):
if self.pos_self_ordering_default_language_id not in self.pos_self_ordering_available_language_ids:
self.pos_self_ordering_available_language_ids = self.pos_self_ordering_available_language_ids + self.pos_self_ordering_default_language_id
if not self.pos_self_ordering_default_language_id and self.pos_self_ordering_available_language_ids:
self.pos_self_ordering_default_language_id = self.pos_self_ordering_available_language_ids[0]
@api.onchange("pos_self_ordering_mode", "pos_module_pos_restaurant")
def _onchange_pos_self_order_kiosk(self):
if self.pos_self_ordering_mode == 'kiosk':
self.is_kiosk_mode = True
self.pos_module_pos_restaurant = False
self.pos_self_ordering_pay_after = "each"
else:
self.is_kiosk_mode = False
if not self.pos_module_pos_restaurant:
self.pos_self_ordering_service_mode = 'counter'
@api.onchange("pos_self_ordering_pay_after", "pos_self_ordering_mode")
def _onchange_pos_self_order_pay_after(self):
if self.pos_self_ordering_pay_after == "meal" and self.pos_self_ordering_mode == 'kiosk':
raise ValidationError(_("Only pay after each is available with kiosk mode."))
if self.pos_self_ordering_service_mode == 'counter' and self.pos_self_ordering_mode == 'mobile':
self.pos_self_ordering_pay_after = "each"
if self.pos_self_ordering_pay_after == "each" and not self.module_pos_preparation_display:
self.module_pos_preparation_display = True
def custom_link_action(self):
self.ensure_one()
return {
"type": "ir.actions.act_window",
"res_model": "pos_self_order.custom_link",
"views": [[False, "tree"]],
"domain": ['|', ['pos_config_ids', 'in', self.pos_config_id.id], ["pos_config_ids", "=", False]],
}
def _generate_single_qr_code(self, url):
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(url)
qr.make(fit=True)
return qr.make_image(fill_color="black", back_color="white")
def generate_qr_codes_zip(self):
if not self.pos_self_ordering_mode in ['mobile', 'consultation']:
raise ValidationError(_("QR codes can only be generated in mobile or consultation mode."))
qr_images = []
if self.pos_module_pos_restaurant:
table_ids = self.pos_config_id.floor_ids.table_ids
if not table_ids:
raise ValidationError(_("In Self-Order mode, you must have at least one table to generate QR codes"))
for table in table_ids:
qr_images.append({
'image': self._generate_single_qr_code(url_unquote(self.pos_config_id._get_self_order_url(table.id))),
'name': f"{table.floor_id.name} - {table.name}",
})
else:
qr_images.append({
'image': self._generate_single_qr_code(url_unquote(self.pos_config_id._get_self_order_url())),
'name': "generic",
})
# Create a zip with all images in qr_images
zip_buffer = BytesIO()
with zipfile.ZipFile(zip_buffer, "w", 0) as zip_file:
for index, qr_image in enumerate(qr_images):
with zip_file.open(f"{qr_image['name']} ({index + 1}).png", "w") as buf:
qr_image['image'].save(buf, format="PNG")
zip_buffer.seek(0)
# Delete previous attachments
self.env["ir.attachment"].search([
("name", "=", "self_order_qr_code.zip"),
]).unlink()
# Create an attachment with the zip
attachment_id = self.env["ir.attachment"].create({
"name": "self_order_qr_code.zip",
"type": "binary",
"raw": zip_buffer.read(),
"res_model": self._name,
"res_id": self.id,
})
return {
"type": "ir.actions.act_url",
"url": f"/web/content/{attachment_id.id}",
"target": "new",
}
def generate_qr_codes_page(self):
"""
Generate the data needed to print the QR codes page
"""
if self.pos_self_ordering_mode == 'mobile' and self.pos_module_pos_restaurant:
table_ids = self.pos_config_id.floor_ids.table_ids
if not table_ids:
raise ValidationError(_("In Self-Order mode, you must have at least one table to generate QR codes"))
url = url_unquote(self.pos_config_id._get_self_order_url(table_ids[0].id))
name = table_ids[0].name
else:
url = url_unquote(self.pos_config_id._get_self_order_url())
name = ""
return self.env.ref("pos_self_order.report_self_order_qr_codes_page").report_action(
[], data={
'pos_name': self.pos_config_id.name,
'floors': [
{
"name": floor.get("name"),
"type": floor.get("type"),
"table_rows": list(split_every(3, floor["tables"], list)),
}
for floor in self.pos_config_id._get_qr_code_data()
],
'table_mode': self.pos_self_ordering_mode and self.pos_module_pos_restaurant and self.pos_self_ordering_service_mode == 'table',
'self_order': self.pos_self_ordering_mode == 'mobile',
'table_example': {
'name': name,
'decoded_url': url or "",
}
}
)
def preview_self_order_app(self):
self.ensure_one()
return self.pos_config_id.preview_self_order_app()
def update_access_tokens(self):
self.ensure_one()
self.pos_config_id._update_access_token()