Files
enterprise-addons/sign/models/sign_item.py
T

100 lines
4.5 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
from odoo.exceptions import ValidationError
class SignItem(models.Model):
_name = 'sign.item'
_description = "Fields to be sign on Document"
_order = "page asc, posY asc, posX asc"
_rec_name = 'document_id'
document_id = fields.Many2one('sign.document', string="Document Template", required=True, index=True, ondelete='cascade')
template_id = fields.Many2one('sign.template', related='document_id.template_id')
type_id = fields.Many2one('sign.item.type', string="Type", required=True, ondelete='restrict')
required = fields.Boolean(default=True)
responsible_id = fields.Many2one("sign.item.role", string="Responsible", ondelete="restrict")
option_ids = fields.Many2many("sign.item.option", string="Selection options", relation='sign_item_option_rel')
radio_set_id = fields.Many2one("sign.item.radio.set", string="Radio button options", ondelete='cascade', index='btree_not_null')
num_options = fields.Integer(related="radio_set_id.num_options")
name = fields.Char(string="Field Name", default=lambda self: self.type_id.placeholder)
page = fields.Integer(string="Document Page", required=True, default=1)
posX = fields.Float(digits=(4, 3), string="Position X", required=True)
posY = fields.Float(digits=(4, 3), string="Position Y", required=True)
width = fields.Float(digits=(4, 3), required=True)
height = fields.Float(digits=(4, 3), required=True)
alignment = fields.Char(default="left", required=True)
constant = fields.Boolean(string="Read-only")
transaction_id = fields.Integer(copy=False)
@api.model_create_multi
def create(self, vals_list):
res = super().create(vals_list)
res.template_id.check_access('write')
return res
def write(self, vals):
res = super().write(vals)
if vals.keys() & {'template_id', 'document_id'}:
self.template_id.check_access('write')
return res
def copy_data(self, default=None):
vals_list = super().copy_data(default=default)
# When duplicating sign items of type "radio" create new equivalent radio sets for the new items.
radio_set_map = {}
for radio_set_id in {item['radio_set_id'] for item in vals_list if item['radio_set_id']}:
new_radio_set = self.env['sign.item.radio.set'].create([{}])
radio_set_map[radio_set_id] = new_radio_set.id
for item in vals_list:
item['radio_set_id'] = radio_set_map.get(item['radio_set_id'])
# Copy the role so editing it on one template doesn't leak to the other.
role_map = self.env.context.get('__sign_role_copy_map')
if role_map is None:
role_map = {} # standalone item copy, not through a template duplication
for responsible_id in {item['responsible_id'] for item in vals_list if item.get('responsible_id')}:
if responsible_id in role_map:
continue
role = self.env['sign.item.role'].browse(responsible_id)
if role.default:
continue
role_map[responsible_id] = role.copy().id
for item in vals_list:
if item.get('responsible_id') in role_map:
item['responsible_id'] = role_map[item['responsible_id']]
return vals_list
@api.constrains('required', 'constant')
def _check_constant(self):
for record in self:
if record.constant and record.type_id.item_type in ['signature', 'initial', 'selection', 'checkbox', 'radio']:
raise ValidationError(self.env._("Read-only can only be applied to items of the following types: 'Text', 'Name', 'Email', 'Phone', 'Company', 'Multiline', 'Date', 'Strikethrough'"))
@api.autovacuum
def _gc_radio_set_and_options(self):
# Unlink orphaned radio sets that has no sign items linked to it
self.env.cr.execute("""
WITH linked_radio AS (
SELECT s.id radio_id
FROM sign_item_radio_set s
LEFT JOIN sign_item si ON si.radio_set_id=s.id
WHERE si.id IS NULL
)
DELETE FROM sign_item_radio_set
WHERE id IN (SELECT * FROM linked_radio)
""")
# Unlink options that don't belong to any selection sign item
self.env.cr.execute("""
DELETE FROM sign_item_option
WHERE id NOT IN (SELECT sign_item_option_id FROM sign_item_option_rel)
""")