1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/approvals/models/approval_category.py
2024-12-10 09:04:09 +07:00

163 lines
8.6 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import base64
from odoo import api, fields, models, tools, _
from odoo.exceptions import ValidationError
CATEGORY_SELECTION = [
('required', 'Required'),
('optional', 'Optional'),
('no', 'None')]
class ApprovalCategory(models.Model):
_name = 'approval.category'
_description = 'Approval Category'
_order = 'sequence, id'
_check_company_auto = True
def _get_default_image(self):
default_image_path = 'approvals/static/src/img/Folder.png'
return base64.b64encode(tools.misc.file_open(default_image_path, 'rb').read())
name = fields.Char(string="Name", translate=True, required=True)
company_id = fields.Many2one(
'res.company', 'Company', copy=False,
required=True, index=True, default=lambda s: s.env.company)
active = fields.Boolean(default=True)
sequence = fields.Integer(string="Sequence")
description = fields.Char(string="Description", translate=True)
image = fields.Binary(string='Image', default=_get_default_image)
has_date = fields.Selection(CATEGORY_SELECTION, string="Has Date", default="no", required=True)
has_period = fields.Selection(CATEGORY_SELECTION, string="Has Period", default="no", required=True)
has_quantity = fields.Selection(CATEGORY_SELECTION, string="Has Quantity", default="no", required=True)
has_amount = fields.Selection(CATEGORY_SELECTION, string="Has Amount", default="no", required=True)
has_reference = fields.Selection(
CATEGORY_SELECTION, string="Has Reference", default="no", required=True,
help="An additional reference that should be specified on the request.")
has_partner = fields.Selection(CATEGORY_SELECTION, string="Has Contact", default="no", required=True)
has_payment_method = fields.Selection(CATEGORY_SELECTION, string="Has Payment", default="no", required=True)
has_location = fields.Selection(CATEGORY_SELECTION, string="Has Location", default="no", required=True)
has_product = fields.Selection(
CATEGORY_SELECTION, string="Has Product", default="no", required=True,
help="Additional products that should be specified on the request.")
requirer_document = fields.Selection([('required', 'Required'), ('optional', 'Optional')], string="Documents", default="optional", required=True)
approval_minimum = fields.Integer(string="Minimum Approval", default="1", required=True)
invalid_minimum = fields.Boolean(compute='_compute_invalid_minimum')
invalid_minimum_warning = fields.Char(compute='_compute_invalid_minimum')
approval_type = fields.Selection(string="Approval Type", selection=[],
help="Allows you to define which documents you would like to create once the request has been approved")
manager_approval = fields.Selection([('approver', 'Is Approver'), ('required', 'Is Required Approver')],
string="Employee's Manager",
help="""How the employee's manager interacts with this type of approval.
Empty: do nothing
Is Approver: the employee's manager will be in the approver list
Is Required Approver: the employee's manager will be required to approve the request.
""")
user_ids = fields.Many2many('res.users', compute='_compute_user_ids', string="Approver Users")
approver_ids = fields.One2many('approval.category.approver', 'category_id', string="Approvers")
approver_sequence = fields.Boolean('Approvers Sequence?', help="If checked, the approvers have to approve in sequence (one after the other). If Employee's Manager is selected as approver, they will be the first in line.")
request_to_validate_count = fields.Integer("Number of requests to validate", compute="_compute_request_to_validate_count")
automated_sequence = fields.Boolean('Automated Sequence?',
help="If checked, the Approval Requests will have an automated generated name based on the given code.")
sequence_code = fields.Char(string="Code")
sequence_id = fields.Many2one('ir.sequence', 'Reference Sequence',
copy=False, check_company=True)
def _compute_request_to_validate_count(self):
domain = [('request_status', '=', 'pending'), ('approver_ids.user_id', '=', self.env.user.id)]
requests_data = self.env['approval.request']._read_group(domain, ['category_id'], ['__count'])
requests_mapped_data = {category.id: count for category, count in requests_data}
for category in self:
category.request_to_validate_count = requests_mapped_data.get(category.id, 0)
@api.depends_context('lang')
@api.depends('approval_minimum', 'approver_ids', 'manager_approval')
def _compute_invalid_minimum(self):
for record in self:
if record.approval_minimum > len(record.approver_ids) + int(bool(record.manager_approval)):
record.invalid_minimum = True
else:
record.invalid_minimum = False
record.invalid_minimum_warning = record.invalid_minimum and _('Your minimum approval exceeds the total of default approvers.')
@api.depends('approver_ids')
def _compute_user_ids(self):
for record in self:
record.user_ids = record.approver_ids.user_id
@api.constrains('approval_minimum', 'approver_ids')
def _constrains_approval_minimum(self):
for record in self:
if record.approval_minimum < len(record.approver_ids.filtered('required')):
raise ValidationError(_('Minimum Approval must be equal or superior to the sum of required Approvers.'))
@api.constrains('approver_ids')
def _constrains_approver_ids(self):
# There seems to be a problem with how the database is updated which doesn't let use to an sql constraint for this
# Issue is: records seem to be created before others are saved, meaning that if you originally have only user a
# change user a to user b and add a new line with user a, the second line will be created and will trigger the constraint
# before the first line will be updated which wouldn't trigger a ValidationError
for record in self:
if len(record.approver_ids) != len(record.approver_ids.user_id):
raise ValidationError(_('An user may not be in the approver list multiple times.'))
@api.constrains('approver_sequence', 'approval_minimum')
def _constrains_approver_sequence(self):
if any(a.approver_sequence and not a.approval_minimum for a in self):
raise ValidationError(_('Approver Sequence can only be activated with at least 1 minimum approver.'))
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if vals.get('automated_sequence'):
sequence = self.env['ir.sequence'].create({
'name': _('Sequence') + ' ' + vals['sequence_code'],
'padding': 5,
'prefix': vals['sequence_code'],
'company_id': vals.get('company_id'),
})
vals['sequence_id'] = sequence.id
return super().create(vals_list)
def write(self, vals):
if 'sequence_code' in vals:
for approval_category in self:
sequence_vals = {
'name': _('Sequence') + ' ' + vals['sequence_code'],
'padding': 5,
'prefix': vals['sequence_code'],
}
if approval_category.sequence_id:
approval_category.sequence_id.write(sequence_vals)
else:
sequence_vals['company_id'] = vals.get('company_id', approval_category.company_id.id)
sequence = self.env['ir.sequence'].create(sequence_vals)
approval_category.sequence_id = sequence
if 'company_id' in vals:
for approval_category in self:
if approval_category.sequence_id:
approval_category.sequence_id.company_id = vals.get('company_id')
return super().write(vals)
def create_request(self):
self.ensure_one()
# If category uses sequence, set next sequence as name
# (if not, set category name as default name).
return {
"type": "ir.actions.act_window",
"res_model": "approval.request",
"views": [[False, "form"]],
"context": {
'default_name': _('New') if self.automated_sequence else self.name,
'default_category_id': self.id,
'default_request_owner_id': self.env.user.id,
'default_request_status': 'new'
},
}