diff --git a/base_tier_validation/README.rst b/base_tier_validation/README.rst index ef4b0875f..622914e05 100644 --- a/base_tier_validation/README.rst +++ b/base_tier_validation/README.rst @@ -70,6 +70,9 @@ To configure this module, you need to: **Note:** +- With *Validated by: Any of specific users*, list the users under + *Reviewers*: any one of them can validate, like a member of a reviewer + group, without creating a group for them. - If check *Notify Reviewers on Creation*, all possible reviewers will be notified by email when this definition is triggered. - If check *Notify reviewers on reaching pending* if you want to send a diff --git a/base_tier_validation/models/tier_definition.py b/base_tier_validation/models/tier_definition.py index e9f3402b5..cec0f9430 100644 --- a/base_tier_validation/models/tier_definition.py +++ b/base_tier_validation/models/tier_definition.py @@ -36,6 +36,7 @@ def _get_tier_validation_model_names(self): default="individual", selection=[ ("individual", "Specific user"), + ("users", "Any of specific users"), ("group", "Any user in a specific group"), ("field", "Field in related record"), ], @@ -48,6 +49,16 @@ def _get_tier_validation_model_names(self): reviewer_group_id = fields.Many2one( comodel_name="res.groups", string="Reviewer group" ) + reviewer_user_ids = fields.Many2many( + comodel_name="res.users", + relation="tier_definition_reviewer_user_rel", + column1="definition_id", + column2="user_id", + string="Reviewers", + domain="[('share', '=', False)]", + help="Any one of these users can validate, like a member of a reviewer " + "group, without having to create a group for them.", + ) reviewer_field_id = fields.Many2one( comodel_name="ir.model.fields", string="Reviewer field", @@ -122,14 +133,15 @@ def _get_tier_validation_model_names(self): "group can validate -- except the requester themselves. Without " "this flag, a requester who happens to be in the same group as " "the configured reviewers can auto-validate their own request. " - "Only meaningful for review_type='group'; the form hides this " - "field for the other review types.", + "Only meaningful when several users can review (a group or a list " + "of users); the form hides this field for the other review types.", ) @api.onchange("review_type") def onchange_review_type(self): self.reviewer_id = None self.reviewer_group_id = None + self.reviewer_user_ids = False def _reviewers_without_model_access(self, model_name, users): """Return the subset of ``users`` that cannot read ``model_name``. @@ -160,9 +172,19 @@ def _reviewers_to_check_for_access(self): return self.reviewer_id if self.review_type == "group": return self.reviewer_group_id.user_ids + if self.review_type == "users": + # In a form, the lines of an x2many are new records; check the + # users themselves. + return self.reviewer_user_ids._origin return self.env["res.users"] - @api.onchange("review_type", "reviewer_id", "reviewer_group_id", "model_id") + @api.onchange( + "review_type", + "reviewer_id", + "reviewer_group_id", + "reviewer_user_ids", + "model_id", + ) def _onchange_warn_reviewer_access(self): """Advisory warning when an assigned reviewer cannot read the model. diff --git a/base_tier_validation/models/tier_review.py b/base_tier_validation/models/tier_review.py index 2b4cd2ffd..df96df4b4 100644 --- a/base_tier_validation/models/tier_review.py +++ b/base_tier_validation/models/tier_review.py @@ -39,6 +39,9 @@ class TierReview(models.Model): review_type = fields.Selection(related="definition_id.review_type") reviewer_id = fields.Many2one(related="definition_id.reviewer_id") reviewer_group_id = fields.Many2one(related="definition_id.reviewer_group_id") + reviewer_user_ids = fields.Many2many( + related="definition_id.reviewer_user_ids", string="Listed Reviewers" + ) reviewer_field_id = fields.Many2one(related="definition_id.reviewer_field_id") reviewer_ids = fields.Many2many( string="Reviewers", @@ -152,6 +155,8 @@ def _get_reviewer_fields(self): "reviewer_id", "reviewer_group_id", "reviewer_group_id.user_ids", + "review_type", + "reviewer_user_ids", "definition_id.exclude_requester", "requested_by", ] @@ -178,7 +183,9 @@ def _compute_todo_by(self): def _get_reviewers(self): reviewers = self.env["res.users"] - if self.reviewer_id or self.reviewer_group_id.user_ids: + if self.review_type == "users": + reviewers = self.reviewer_user_ids + elif self.reviewer_id or self.reviewer_group_id.user_ids: reviewers = self.reviewer_id + self.reviewer_group_id.user_ids elif self.reviewer_field_id: resource = self.env[self.model].browse(self.res_id) diff --git a/base_tier_validation/readme/CONFIGURE.md b/base_tier_validation/readme/CONFIGURE.md index 4bd817e66..1fa346b8d 100644 --- a/base_tier_validation/readme/CONFIGURE.md +++ b/base_tier_validation/readme/CONFIGURE.md @@ -7,6 +7,9 @@ To configure this module, you need to: **Note:** +- With *Validated by: Any of specific users*, list the users under + *Reviewers*: any one of them can validate, like a member of a reviewer + group, without creating a group for them. - If check *Notify Reviewers on Creation*, all possible reviewers will be notified by email when this definition is triggered. - If check *Notify reviewers on reaching pending* if you want to send a notification when pending status is reached. diff --git a/base_tier_validation/readme/newsfragments/91.feature b/base_tier_validation/readme/newsfragments/91.feature new file mode 100644 index 000000000..a407ac78d --- /dev/null +++ b/base_tier_validation/readme/newsfragments/91.feature @@ -0,0 +1 @@ +New *Validated by* option *Any of specific users*: any one of the listed users can validate, without creating a group for them. diff --git a/base_tier_validation/static/description/index.html b/base_tier_validation/static/description/index.html index 2e9108df6..88604ea88 100644 --- a/base_tier_validation/static/description/index.html +++ b/base_tier_validation/static/description/index.html @@ -3,7 +3,7 @@
-