diff --git a/extra-addons/approvals/__manifest__.py b/extra-addons/approvals/__manifest__.py index c516d2d04..92fbca0ac 100644 --- a/extra-addons/approvals/__manifest__.py +++ b/extra-addons/approvals/__manifest__.py @@ -33,6 +33,7 @@ creates next activities for the related approvers. 'report/approval_request_report.xml', 'views/approval_request_views.xml', 'views/res_users_views.xml', + 'views/approval_condition_views.xml' ], 'demo':[ 'data/approval_demo.xml', diff --git a/extra-addons/approvals/models/__init__.py b/extra-addons/approvals/models/__init__.py index b6876aff2..7ac1bd6ae 100644 --- a/extra-addons/approvals/models/__init__.py +++ b/extra-addons/approvals/models/__init__.py @@ -7,3 +7,4 @@ from . import approval_product_line from . import approval_request from . import mail_activity from . import ir_attachment +from . import approval_condition diff --git a/extra-addons/approvals/models/approval_category.py b/extra-addons/approvals/models/approval_category.py index 48aec27c9..c9d2bad1e 100644 --- a/extra-addons/approvals/models/approval_category.py +++ b/extra-addons/approvals/models/approval_category.py @@ -95,6 +95,8 @@ class ApprovalCategory(models.Model): copy=False, check_company=True) model_id = fields.Many2one('ir.model', 'Model',copy=False) + + conditions_ids = fields.Many2many('approval.condition', 'approval_category_condition_rel', 'category_id', 'condition_id') # ---------------------------------------- Methods ----------------------------------------- def _compute_request_to_validate_count(self): diff --git a/extra-addons/approvals/models/approval_condition.py b/extra-addons/approvals/models/approval_condition.py new file mode 100644 index 000000000..f39de8204 --- /dev/null +++ b/extra-addons/approvals/models/approval_condition.py @@ -0,0 +1,77 @@ +from odoo import api, fields, models + +class ApprovalConditions(models.Model): + _name = 'approval.condition' + _description = 'Approval Condition' + _order = 'sequence, id' + + name = fields.Char(string="Name", required=True) + description = fields.Text(string="Description", required=True) + + filter_pre_condition = fields.Char( + string='Condition', + compute='_compute_filter_pre_condition', + readonly=False, store=True, + help="If present, this condition must be satisfied before the update of the record. " + "Not checked on record creation.") + + trigger = fields.Selection( + [ + ('on_stage_set', "Stage is set to"), + ('on_user_set', "User is set"), + ('on_tag_set', "Tag is added"), + ('on_state_set', "State is set to"), + ('on_priority_set', "Priority is set to"), + ('on_archive', "On archived"), + ('on_unarchive', "On unarchived"), + ('on_create_or_write', "On save"), + ('on_create', "On creation"), # deprecated, use 'on_create_or_write' instead + ('on_write', "On update"), # deprecated, use 'on_create_or_write' instead + ('on_unlink', "On deletion"), + ('on_change', "On UI change"), + ('on_time', "Based on date field"), + ('on_time_created', "After creation"), + ('on_time_updated', "After last update"), + ("on_message_received", "On incoming message"), + ("on_message_sent", "On outgoing message"), + ('on_webhook', "On webhook"), + ], string='Trigger', + compute='_compute_trigger', readonly=False, store=True, required=True + ) + + trigger_field_ids = fields.Many2many( + 'ir.model.fields', string='Trigger Fields', + compute='_compute_trigger_field_ids', readonly=False, store=True, + help="The automation rule will be triggered if and only if one of these fields is updated." + "If empty, all fields are watched.") + + trg_field_ref = fields.Reference( + selection=[('ir.model.fields', 'Field Reference')], + string='Trigger Reference', + readonly=False, + store=True, + help="Some triggers need a reference to another field. This field is used to store it." + ) + + sequence = fields.Boolean('Approvers Sequence?', help="If checked, the approvers have to approve in sequence.") + approval_minimum = fields.Integer(string="Minimum Approval", default=1, required=True) + user_ids = fields.Many2many('res.users', compute='_compute_user_ids', string="Approver Users") + approver_ids = fields.One2many('approval.category.approver', 'category_id', string="Approvers") + @api.depends('approver_ids') + def _compute_user_ids(self): + for record in self: + record.user_ids = record.approver_ids.user_id + @api.depends('trigger', 'trigger_field_ids', 'trg_field_ref') + def _compute_filter_pre_condition(self): + for automation in self: + if automation.trigger != 'on_tag_set' or len(automation.trigger_field_ids) != 1: + automation.filter_pre_condition = False + else: + field = automation.trigger_field_ids.name + value = automation.trg_field_ref + automation.filter_pre_condition = f"[('{field}', 'not in', [{value}])]" if value else False + + def delete_condition(self): + for record in self: + record.unlink() + diff --git a/extra-addons/approvals/security/ir.model.access.csv b/extra-addons/approvals/security/ir.model.access.csv index 837145bcd..aea42a037 100644 --- a/extra-addons/approvals/security/ir.model.access.csv +++ b/extra-addons/approvals/security/ir.model.access.csv @@ -13,3 +13,5 @@ access_approval_approver_user,access_approval_approver,model_approval_approver,g access_approval_approver_manager,access_approval_approver,model_approval_approver,group_approval_manager,1,1,1,1 access_approval_product_line_user,access_approval_product_line,model_approval_product_line,base.group_user,1,1,1,1 access_approval_product_line_manager,access_approval_product_line,model_approval_product_line,group_approval_manager,1,1,1,1 +access_approval_condition,access_approval_condition,model_approval_condition,base.group_user,1,1,1,1 + diff --git a/extra-addons/approvals/static/src/views/kanban/approvals_category_kanban.scss b/extra-addons/approvals/static/src/views/kanban/approvals_category_kanban.scss new file mode 100644 index 000000000..0be126336 --- /dev/null +++ b/extra-addons/approvals/static/src/views/kanban/approvals_category_kanban.scss @@ -0,0 +1,52 @@ +.o_approvals_category_actions_field, +.o_approvals_category_kanban_view { + .o_kanban_ungrouped { + padding: 0; + + .o_kanban_record { + width: 30%; + margin: 0; + + &.o_kanban_ghost { + display: none; + } + } + } +} + +.o_approvals_category_actions_field .o_kanban_ghost { + display: none; +} + +.o_approvals_category_kanban_view { + .o_kanban_grouped .row { + flex-direction: column !important; + gap: 0.5rem !important; + + > * { + width: 100% !important; + + > * { + margin: 0 0.5rem !important; + } + } + } + + .o_kanban_ungrouped .o_kanban_record .oe_kanban_global_click { + border-top: 0; + display: flex; + align-items: center; + + .o_widget_web_ribbon { + align-self: flex-start; + } + } +} +.o_form_view .o_group .o_field_widget, .o_form_view .o_inner_group .o_field_widget { + width: 50%; +} +.o_approvals_category_error { + pre { + max-height: 25vh !important; + } +} diff --git a/extra-addons/approvals/views/approval_category_views.xml b/extra-addons/approvals/views/approval_category_views.xml index 60ea973ee..e5a2159f5 100644 --- a/extra-addons/approvals/views/approval_category_views.xml +++ b/extra-addons/approvals/views/approval_category_views.xml @@ -76,39 +76,54 @@ - - - - + + + + + + + + + + + + + +