Files

196 lines
6.2 KiB
Python
Raw Permalink Normal View History

2026-07-01 14:41:49 +07:00
# -*- coding: utf-8 -*-
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from .selection import ApproverState, ApprovalMethods, ApprovalStep
class DocApprovalTeam(models.Model):
_name = 'xf.doc.approval.team'
_description = 'Doc Approval Team'
active = fields.Boolean('Active', default=True)
name = fields.Char(
string='Name',
required=True,
)
user_id = fields.Many2one(
string='Team Leader',
comodel_name='res.users',
required=True,
default=lambda self: self.env.user,
index=True
)
company_id = fields.Many2one(
string='Company',
comodel_name='res.company',
required=True,
default=lambda self: self.env.company.id,
index=True,
)
approver_ids = fields.One2many(
string='Approvers',
comodel_name='xf.doc.approval.team.approver',
inverse_name='team_id',
)
# Validation
@api.constrains('company_id')
def _check_team_company(self):
for team in self:
team.approver_ids.validate_company(team.company_id)
class DocApprovalApproverAbstract(models.Model):
_name = 'xf.doc.approval.approver.abstract'
_description = 'Abstract Approver'
_order = 'step'
_rec_name = 'user_id'
step = fields.Selection(
string='Step',
selection=ApprovalStep.list,
required=True,
default=ApprovalStep.default,
)
user_id = fields.Many2one(
string='Approver',
comodel_name='res.users',
required=True
)
role = fields.Char(
string='Role/Position',
required=True,
default="Approver"
)
# Onchange handlers
@api.onchange('user_id')
def _detect_user_role(self):
for approver in self:
# if user related to employee, try to get job title for hr.employee
employee = hasattr(approver.user_id, 'employee_ids') and getattr(approver.user_id, 'employee_ids')
employee_job_id = hasattr(employee, 'job_id') and getattr(employee, 'job_id')
employee_job_title = employee_job_id.name if employee_job_id else False
if employee_job_title:
approver.role = employee_job_title
continue
# if user related partner, try to get job title for res.partner
partner = approver.user_id.partner_id
partner_job_title = hasattr(partner, 'function') and getattr(partner, 'function')
if partner_job_title:
approver.role = partner_job_title
# Validation
@api.constrains('user_id')
def _check_users(self):
for approver in self:
if not approver.user_id.has_group('xf_doc_approval.group_xf_doc_approval_user'):
raise ValidationError(_('%s does not have access to the Doc Approval module.') % (approver.user_id.name,)
+ '\n' +
_('Please ask system administrator to add him/her to the Doc Approval module group first.'))
def validate_company(self, company):
if not company:
return
for approver in self:
if company not in approver.user_id.company_ids:
raise ValidationError(
_('%s does not have access to the company %s') % (approver.user_id.name, company.name))
class DocApprovalTeamApprover(models.Model):
_name = 'xf.doc.approval.team.approver'
_inherit = ['xf.doc.approval.approver.abstract']
_description = 'Approval Team Member'
team_id = fields.Many2one(
string='Team',
comodel_name='xf.doc.approval.team',
required=True,
ondelete='cascade'
)
# Validation
@api.constrains('user_id', 'team_id')
def _check_users(self):
for approver in self:
approver.validate_company(approver.team_id.company_id)
return super(DocApprovalTeamApprover, self)._check_users()
class DocApprovalDocumentApprover(models.Model):
_name = 'xf.doc.approval.document.approver'
_inherit = ['xf.doc.approval.approver.abstract']
_description = 'Doc Approver'
team_approver_id = fields.Many2one(
string='Doc Team Approver',
comodel_name='xf.doc.approval.team.approver',
ondelete='set null'
)
document_package_id = fields.Many2one(
string='Document Package',
comodel_name='xf.doc.approval.document.package',
required=True,
ondelete='cascade',
)
method = fields.Selection(
string='Method',
related='document_package_id.method',
readonly=True,
)
state = fields.Selection(
string='Status',
selection=ApproverState.list,
readonly=True,
required=True,
default=ApproverState.default
)
notes = fields.Text(
string='Notes',
readonly=True,
)
# Validation
@api.constrains('user_id', 'document_package_id')
def _check_users(self):
for approver in self:
approver.validate_company(approver.document_package_id.company_id)
return super(DocApprovalDocumentApprover, self)._check_users()
# User actions
def action_wizard(self, view_ref, window_title):
self.ensure_one()
view = self.env.ref('xf_doc_approval.' + view_ref)
return {
'name': window_title,
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': self._name,
'res_id': self.id,
'views': [(view.id, 'form')],
'view_id': view.id,
'target': 'new'
}
def action_approve(self):
for approver in self:
document_package = approver.document_package_id
approver.state = 'approved'
if document_package.approval_state == 'to approve':
document_package.sudo().action_send_for_approval()
elif document_package.approval_state == 'approved':
document_package.sudo().action_finish_approval()
def action_reject(self):
for approver in self:
approver.state = 'rejected'
approver.document_package_id.sudo().set_state('rejected', {'reject_reason': approver.notes})