100 lines
4.5 KiB
Python
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)
|
|
""")
|