# Copyright 2019 Creu Blanca # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import base64 import json import binascii from odoo import api, fields, models, _ from odoo.exceptions import UserError import re class DocumentQuickAccessRule(models.Model): _name = 'document.quick.access.rule' _description = 'Document Quick Access Rule' _order = 'priority,model_id' name = fields.Char(required=True) priority = fields.Integer(default=16, required=True) barcode_format = fields.Selection([ ('standard', 'Standard'), ('b64_standard', 'Base64'), ], required=True, default='standard') # All formats must have a function to determine the code from a record and # get the record from the code model_id = fields.Many2one( 'ir.model', required=True, ) active = fields.Boolean( default=True, ) def get_code(self, record): self.ensure_one() return getattr(self, '_get_code_%s' % self.barcode_format)(record) def _get_code_b64_standard(self, record): return base64.b64encode( self._get_code_standard(record).encode('utf-8')).decode('utf-8') def _get_code_standard(self, record): return '%s,%s' % (record._name, record.id) def _check_code_b64_standard(self, code): try: aux_code = base64.b64decode(code.encode('utf-8'), validate=True) except binascii.Error: return False return self._check_code_standard(aux_code.decode('utf-8')) def _check_code_standard(self, code): return re.match("^[a-zA-Z0-9\\.]*,[0-9]*$", code) def _read_code_b64_standard(self, code): aux_code = base64.b64decode(code.encode('utf-8')).decode('utf-8') return self._read_code_standard(aux_code) def _read_code_standard(self, code): params = code.split(',') return self.env[params[0]].browse(int(params[1])).exists() def read_code_action(self, code): try: record = self.read_code(code) except UserError: return { 'type': 'ir.actions.act_window', 'name': 'Search QR', 'res_model': 'barcode.action', 'views': [[False, 'form']], 'target': 'new', 'context': json.dumps({ 'default_model': 'document.quick.access.rule', 'default_method': 'read_code_action', 'default_state': 'warning', 'default_status': _('Document cannot be found') }) } record.check_access_rights('read') result = { "type": "ir.actions.act_window", "res_model": record._name, "views": [[record.get_formview_id(), "form"]], "res_id": record.id, "target": "main", } return result @api.model def read_code(self, code): formats = self._fields['barcode_format'].selection for barcode_format, format_name in formats: if getattr(self, '_check_code_%s' % barcode_format)(code): record = getattr(self, '_read_code_%s' % barcode_format)(code) if record and self.search([ ('model_id.model', '=', record._name), ('barcode_format', '=', barcode_format) ]): return record raise UserError(_('No format has been found for this record'))