bemade-addons/portal_planning/models/portal_planning_modification.py
2025-06-19 11:31:33 -04:00

249 lines
7.8 KiB
Python

# -*- coding: utf-8 -*-
from odoo import api, fields, models, _
from datetime import datetime, timedelta
class PlanningModification(models.Model):
"""Modèle pour suivre les modifications de créneaux de planning via le portail."""
_name = 'portal.planning.modification'
_description = 'Modification de Planning via Portail'
_rec_name = 'slot_id'
_order = 'date desc'
_inherit = ['mail.thread', 'mail.activity.mixin']
slot_id = fields.Many2one(
'planning.slot',
string='Créneau de planning',
required=True,
ondelete='cascade',
tracking=True
)
user_id = fields.Many2one(
'res.users',
string='Demandé par',
required=True,
default=lambda self: self.env.user.id,
tracking=True
)
employee_id = fields.Many2one(
'hr.employee',
string='Employé',
related='slot_id.employee_id',
store=True,
readonly=True
)
date = fields.Datetime(
string='Date de demande',
required=True,
default=fields.Datetime.now,
tracking=True
)
# Valeurs originales
old_start = fields.Datetime(
string='Début original',
required=True,
tracking=True
)
old_end = fields.Datetime(
string='Fin originale',
required=True,
tracking=True
)
old_role_id = fields.Many2one(
'planning.role',
string='Rôle original',
tracking=True
)
# Nouvelles valeurs
new_start = fields.Datetime(
string='Nouveau début',
required=True,
tracking=True
)
new_end = fields.Datetime(
string='Nouvelle fin',
required=True,
tracking=True
)
new_role_id = fields.Many2one(
'planning.role',
string='Nouveau rôle',
tracking=True
)
# Suivi de la demande
state = fields.Selection([
('pending', 'En attente'),
('approved', 'Approuvé'),
('rejected', 'Refusé'),
('cancelled', 'Annulé')
], string='État', default='pending', tracking=True, copy=False)
approver_id = fields.Many2one(
'res.users',
string='Approuvé/Refusé par',
copy=False,
tracking=True
)
approval_date = fields.Datetime(
string='Date d\'approbation/refus',
copy=False,
tracking=True
)
notes = fields.Text(
string='Notes',
tracking=True
)
company_id = fields.Many2one(
'res.company',
string='Société',
default=lambda self: self.env.company
)
# Champs calculés
allocated_hours = fields.Float(
string='Heures allouées',
compute='_compute_allocated_hours',
store=True,
readonly=True
)
can_approve = fields.Boolean(
compute='_compute_can_approve',
string='Peut approuver',
help="Indique si l'utilisateur actuel peut approuver cette demande"
)
can_reject = fields.Boolean(
compute='_compute_can_reject',
string='Peut refuser',
help="Indique si l'utilisateur actuel peut refuser cette demande"
)
can_cancel = fields.Boolean(
compute='_compute_can_cancel',
string='Peut annuler',
help="Indique si l'utilisateur actuel peut annuler cette demande"
)
@api.depends('new_start', 'new_end')
def _compute_allocated_hours(self):
"""Calcule le nombre d'heures allouées pour la modification."""
for modification in self:
if modification.new_start and modification.new_end:
delta = modification.new_end - modification.new_start
modification.allocated_hours = delta.total_seconds() / 3600
else:
modification.allocated_hours = 0
@api.depends('state')
def _compute_can_approve(self):
"""Détermine si l'utilisateur actuel peut approuver cette demande."""
is_manager = self.env.user.has_group('planning.group_planning_manager')
for modification in self:
modification.can_approve = modification.state == 'pending' and is_manager
@api.depends('state')
def _compute_can_reject(self):
"""Détermine si l'utilisateur actuel peut refuser cette demande."""
is_manager = self.env.user.has_group('planning.group_planning_manager')
for modification in self:
modification.can_reject = modification.state == 'pending' and is_manager
@api.depends('state', 'user_id')
def _compute_can_cancel(self):
"""Détermine si l'utilisateur actuel peut annuler cette demande."""
is_manager = self.env.user.has_group('planning.group_planning_manager')
for modification in self:
modification.can_cancel = (
modification.state == 'pending' and
(modification.user_id.id == self.env.user.id or is_manager)
)
def action_approve(self):
"""Approuve la demande de modification."""
self.ensure_one()
if not self.can_approve:
return False
# Mettre à jour le créneau de planning
self.slot_id.write({
'start_datetime': self.new_start,
'end_datetime': self.new_end,
'allocated_hours': self.allocated_hours,
'role_id': self.new_role_id.id if self.new_role_id else self.slot_id.role_id.id,
'portal_modification_approved': 'approved',
'portal_confirmed': False, # Nécessite une nouvelle confirmation
})
# Mettre à jour la demande
self.write({
'state': 'approved',
'approver_id': self.env.user.id,
'approval_date': fields.Datetime.now()
})
# Envoyer une notification à l'employé
self.message_post(
body=_('Demande de modification approuvée par %s') % self.env.user.name,
message_type='notification',
subtype_xmlid='mail.mt_comment',
partner_ids=[self.user_id.partner_id.id]
)
return True
def action_reject(self):
"""Refuse la demande de modification."""
self.ensure_one()
if not self.can_reject:
return False
# Mettre à jour le créneau de planning
self.slot_id.write({
'portal_modification_approved': 'rejected'
})
# Mettre à jour la demande
self.write({
'state': 'rejected',
'approver_id': self.env.user.id,
'approval_date': fields.Datetime.now()
})
# Envoyer une notification à l'employé
self.message_post(
body=_('Demande de modification refusée par %s') % self.env.user.name,
message_type='notification',
subtype_xmlid='mail.mt_comment',
partner_ids=[self.user_id.partner_id.id]
)
return True
def action_cancel(self):
"""Annule la demande de modification."""
self.ensure_one()
if not self.can_cancel:
return False
# Mettre à jour le créneau de planning si c'est l'employé qui annule
if self.user_id.id == self.env.user.id:
self.slot_id.write({
'portal_modification_approved': False,
'portal_modified': False
})
# Mettre à jour la demande
self.write({
'state': 'cancelled',
'approver_id': self.env.user.id,
'approval_date': fields.Datetime.now()
})
# Envoyer une notification
self.message_post(
body=_('Demande de modification annulée par %s') % self.env.user.name,
message_type='notification',
subtype_xmlid='mail.mt_comment'
)
return True