Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FWP] [17.0] OCA-PORT PRs 802 860 888 902 921 #905

Merged
merged 8 commits into from
Jul 16, 2024
8 changes: 8 additions & 0 deletions .oca/oca-port/blacklist/base_tier_validation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"pull_requests": {
"OCA/server-ux#778": "Already ported",
"OCA/server-ux#813": "Already ported",
"OCA/server-ux#830": "Already ported",
"OCA/server-ux#848": "Already ported"
}
}
1 change: 1 addition & 0 deletions base_tier_validation/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ Contributors
- bosd
- Evan Soh <[email protected]>
- Manuel Regidor <[email protected]>
- Eduardo de Miguel <[email protected]>

Maintainers
-----------
Expand Down
1 change: 1 addition & 0 deletions base_tier_validation/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"views/res_config_settings_views.xml",
"views/tier_definition_view.xml",
"views/tier_review_view.xml",
"views/tier_validation_exception_view.xml",
"wizard/comment_wizard_view.xml",
"templates/tier_validation_templates.xml",
],
Expand Down
1 change: 1 addition & 0 deletions base_tier_validation/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from . import tier_definition
from . import tier_validation_exception
from . import tier_review
from . import tier_validation
from . import res_users
Expand Down
6 changes: 4 additions & 2 deletions base_tier_validation/models/tier_definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@
@api.depends("review_type", "model_id")
def _compute_domain_reviewer_field(self):
for rec in self:
rec.valid_reviewer_field_ids = self.env["ir.model.fields"].search(
[("model", "=", rec.model), ("relation", "=", "res.users")]
rec.valid_reviewer_field_ids = (

Check warning on line 111 in base_tier_validation/models/tier_definition.py

View check run for this annotation

Codecov / codecov/patch

base_tier_validation/models/tier_definition.py#L111

Added line #L111 was not covered by tests
self.env["ir.model.fields"]
.sudo()
.search([("model", "=", rec.model), ("relation", "=", "res.users")])
)
133 changes: 129 additions & 4 deletions base_tier_validation/models/tier_validation.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright 2017-19 ForgeFlow S.L. (https://www.forgeflow.com)
# Copyright 2024 Moduon Team (https://www.moduon.team)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from ast import literal_eval
Expand All @@ -9,6 +10,8 @@
from odoo.exceptions import ValidationError
from odoo.tools.misc import frozendict

BASE_EXCEPTION_FIELDS = ["message_follower_ids", "access_token"]


class TierValidation(models.AbstractModel):
_name = "tier.validation"
Expand Down Expand Up @@ -251,10 +254,43 @@
else:
return self

@api.model
def _get_validation_exceptions(self, extra_domain=None, add_base_exceptions=True):
"""Return Tier Validation Exception field names that matchs custom domain."""
exception_fields = (
self.env["tier.validation.exception"]
.search(
[
("model_name", "=", self._name),
("company_id", "in", [False] + self.env.company.ids),
*(extra_domain or []),
]
)
.mapped("field_ids.name")
)
if add_base_exceptions:
exception_fields = list(set(exception_fields + BASE_EXCEPTION_FIELDS))
return exception_fields

@api.model
def _get_all_validation_exceptions(self):
"""Extend for more field exceptions to be written when on the entire
validation process."""
return self._get_validation_exceptions()

@api.model
def _get_under_validation_exceptions(self):
"""Extend for more field exceptions."""
return ["message_follower_ids", "access_token"]
"""Extend for more field exceptions to be written under validation."""
return self._get_validation_exceptions(
extra_domain=[("allowed_to_write_under_validation", "=", True)]
)

@api.model
def _get_after_validation_exceptions(self):
"""Extend for more field exceptions to be written after validation."""
return self._get_validation_exceptions(
extra_domain=[("allowed_to_write_after_validation", "=", True)]
)

def _check_allow_write_under_validation(self, vals):
"""Allow to add exceptions for fields that are allowed to be written
Expand All @@ -265,6 +301,36 @@
return False
return True

def _check_allow_write_after_validation(self, vals):
"""Allow to add exceptions for fields that are allowed to be written
even when the record is after validation."""
exceptions = self._get_after_validation_exceptions()
for val in vals:
if val not in exceptions:
return False
return True

def _get_fields_to_write_validation(self, vals, records_exception_function):
"""Not allowed fields to write when validation depending
on the given function."""
exceptions = records_exception_function()
not_allowed_fields = []
for val in vals:
if val not in exceptions:
not_allowed_fields.append(val)
if not not_allowed_fields:
return []

Check warning on line 322 in base_tier_validation/models/tier_validation.py

View check run for this annotation

Codecov / codecov/patch

base_tier_validation/models/tier_validation.py#L322

Added line #L322 was not covered by tests

not_allowed_field_names, allowed_field_names = [], []
for fld_name, fld_data in self.fields_get(
not_allowed_fields + exceptions
).items():
if fld_name in not_allowed_fields:
not_allowed_field_names.append(fld_data["string"])
else:
allowed_field_names.append(fld_data["string"])
return allowed_field_names, not_allowed_field_names

def write(self, vals):
for rec in self:
if rec._check_state_conditions(vals):
Expand All @@ -286,6 +352,7 @@
"one record."
)
)
# Write under validation
if (
rec.review_ids
and getattr(rec, self._state_field) in self._state_from
Expand All @@ -294,7 +361,50 @@
and not rec._check_allow_write_under_validation(vals)
and not rec._context.get("skip_validation_check")
):
raise ValidationError(_("The operation is under validation."))
(
allowed_fields,
not_allowed_fields,
) = rec._get_fields_to_write_validation(
vals, rec._get_under_validation_exceptions
)
raise ValidationError(
_(
"You are not allowed to write those fields under validation.\n"
"- %(not_allowed_fields)s\n\n"
"Only those fields can be modified:\n- %(allowed_fields)s"
)
% {
"not_allowed_fields": "\n- ".join(not_allowed_fields),
"allowed_fields": "\n- ".join(allowed_fields),
}
)

# Write after validation. Check only if Tier Validation Exception is created
if (
rec._get_validation_exceptions(add_base_exceptions=False)
and rec.validation_status == "validated"
and getattr(rec, self._state_field)
in (self._state_to + [self._cancel_state])
and not rec._check_allow_write_after_validation(vals)
and not rec._context.get("skip_validation_check")
):
(
allowed_fields,
not_allowed_fields,
) = rec._get_fields_to_write_validation(
vals, rec._get_after_validation_exceptions
)
raise ValidationError(
_(
"You are not allowed to write those fields after validation.\n"
"- %(not_allowed_fields)s\n\n"
"Only those fields can be modified:\n- %(allowed_fields)s"
)
% {
"not_allowed_fields": "\n- ".join(not_allowed_fields),
"allowed_fields": "\n- ".join(allowed_fields),
}
)
if rec._allow_to_remove_reviews(vals):
rec.mapped("review_ids").unlink()
return super().write(vals)
Expand Down Expand Up @@ -422,7 +532,10 @@
lambda x: x.sequence in sequences or x.approve_sequence_bypass
)
if self.has_comment:
return self._add_comment("validate", reviews)
user_reviews = reviews.filtered(
lambda r: r.status == "pending" and (self.env.user in r.reviewer_ids)
)
return self._add_comment("validate", user_reviews)
self._validate_tier(reviews)
self._update_counter({"review_deleted": True})

Expand Down Expand Up @@ -622,6 +735,9 @@
new_node = etree.fromstring(str_element)
return new_node

def _get_tier_validation_readonly_domain(self):
return "bool(review_ids)"

@api.model
def get_view(self, view_id=None, view_type="form", **options):
res = super().get_view(view_id=view_id, view_type=view_type, **options)
Expand Down Expand Up @@ -662,6 +778,15 @@
all_models[model] = res["models"][model]
new_node = etree.fromstring(new_arch)
node.append(new_node)
excepted_fields = self._get_all_validation_exceptions()
for node in doc.xpath("//field[@name][not(ancestor::field)]"):
if node.attrib.get("name") in excepted_fields:
continue

Check warning on line 784 in base_tier_validation/models/tier_validation.py

View check run for this annotation

Codecov / codecov/patch

base_tier_validation/models/tier_validation.py#L784

Added line #L784 was not covered by tests
new_r_modifier = self._get_tier_validation_readonly_domain()
old_r_modifier = node.attrib.get("readonly")
if old_r_modifier:
new_r_modifier = f"({old_r_modifier}) or ({new_r_modifier})"
node.attrib["readonly"] = new_r_modifier
res["arch"] = etree.tostring(doc)
res["models"] = frozendict(all_models)
return res
Expand Down
95 changes: 95 additions & 0 deletions base_tier_validation/models/tier_validation_exception.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Copyright 2024 Moduon Team (https://www.moduon.team)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import _, api, exceptions, fields, models

from .tier_validation import BASE_EXCEPTION_FIELDS


class TierValidationException(models.Model):
_name = "tier.validation.exception"
_description = "Tier Validation Exceptions"
_rec_name = "model_name"

@api.model
def _get_tier_validation_model_names(self):
return self.env["tier.definition"]._get_tier_validation_model_names()

model_id = fields.Many2one(
comodel_name="ir.model",
string="Model",
required=True,
ondelete="cascade",
domain=lambda self: [("model", "in", self._get_tier_validation_model_names())],
)
model_name = fields.Char(
related="model_id.model",
string="Model",
store=True,
readonly=True,
index=True,
)
field_ids = fields.Many2many(
comodel_name="ir.model.fields",
string="Fields",
domain="[('id', 'in', valid_model_field_ids)]",
required=True,
)
valid_model_field_ids = fields.One2many(
comodel_name="ir.model.fields",
compute="_compute_valid_model_field_ids",
)
company_id = fields.Many2one(
comodel_name="res.company",
string="Company",
default=lambda self: self.env.company,
)
allowed_to_write_under_validation = fields.Boolean(
string="Write under Validation",
default=True,
)
allowed_to_write_after_validation = fields.Boolean(
string="Write after Validation",
default=True,
)

@api.depends("model_id")
def _compute_valid_model_field_ids(self):
for record in self:
record.valid_model_field_ids = (

Check warning on line 59 in base_tier_validation/models/tier_validation_exception.py

View check run for this annotation

Codecov / codecov/patch

base_tier_validation/models/tier_validation_exception.py#L59

Added line #L59 was not covered by tests
self.env["ir.model.fields"]
.sudo()
.search(
[
("model", "=", record.model_name),
("name", "not in", BASE_EXCEPTION_FIELDS),
]
)
)

@api.constrains(
"allowed_to_write_under_validation", "allowed_to_write_after_validation"
)
def _check_allowed_to_write(self):
if (
not self.allowed_to_write_under_validation
and not self.allowed_to_write_after_validation
):
raise exceptions.ValidationError(

Check warning on line 78 in base_tier_validation/models/tier_validation_exception.py

View check run for this annotation

Codecov / codecov/patch

base_tier_validation/models/tier_validation_exception.py#L78

Added line #L78 was not covered by tests
_(
"At least one of these fields must be checked! "
"Write under Validation, Write after Validation"
)
)

_sql_constraints = [
(
"model_company_under_after_unique",
"unique(model_id, company_id, "
"allowed_to_write_under_validation, allowed_to_write_after_validation)",
_(
"The model already exists for this company with this "
"Write Validation configuration!"
),
)
]
1 change: 1 addition & 0 deletions base_tier_validation/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
- bosd
- Evan Soh \<<[email protected]>\>
- Manuel Regidor \<<[email protected]>\>
- Eduardo de Miguel \<<[email protected]>\>
2 changes: 2 additions & 0 deletions base_tier_validation/security/ir.model.access.csv
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ access_tier_review,access.tier.review,model_tier_review,base.group_user,1,1,1,1
access_tier_definition_all,tier.definition.all,model_tier_definition,base.group_user,1,0,0,0
access_tier_definition_settings,tier.definition.settings,model_tier_definition,base.group_system,1,1,1,1
access_comment_wizard,access.comment.wizard,model_comment_wizard,base.group_user,1,1,1,1
access_tier_validation_exceptions_all,tier.validation.exceptions,model_tier_validation_exception,,1,0,0,0
access_tier_validation_exceptions_settings,tier.validation.exceptions,model_tier_validation_exception,base.group_system,1,1,1,1
12 changes: 8 additions & 4 deletions base_tier_validation/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

/*
:Author: David Goodger ([email protected])
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.

See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
Expand Down Expand Up @@ -274,7 +275,7 @@
margin-left: 2em ;
margin-right: 2em }

pre.code .ln { color: grey; } /* line numbers */
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
Expand All @@ -300,7 +301,7 @@
span.pre {
white-space: pre }

span.problematic {
span.problematic, pre.problematic {
color: red }

span.section-subtitle {
Expand Down Expand Up @@ -588,12 +589,15 @@ <h2><a class="toc-backref" href="#toc-entry-22">Contributors</a></h2>
<li>bosd</li>
<li>Evan Soh &lt;<a class="reference external" href="mailto:evan.soh&#64;omnisoftsolution.com">evan.soh&#64;omnisoftsolution.com</a>&gt;</li>
<li>Manuel Regidor &lt;<a class="reference external" href="mailto:manuel.regidor&#64;sygel.es">manuel.regidor&#64;sygel.es</a>&gt;</li>
<li>Eduardo de Miguel &lt;<a class="reference external" href="mailto:edu&#64;moduon.team">edu&#64;moduon.team</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-23">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
Expand Down
Loading
Loading