-
-
Notifications
You must be signed in to change notification settings - Fork 83
/
Copy pathmodels.py
192 lines (175 loc) · 8.04 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# Copyright 2021 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, api, models
from odoo.exceptions import UserError
class BaseModel(models.AbstractModel):
_inherit = "base"
_check_pms_properties_auto = False
"""On write and create, call ``_check_pms_properties_auto`` to ensure properties
consistency on the relational fields having ``check_pms_properties=True``
as attribute.
"""
def _valid_field_parameter(self, field, name):
"""Make new field attribute valid for Odoo."""
return name == "check_pms_properties" or super()._valid_field_parameter(
field, name
)
@api.model_create_multi
def create(self, vals_list):
records = super(BaseModel, self).create(vals_list)
if self._check_pms_properties_auto:
records._check_pms_properties()
return records
def write(self, vals):
res = super(BaseModel, self).write(vals)
check_pms_properties = False
for fname in vals:
field = self._fields.get(fname)
if (
fname == "pms_property_id"
or fname == "pms_property_ids"
or fname == "company_id"
or (field.relational and getattr(field, "check_pms_properties", False))
):
check_pms_properties = True
if res and check_pms_properties and self._check_pms_properties_auto:
self._check_pms_properties()
return res
def _check_pms_properties(self, fnames=None):
"""Check the properties of the values of the given field names.
:param list fnames: names of relational fields to check
:raises UserError: if the `pms_properties` of the value of any field is not
in `[False, self.pms_property_id]` (or `self` if
:class:`~odoo.addons.base.models.pms_property`).
For :class:`~odoo.addons.base.models.res_users` relational fields,
verifies record company is in `company_ids` fields.
User with main pms property A, having access to pms property A and B, could be
assigned or linked to records in property B.
"""
if fnames is None:
fnames = self._fields
regular_fields = self._get_regular_fields(fnames)
if not regular_fields:
return
inconsistencies = self._check_inconsistencies(regular_fields)
if inconsistencies:
lines = [_("Incompatible properties on records:")]
property_msg = _(
"""- Record is properties %(pms_properties)r and %(field)r
(%(fname)s: %(values)s) belongs to another properties."""
)
record_msg = _(
"""- %(record)r belongs to properties %(pms_properties)r and
%(field)r (%(fname)s: %(values)s) belongs to another properties."""
)
for record, name, corecords in inconsistencies[:5]:
if record._name == "pms.property":
msg, pms_properties = property_msg, record
else:
msg, pms_properties = (
record_msg,
record.pms_property_id.name
if "pms_property_id" in record
else ", ".join(repr(p.name) for p in record.pms_property_ids),
)
field = self.env["ir.model.fields"]._get(self._name, name)
lines.append(
msg
% {
"record": record.display_name,
"pms_properties": pms_properties,
"field": field.field_description,
"fname": field.name,
"values": ", ".join(
repr(rec.display_name) for rec in corecords
),
}
)
raise UserError("\n".join(lines))
def _get_regular_fields(self, fnames):
regular_fields = []
for name in fnames:
field = self._fields[name]
if (
field.relational
and getattr(field, "check_pms_properties", False)
and (
"pms_property_id" in self.env[field.comodel_name]
or "pms_property_ids" in self.env[field.comodel_name]
)
):
regular_fields.append(name)
return regular_fields
def _check_inconsistencies(self, regular_fields):
inconsistencies = []
for record in self:
pms_properties = False
if record._name == "pms.property":
pms_properties = record
if "pms_property_id" in record:
pms_properties = record.pms_property_id
if "pms_property_ids" in record:
pms_properties = record.pms_property_ids
# Check the property & company consistence
if "company_id" in self._fields:
if record.company_id and pms_properties:
property_companies = pms_properties.mapped("company_id.id")
if (
len(property_companies) > 1
or record.company_id.id != property_companies[0]
):
raise UserError(
_(
"You cannot establish a company other than "
"the one with the established properties"
)
)
# Check verifies that all
# records linked via relation fields are compatible
# with the properties of the origin document,
for name in regular_fields:
field = self._fields[name]
co_pms_properties = False
corecord = record.sudo()[name]
# TODO:res.users management properties
if "pms_property_id" in corecord:
co_pms_properties = corecord.pms_property_id
if "pms_property_ids" in corecord:
co_pms_properties = corecord.pms_property_ids
if (
# There is an inconsistency if:
#
# - Record has properties and corecord too and
# there's no match between them:
# X Pms_room_class with Property1 cannot contain
# Pms_room with property2 X
#
# - Record has a relation one2many with corecord and
# corecord properties aren't included in record properties
# or what is the same, subtraction between corecord properties
# and record properties must be False:
# X Pricelist with Prop1 and Prop2 cannot contain
# Pricelist_item with Prop1 and Prop3 X
# X Pricelist with Prop1 and Prop2 cannot contain
# Pricelist_item with Prop1, Prop2 and Prop3 X
# -In case that record has a relation many2one
# with corecord the condition is the same as avobe
(
pms_properties
and co_pms_properties
and (not pms_properties & co_pms_properties)
)
or (
corecord
and field.type == "one2many"
and pms_properties
and (co_pms_properties - pms_properties)
)
or (
field.type == "many2one"
and co_pms_properties
and ((pms_properties - co_pms_properties) or not pms_properties)
)
):
inconsistencies.append((record, name, corecord))
return inconsistencies