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

203 lines
7.9 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime, timedelta
from odoo.tests.common import TransactionCase, tagged
from odoo.exceptions import AccessError, ValidationError
@tagged('post_install', '-at_install')
class TestPlanningSlot(TransactionCase):
"""Test cases for planning.slot model extended for portal access."""
@classmethod
def setUpClass(cls):
super().setUpClass()
# Créer un utilisateur portail
cls.portal_user = cls.env['res.users'].create({
'name': 'Portal User',
'login': 'portal_test_user',
'email': 'portal_test@example.com',
'groups_id': [(6, 0, [cls.env.ref('base.group_portal').id])],
})
# Créer un employé lié à l'utilisateur portail
cls.employee = cls.env['hr.employee'].create({
'name': 'Test Employee',
'user_id': cls.portal_user.id,
})
# Créer un rôle de planning
cls.role = cls.env['planning.role'].create({
'name': 'Test Role',
})
# Dates pour les tests
cls.start_datetime = datetime.now().replace(hour=8, minute=0, second=0, microsecond=0) + timedelta(days=1)
cls.end_datetime = cls.start_datetime + timedelta(hours=4)
# Créer un créneau de planning
cls.slot = cls.env['planning.slot'].sudo().create({
'name': 'Test Slot',
'start_datetime': cls.start_datetime,
'end_datetime': cls.end_datetime,
'role_id': cls.role.id,
'employee_id': cls.employee.id,
'allocated_hours': 4.0,
'portal_status': 'draft',
'portal_confirmed': False,
'portal_modified': False,
})
def test_01_confirm_slot_portal(self):
"""Test la confirmation d'un créneau via le portail."""
# Confirmer le créneau
self.slot.action_confirm_portal()
# Vérifier que le statut a changé
self.assertEqual(self.slot.portal_status, 'confirmed')
self.assertTrue(self.slot.portal_confirmed)
self.assertFalse(self.slot.portal_modified)
def test_02_modify_slot_portal(self):
"""Test la modification d'un créneau via le portail."""
# Nouvelles valeurs pour la modification
new_start = self.start_datetime + timedelta(hours=1)
new_end = self.end_datetime + timedelta(hours=1)
# Modifier le créneau
self.slot.write({
'portal_start_datetime': new_start,
'portal_end_datetime': new_end,
'portal_modified': True,
'portal_status': 'modified',
})
# Vérifier que les valeurs de modification ont été enregistrées
self.assertEqual(self.slot.portal_start_datetime, new_start)
self.assertEqual(self.slot.portal_end_datetime, new_end)
self.assertTrue(self.slot.portal_modified)
self.assertEqual(self.slot.portal_status, 'modified')
# Approuver la modification
self.slot.action_approve_modification()
# Vérifier que les valeurs ont été appliquées au créneau
self.assertEqual(self.slot.start_datetime, new_start)
self.assertEqual(self.slot.end_datetime, new_end)
self.assertEqual(self.slot.portal_status, 'confirmed')
self.assertTrue(self.slot.portal_confirmed)
self.assertFalse(self.slot.portal_modified)
def test_03_reject_modification(self):
"""Test le rejet d'une modification de créneau."""
# Nouvelles valeurs pour la modification
new_start = self.start_datetime + timedelta(hours=1)
new_end = self.end_datetime + timedelta(hours=1)
# Modifier le créneau
self.slot.write({
'portal_start_datetime': new_start,
'portal_end_datetime': new_end,
'portal_modified': True,
'portal_status': 'modified',
})
# Rejeter la modification
self.slot.action_reject_modification()
# Vérifier que les valeurs originales sont conservées
self.assertEqual(self.slot.start_datetime, self.start_datetime)
self.assertEqual(self.slot.end_datetime, self.end_datetime)
self.assertEqual(self.slot.portal_status, 'draft')
self.assertFalse(self.slot.portal_confirmed)
self.assertFalse(self.slot.portal_modified)
def test_04_generate_timesheet(self):
"""Test la génération de feuille de temps à partir d'un créneau."""
# Activer la génération de feuilles de temps
self.slot.write({
'generate_timesheet': True,
'portal_status': 'confirmed',
'portal_confirmed': True,
})
# Générer la feuille de temps
self.slot.action_generate_timesheet()
# Vérifier qu'une feuille de temps a été créée
timesheet = self.env['account.analytic.line'].sudo().search([
('planning_slot_id', '=', self.slot.id),
('employee_id', '=', self.employee.id),
], limit=1)
self.assertTrue(timesheet, "Une feuille de temps aurait dû être créée")
self.assertEqual(timesheet.unit_amount, self.slot.allocated_hours)
def test_05_compute_can_modify(self):
"""Test le calcul du champ portal_can_modify."""
# Par défaut, un créneau en brouillon peut être modifié
self.assertTrue(self.slot.portal_can_modify)
# Un créneau confirmé ne peut pas être modifié
self.slot.write({
'portal_status': 'confirmed',
'portal_confirmed': True,
})
self.assertFalse(self.slot.portal_can_modify)
# Un créneau déjà modifié ne peut pas être modifié à nouveau
self.slot.write({
'portal_status': 'modified',
'portal_modified': True,
'portal_confirmed': False,
})
self.assertFalse(self.slot.portal_can_modify)
def test_06_compute_can_confirm(self):
"""Test le calcul du champ portal_can_confirm."""
# Par défaut, un créneau en brouillon peut être confirmé
self.assertTrue(self.slot.portal_can_confirm)
# Un créneau déjà confirmé ne peut pas être confirmé à nouveau
self.slot.write({
'portal_status': 'confirmed',
'portal_confirmed': True,
})
self.assertFalse(self.slot.portal_can_confirm)
# Un créneau modifié ne peut pas être confirmé
self.slot.write({
'portal_status': 'modified',
'portal_modified': True,
'portal_confirmed': False,
})
self.assertFalse(self.slot.portal_can_confirm)
def test_07_compute_can_exchange(self):
"""Test le calcul du champ portal_can_exchange."""
# Par défaut, un créneau peut être échangé
self.assertTrue(self.slot.portal_can_exchange)
# Un créneau avec une demande d'échange en cours ne peut pas être échangé à nouveau
exchange = self.env['portal.planning.exchange'].sudo().create({
'name': 'Test Exchange',
'source_slot_id': self.slot.id,
'source_user_id': self.portal_user.id,
'state': 'pending',
})
# Rafraîchir le créneau pour recalculer les champs calculés
self.slot.refresh()
# Vérifier que le créneau ne peut plus être échangé
self.assertFalse(self.slot.portal_can_exchange)
# Annuler la demande d'échange
exchange.action_cancel()
# Rafraîchir le créneau pour recalculer les champs calculés
self.slot.refresh()
# Vérifier que le créneau peut à nouveau être échangé
self.assertTrue(self.slot.portal_can_exchange)