You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
5.3 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2017 Eficent Business and IT Consulting Services S.L.
  3. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
  4. from openerp import api, fields, models, _
  5. from openerp.exceptions import ValidationError, UserError
  6. from openerp.tools.safe_eval import safe_eval
  7. class TierValidation(models.AbstractModel):
  8. _name = "tier.validation"
  9. _state_field = 'state'
  10. _state_from = ['draft']
  11. _state_to = ['confirmed']
  12. _cancel_state = 'cancel'
  13. # TODO: reset validation?
  14. # TODO: step by step validation?
  15. review_ids = fields.One2many(
  16. comodel_name='tier.review', inverse_name='res_id',
  17. string='Validations',
  18. domain=lambda self: [('model', '=', self._name)],
  19. auto_join=True,
  20. )
  21. validated = fields.Boolean(compute="_compute_validated_rejected")
  22. need_validation = fields.Boolean(compute="_compute_need_validation")
  23. rejected = fields.Boolean(compute="_compute_validated_rejected")
  24. reviewer_ids = fields.Many2many(
  25. string="Reviewers", comodel_name="res.users",
  26. compute="_compute_reviewer_ids",
  27. search="_search_reviewer_ids",
  28. )
  29. @api.multi
  30. @api.depends('review_ids')
  31. def _compute_reviewer_ids(self):
  32. for rec in self:
  33. rec.reviewer_ids = rec.review_ids.filtered(
  34. lambda r: r.status == 'pending').mapped('reviewer_ids')
  35. @api.model
  36. def _search_reviewer_ids(self, operator, value):
  37. reviews = self.env['tier.review'].search([
  38. ('model', '=', self._name), ('reviewer_ids', operator, value)])
  39. return [('id', 'in', list(set(reviews.mapped('res_id'))))]
  40. @api.multi
  41. def _compute_validated_rejected(self):
  42. """Override for different validation/rejection policy."""
  43. for rec in self:
  44. # sort by tier
  45. rec.validated = not any(
  46. [s != 'approved' for s in self.review_ids.mapped('status')])
  47. rec.rejected = any(
  48. [s == 'rejected' for s in self.review_ids.mapped('status')])
  49. @api.multi
  50. def _compute_need_validation(self):
  51. for rec in self:
  52. rec.need_validation = not self.review_ids and self.env[
  53. 'tier.definition'].search([('model', '=', self._name)]) and \
  54. getattr(rec, self._state_field) in self._state_from
  55. @api.multi
  56. def evaluate_tier(self, tier):
  57. try:
  58. res = safe_eval(tier.python_code, globals_dict={'rec': self})
  59. except Exception, error:
  60. raise UserError(_(
  61. "Error evaluating tier validation conditions.\n %s") % error)
  62. return res
  63. @api.multi
  64. def write(self, vals):
  65. for rec in self:
  66. if (getattr(rec, self._state_field) in self._state_from and
  67. vals.get(self._state_field) in self._state_to):
  68. if rec.need_validation:
  69. raise ValidationError(_(
  70. "This action needs to be validated for at least one "
  71. "record. \nPlease request a validation."))
  72. if not rec.validated:
  73. raise ValidationError(_(
  74. "A validation process is still open for at least "
  75. "one record."))
  76. if (rec.review_ids and getattr(rec, self._state_field) in
  77. self._state_from and not vals.get(self._state_field) in
  78. (self._state_to + [self._cancel_state])):
  79. raise ValidationError(_("The operation is under validation."))
  80. if vals.get(self._state_field) in self._state_from:
  81. self.mapped('review_ids').sudo().unlink()
  82. return super(TierValidation, self).write(vals)
  83. @api.multi
  84. def validate_tier(self):
  85. for rec in self:
  86. user_reviews = rec.review_ids.filtered(
  87. lambda r: r.status in ('pending', 'rejected') and
  88. (r.reviewer_id == self.env.user or
  89. r.reviewer_group_id in self.env.user.groups_id))
  90. user_reviews.write({'status': 'approved'})
  91. @api.multi
  92. def reject_tier(self):
  93. for rec in self:
  94. user_reviews = rec.review_ids.filtered(
  95. lambda r: r.status in ('pending', 'approved') and
  96. (r.reviewer_id == self.env.user or
  97. r.reviewer_group_id in self.env.user.groups_id))
  98. user_reviews.write({'status': 'rejected'})
  99. @api.multi
  100. def request_validation(self):
  101. td_obj = self.env['tier.definition']
  102. tr_obj = self.env['tier.review']
  103. for rec in self:
  104. if getattr(rec, self._state_field) in self._state_from:
  105. if rec.need_validation:
  106. tier_definitions = td_obj.search([
  107. ('model', '=', self._name)], order="sequence desc")
  108. sequence = 0
  109. for td in tier_definitions:
  110. if self.evaluate_tier(td):
  111. sequence += 1
  112. tr_obj.create({
  113. 'model': self._name,
  114. 'res_id': rec.id,
  115. 'definition_id': td.id,
  116. 'sequence': sequence,
  117. })
  118. # TODO: notify? post some msg in chatter?
  119. return True