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

175 lines
7.3 KiB
Python

# -*- coding: utf-8 -*-
from odoo import api, fields, models, _
from datetime import datetime, timedelta
class PlanningRequest(models.Model):
"""Modèle pour les demandes de planning créées par les utilisateurs du portail."""
_name = 'portal.planning.request'
_description = 'Planning Request'
_rec_name = 'name'
_order = 'start_datetime desc'
_inherit = ['mail.thread', 'mail.activity.mixin']
name = fields.Char(string='Titre', required=True, tracking=True)
description = fields.Text(string='Description', tracking=True)
employee_id = fields.Many2one('hr.employee', string='Employé', required=True, default=lambda self: self.env.user.employee_id.id, tracking=True)
user_id = fields.Many2one('res.users', string='Utilisateur', related='employee_id.user_id', store=True)
role_id = fields.Many2one('planning.role', string='Rôle', tracking=True)
start_datetime = fields.Datetime(string='Date de début', required=True, tracking=True)
end_datetime = fields.Datetime(string='Date de fin', required=True, tracking=True)
allocated_hours = fields.Float(string='Durée', compute='_compute_allocated_hours', store=True, readonly=False, tracking=True)
state = fields.Selection([
('draft', 'Brouillon'),
('submitted', 'Soumis'),
('approved', 'Approuvé'),
('rejected', 'Refusé'),
('cancelled', 'Annulé'),
], string='État', default='draft', tracking=True, copy=False)
company_id = fields.Many2one('res.company', string='Société', default=lambda self: self.env.company)
planning_slot_id = fields.Many2one('planning.slot', string='Créneau de planning créé', readonly=True, copy=False)
can_edit = fields.Boolean(compute='_compute_can_edit')
can_submit = fields.Boolean(compute='_compute_can_submit')
can_approve = fields.Boolean(compute='_compute_can_approve')
can_reject = fields.Boolean(compute='_compute_can_reject')
can_cancel = fields.Boolean(compute='_compute_can_cancel')
@api.depends('start_datetime', 'end_datetime')
def _compute_allocated_hours(self):
for request in self:
if request.start_datetime and request.end_datetime:
delta = request.end_datetime - request.start_datetime
request.allocated_hours = delta.total_seconds() / 3600
else:
request.allocated_hours = 0
@api.depends('state', 'user_id')
def _compute_can_edit(self):
for request in self:
request.can_edit = request.state == 'draft' and request.user_id.id == self.env.user.id
@api.depends('state', 'user_id')
def _compute_can_submit(self):
for request in self:
request.can_submit = request.state == 'draft' and request.user_id.id == self.env.user.id
@api.depends('state')
def _compute_can_approve(self):
is_manager = self.env.user.has_group('planning.group_planning_manager')
for request in self:
request.can_approve = request.state == 'submitted' and is_manager
@api.depends('state')
def _compute_can_reject(self):
is_manager = self.env.user.has_group('planning.group_planning_manager')
for request in self:
request.can_reject = request.state == 'submitted' and is_manager
@api.depends('state', 'user_id')
def _compute_can_cancel(self):
is_manager = self.env.user.has_group('planning.group_planning_manager')
for request in self:
request.can_cancel = (request.state in ['draft', 'submitted'] and request.user_id.id == self.env.user.id) or \
(request.state in ['submitted', 'approved'] and is_manager)
def action_submit(self):
self.ensure_one()
if self.can_submit:
self.write({'state': 'submitted'})
# Envoyer une notification au responsable
self.message_post(
body=_('Demande de planning soumise par %s') % self.employee_id.name,
message_type='notification',
subtype_xmlid='mail.mt_comment'
)
return True
def action_approve(self):
self.ensure_one()
if self.can_approve:
# Créer un créneau de planning réel
slot_vals = {
'employee_id': self.employee_id.id,
'role_id': self.role_id.id,
'start_datetime': self.start_datetime,
'end_datetime': self.end_datetime,
'allocated_hours': self.allocated_hours,
'name': self.description,
'state': 'published',
}
slot = self.env['planning.slot'].sudo().create(slot_vals)
# Mettre à jour la demande
self.write({
'state': 'approved',
'planning_slot_id': slot.id
})
# Envoyer une notification à l'employé
self.message_post(
body=_('Demande de planning approuvée. Un créneau de planning a été créé.'),
message_type='notification',
subtype_xmlid='mail.mt_comment'
)
return True
def action_reject(self):
self.ensure_one()
if self.can_reject:
self.write({'state': 'rejected'})
# Envoyer une notification à l'employé
self.message_post(
body=_('Demande de planning refusée.'),
message_type='notification',
subtype_xmlid='mail.mt_comment'
)
return True
def action_cancel(self):
self.ensure_one()
if self.can_cancel:
self.write({'state': 'cancelled'})
# Envoyer une notification
self.message_post(
body=_('Demande de planning annulée.'),
message_type='notification',
subtype_xmlid='mail.mt_comment'
)
return True
def action_reset_to_draft(self):
self.ensure_one()
if self.state in ['rejected', 'cancelled'] and self.user_id.id == self.env.user.id:
self.write({'state': 'draft'})
return True
@api.model
def _sync_planning_slots(self):
"""Synchronise les créneaux de planning avec les demandes approuvées."""
# Cette méthode peut être utilisée pour synchroniser les demandes approuvées
# avec les créneaux de planning existants si nécessaire
return True
def action_view_planning_slot(self):
"""Afficher le créneau de planning associé à cette demande."""
self.ensure_one()
if not self.planning_slot_id:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Information'),
'message': _('Aucun créneau de planning n\'est associé à cette demande.'),
'type': 'info',
'sticky': False,
}
}
return {
'name': _('Créneau de planning'),
'type': 'ir.actions.act_window',
'res_model': 'planning.slot',
'res_id': self.planning_slot_id.id,
'view_mode': 'form',
'target': 'current',
}