Repository
OCA/tier-validation · module folder · Try on Runboat
Module version
1.2.1
Category
Tools
Folder size
0.73 MB
License
AGPL-3
Application
No
Auto-installable
No
Website
https://github.com/OCA/tier-validation
Last tracking update
2026-08-07 09:06:34
Authors
Odoo Community Association (OCA), ForgeFlow
Maintainers
Odoo Community Association (OCA), ForgeFlow
Committers
Maksym Yankin, Weblate, OCA-git-bot, oca-ci, bosd
Odoo dependencies
odoo/odoo:
- web
- bus
Python dependencies
None
System dependencies
None
Required by
account_move_tier_validation, base_tier_validation_confirm_auth, base_tier_validation_correction, base_tier_validation_formula, base_tier_validation_forward, base_tier_validation_server_action, purchase_request_tier_validation, purchase_tier_validation, sale_tier_validation, stock_picking_tier_validation
Description
Validating some operations is a common need across different areas in a
company and sometimes it also involves several people and stages in the
process. With this module you will be able to define your custom
validation workflows for any Odoo document.

This module does not provide a functionality by itself but an abstract
model to implement a validation process based on tiers on other models
(e.g. purchase orders, sales orders, budgets, expenses...).

**Note:** To be able to use this module in a new model you will need
some development.

See [purchase_tier_validation](https://github.com/OCA/purchase-workflow)
as an example of implementation.

Additionally, if your state field is a (stored) computed field, you need to
set `_tier_validation_state_field_is_computed` to `True` in your model Python
file, and you will want to add the dependent fields of the compute method
in `_get_after_validation_exceptions` and `_get_under_validation_exceptions`.

Code Analysis

Views touched (11)
XML IDNameModelTypeStatus
tier_definition_view_form tier.definition.form tier.definition form New
tier_definition_view_search tier.definition.search tier.definition search New
tier_definition_view_tree tier.definition.list tier.definition list New
tier_review_view_tree tier.review.list tier.review list New
tier_validation_buttons tier_validation_buttons ir.ui.view qweb New
tier_validation_exception_form tier.validation.exception.form tier.validation.exception form New
tier_validation_exception_search tier.validation.exception.search tier.validation.exception search New
tier_validation_exception_tree tier.validation.exception.list tier.validation.exception list New
tier_validation_label tier_validation_label ir.ui.view qweb New
tier_validation_reviews tier_validation_reviews ir.ui.view qweb New
view_comment_wizard Comment Wizard comment.wizard form New
HTTP endpoints (0)

No HTTP endpoints found for this module.

Models touched (6)

New fields (5)
  • comment Char
    required=True
  • res_id Integer
  • res_model Char
  • review_ids Many2many → tier.review
    comodel_name='tier.review'
  • validate_reject Char
Public methods (1)
  • add_comment(self)

New fields (1)
  • review_ids Many2many → tier.review
    comodel_name='tier.review' copy=False string='Reviews'
Public methods (1)
  • review_user_count(self)
    @api.model

New fields (24)
  • active Boolean
    default=True
  • allow_write_for_reviewer Boolean
    default=False string='Allow Write For Reviewers'
  • approve_sequence Boolean
    default=False help='Approval order by the specified sequence number' string='Approve by sequence'
  • approve_sequence_bypass Boolean
    help='Bypassed (auto validated), if previous tier was validated by same reviewer'
  • company_id Many2one → res.company
    comodel_name='res.company' default=<expr> string='Company'
  • definition_domain Char
  • definition_type Selection
    default='domain' selection=[('domain', 'Domain')] string='Definition'
  • exclude_requester Boolean
    default=False help="When set, the user who requested the validation is removed from this tier's reviewer pool. Anyone else in the configured 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." string='Four-eyes Principle'
  • has_comment Boolean
    default=False string='Comment'
  • model Char
    index=True related='model_id.model' store=True
  • model_id Many2one → ir.model
    comodel_name='ir.model' domain=<expr> string='Referenced Model'
  • name Char
    default=<expr> required=True string='Description' translate=True
  • notify_on_accepted Boolean
    help='If set, reviewers will be notified by email when a review related to this definition is accepted.' string='Notify Reviewers on Accepted'
  • notify_on_create Boolean
    help='If set, all possible reviewers will be notified by email when this definition is triggered.' string='Notify Reviewers on Creation'
  • notify_on_pending Boolean
    help="If set, all possible reviewers will be notified by email when this status is reached.Usefull in an Approve by sequence scenario. An notification request to review is sent out when it's their turn to review." string='Notify Reviewers on reaching Pending'
  • notify_on_rejected Boolean
    help='If set, reviewers will be notified by email when a review related to this definition is rejected.' string='Notify Reviewers on Rejected'
  • notify_on_restarted Boolean
    help='If set, reviewers will be notified by email when a reviews related to this definition are restarted.' string='Notify Reviewers on Restarted'
  • notify_reminder_delay Integer
    help='Number of days after which a message must be posted to remind about pending validation (0 = no reminder)' string='Send reminder message on pending reviews'
  • review_type Selection
    default='individual' selection=[('individual', 'Specific user'), ('group', 'Any user in a specific group'), ('field', 'Field in related record')] string='Validated by'
  • reviewer_field_id Many2one → ir.model.fields
    comodel_name='ir.model.fields' domain="[('id', 'in', valid_reviewer_field_ids)]" string='Reviewer field'
  • reviewer_group_id Many2one → res.groups
    comodel_name='res.groups' string='Reviewer group'
  • reviewer_id Many2one → res.users
    comodel_name='res.users' string='Reviewer'
  • sequence Integer
    default=30
  • valid_reviewer_field_ids One2many → ir.model.fields
    comodel_name='ir.model.fields' compute='_compute_domain_reviewer_field'
Public methods (1)
  • onchange_review_type(self)
    @api.onchange('review_type')

New fields (24)
  • approve_sequence Boolean
    related='definition_id.approve_sequence'
  • approve_sequence_bypass Boolean
    related='definition_id.approve_sequence_bypass'
  • can_review Boolean
    compute='_compute_can_review' help='Can review will be marked if the review is pending and the\n approve sequence has been achieved' store=True
  • comment Char
    string='Comments'
  • company_id Many2one
    related='definition_id.company_id' store=True
  • definition_id Many2one → tier.definition
    comodel_name='tier.definition'
  • display_status Char
    compute='_compute_display_status'
  • done_by Many2one → res.users
    comodel_name='res.users'
  • has_comment Boolean
    related='definition_id.has_comment'
  • last_reminder_date Datetime
    readonly=True
  • model Char
    index=True string='Related Document Model'
  • name Char
    related='definition_id.name'
  • requested_by Many2one → res.users
    comodel_name='res.users'
  • res_id Many2oneReference
    index=True model_field='model' string='Related Document ID'
  • review_type Selection
    related='definition_id.review_type'
  • reviewed_date Datetime
    string='Validation Date'
  • reviewed_formated_date Char
    compute='_compute_reviewed_formated_date' string='Validation Formated Date'
  • reviewer_field_id Many2one
    related='definition_id.reviewer_field_id'
  • reviewer_group_id Many2one
    related='definition_id.reviewer_group_id'
  • reviewer_id Many2one
    related='definition_id.reviewer_id'
  • reviewer_ids Many2many → res.users
    comodel_name='res.users' compute='_compute_reviewer_ids' store=True string='Reviewers'
  • sequence Integer
    string='Tier'
  • status Selection
    default='waiting' args: [('waiting', 'Waiting'), ('pending', 'Pending'), ('rejected', 'Rejected'), ('approved', 'Approved'), ('cancel', 'Cancel')]
  • todo_by Char
    compute='_compute_todo_by' store=True
Public methods (0)

No public methods.

New fields (11)
  • can_review Boolean
    compute='_compute_can_review' search='_search_can_review'
  • has_comment Boolean
    compute='_compute_has_comment' help='If set, Allow the reviewer to leave a comment on the review.'
  • hide_reviews Boolean
    compute='_compute_hide_reviews'
  • need_validation Boolean
    compute='_compute_need_validation'
  • next_review Char
    compute='_compute_next_review'
  • rejected_message Html
    compute='_compute_rejected_message'
  • review_ids One2many → tier.review
    bypass_search_access=True comodel_name='tier.review' domain=<expr> inverse_name='res_id' string='Validations'
  • reviewer_ids Many2many → res.users
    comodel_name='res.users' compute='_compute_reviewer_ids' search='_search_reviewer_ids' string='Reviewers'
  • to_validate_message Html
    compute='_compute_to_validate_message'
  • validated_message Html
    compute='_compute_validated_message'
  • validation_status Selection
    compute='_compute_validation_status' default='no' selection=[('no', 'Without validation'), ('waiting', 'Waiting'), ('pending', 'Pending'), ('rejected', 'Rejected'), ('validated', 'Validated')] store=True
Public methods (8)
  • evaluate_tier(self, tier)
  • get_view(self, view_id=None, view_type='form', **options)
    @api.model
  • reject_tier(self)
  • request_validation(self)
  • restart_validation(self)
  • unlink(self)
  • validate_tier(self)
  • write(self, vals)

New fields (9)
  • allowed_to_write_after_validation Boolean
    default=True string='Write after Validation'
  • allowed_to_write_under_validation Boolean
    default=True string='Write under Validation'
  • company_id Many2one → res.company
    comodel_name='res.company' default=<expr> string='Company'
  • field_ids Many2many → ir.model.fields
    comodel_name='ir.model.fields' domain="[('id', 'in', valid_model_field_ids)]" required=True string='Fields'
  • group_ids Many2many → res.groups
    comodel_name='res.groups' help='Allowed groups to use this Tier Validation Exception' string='Groups'
  • model_id Many2one → ir.model
    comodel_name='ir.model' domain=<expr> ondelete='cascade' required=True string='Model'
  • model_name Char
    index=True related='model_id.model' store=True string='Model Name'
  • name Char
    default='New Tier Validation Exception' required=True
  • valid_model_field_ids One2many → ir.model.fields
    comodel_name='ir.model.fields' compute='_compute_valid_model_field_ids'
Public methods (0)

No public methods.

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…