206 lines
11 KiB
Python
206 lines
11 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from datetime import datetime, date, time
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
from odoo.tests import new_test_user, tagged
|
|
from .test_ui_common import TestUiCommon
|
|
|
|
|
|
@tagged('-at_install', 'post_install')
|
|
class TestUi(TestUiCommon):
|
|
def test_01_ui(self):
|
|
self.start_tour("/", 'planning_test_tour', login='admin')
|
|
|
|
def test_shift_switch_ui(self):
|
|
bert_user = new_test_user(self.env,
|
|
login='bert_user',
|
|
groups='planning.group_planning_user',
|
|
name='Bert User',
|
|
email='user@example.com')
|
|
joseph_user = new_test_user(self.env,
|
|
login='joseph_user',
|
|
groups='planning.group_planning_user',
|
|
name='Joseph User',
|
|
email='juser@example.com')
|
|
employee_bert, employee_joseph = self.env['hr.employee'].create([
|
|
{
|
|
'name': 'bert',
|
|
'work_email': 'bert@a.be',
|
|
'tz': 'UTC',
|
|
'employee_type': 'freelance',
|
|
'create_date': '2015-01-01 00:00:00',
|
|
'user_id': bert_user.id,
|
|
},
|
|
{
|
|
'name': 'joseph',
|
|
'work_email': 'joseph@a.be',
|
|
'tz': 'UTC',
|
|
'employee_type': 'freelance',
|
|
'create_date': '2015-01-01 00:00:00',
|
|
'user_id': joseph_user.id,
|
|
}
|
|
])
|
|
test_slot = self.env['planning.slot'].create({
|
|
'start_datetime': datetime.now(),
|
|
'end_datetime': datetime.now() + relativedelta(hours=1),
|
|
'state': 'published',
|
|
'resource_id': employee_bert.resource_id.id,
|
|
})
|
|
self.assertEqual(test_slot.request_to_switch, False, 'Before requesting to switch, the request to switch should be False')
|
|
self.start_tour("/", 'planning_shift_switching_backend', login='bert_user')
|
|
self.assertEqual(test_slot.request_to_switch, True, 'Before requesting to switch, the request to switch should be False')
|
|
self.start_tour("/", 'planning_assigning_unwanted_shift_backend', login='admin')
|
|
self.assertEqual(test_slot.request_to_switch, False, 'After the assign action, the request to switch should be False')
|
|
self.assertEqual(test_slot.resource_id, employee_joseph.resource_id, 'The shift should now be assigned to Joseph')
|
|
|
|
def test_split_shift_ui(self):
|
|
# create a user with planning manager rights and timezone set to UTC
|
|
hugo = new_test_user(
|
|
self.env,
|
|
login='hugo_user',
|
|
groups='planning.group_planning_manager',
|
|
name='Hugo',
|
|
email='hugo@example.com',
|
|
tz='UTC',
|
|
)
|
|
# 1. Creating work schedule in UTC
|
|
attendance_schedule = { # To round to hours!
|
|
'start_am': time.fromisoformat('08:00:00'),
|
|
'end_am': time.fromisoformat('12:00:00'),
|
|
'start_pm': time.fromisoformat('13:00:00'),
|
|
'end_pm': time.fromisoformat('17:00:00'),
|
|
}
|
|
work_schedule_calendar = self.env['resource.calendar'].create([{
|
|
'name': 'Musketeers schedule (UTC)',
|
|
'tz': 'UTC',
|
|
}])
|
|
self.env['resource.calendar.attendance'].create([
|
|
{
|
|
'name': 'Wednesday AM',
|
|
'dayofweek': '2',
|
|
'hour_from': attendance_schedule['start_am'].hour,
|
|
'hour_to': attendance_schedule['end_am'].hour,
|
|
'calendar_id': work_schedule_calendar.id,
|
|
},
|
|
{
|
|
'name': 'Wednesday PM',
|
|
'dayofweek': '2',
|
|
'hour_from': attendance_schedule['start_am'].hour,
|
|
'hour_to': attendance_schedule['end_am'].hour,
|
|
'calendar_id': work_schedule_calendar.id,
|
|
},
|
|
{
|
|
'name': 'Thursday AM',
|
|
'dayofweek': '3',
|
|
'hour_from': attendance_schedule['start_am'].hour,
|
|
'hour_to': attendance_schedule['end_am'].hour,
|
|
'calendar_id': work_schedule_calendar.id,
|
|
},
|
|
{
|
|
'name': 'Thursday PM',
|
|
'dayofweek': '3',
|
|
'hour_from': attendance_schedule['start_am'].hour,
|
|
'hour_to': attendance_schedule['end_am'].hour,
|
|
'calendar_id': work_schedule_calendar.id,
|
|
},
|
|
{
|
|
'name': 'Friday AM',
|
|
'dayofweek': '4',
|
|
'hour_from': attendance_schedule['start_am'].hour,
|
|
'hour_to': attendance_schedule['end_am'].hour,
|
|
'calendar_id': work_schedule_calendar.id,
|
|
},
|
|
{
|
|
'name': 'Friday PM',
|
|
'dayofweek': '4',
|
|
'hour_from': attendance_schedule['start_am'].hour,
|
|
'hour_to': attendance_schedule['end_am'].hour,
|
|
'calendar_id': work_schedule_calendar.id,
|
|
},
|
|
])
|
|
|
|
# 2. Creating employees using those work schedules
|
|
employee_aramis, employee_athos, employee_porthos = self.env['hr.employee'].create([
|
|
{
|
|
'name': 'Aramis',
|
|
'resource_calendar_id': work_schedule_calendar.id,
|
|
},
|
|
{
|
|
'name': 'Athos',
|
|
'resource_calendar_id': work_schedule_calendar.id,
|
|
},
|
|
{
|
|
'name': 'Porthos',
|
|
'resource_calendar_id': work_schedule_calendar.id,
|
|
},
|
|
])
|
|
|
|
# 3. Creating shifts for those employees (in UTC)
|
|
days_to_wednesday = 2 - date.today().weekday() + 7 * (date.today().weekday() // 6)
|
|
start_date = date.today() + relativedelta(days=days_to_wednesday)
|
|
end_date = start_date + relativedelta(days=2)
|
|
start_date_normal = datetime.combine(start_date, attendance_schedule['start_am'])
|
|
start_date_late = datetime.combine(start_date, attendance_schedule['end_pm']) + relativedelta(hours=3)
|
|
end_date_normal = datetime.combine(end_date, attendance_schedule['end_pm'])
|
|
end_date_early = datetime.combine(end_date, attendance_schedule['start_am']) - relativedelta(hours=2)
|
|
|
|
self.env['planning.slot'].with_user(hugo).create([
|
|
{
|
|
'start_datetime': start_date_normal,
|
|
'end_datetime': end_date_normal,
|
|
'state': 'published',
|
|
'resource_id': employee_aramis.resource_id.id,
|
|
},
|
|
{
|
|
'start_datetime': start_date_late,
|
|
'end_datetime': end_date_early,
|
|
'state': 'published',
|
|
'resource_id': employee_athos.resource_id.id,
|
|
},
|
|
{
|
|
'start_datetime': start_date_normal,
|
|
'end_datetime': end_date_normal,
|
|
'state': 'published',
|
|
'resource_id': employee_porthos.resource_id.id,
|
|
'repeat': True,
|
|
'repeat_unit': 'week',
|
|
'repeat_interval': 1,
|
|
'repeat_type': 'x_times',
|
|
'repeat_number': 3,
|
|
},
|
|
])
|
|
# Initially 1 slot assigned to Aramis, 1 to Athos and 3 to Porthos
|
|
self.assertEqual(self.env['planning.slot'].search_count([('resource_id', '=', employee_aramis.resource_id.id)]), 1)
|
|
self.assertEqual(self.env['planning.slot'].search_count([('resource_id', '=', employee_athos.resource_id.id)]), 1)
|
|
self.assertEqual(self.env['planning.slot'].search_count([('resource_id', '=', employee_porthos.resource_id.id)]), 3)
|
|
|
|
# 4. Launching tour (Browser in UTC by default)
|
|
self.start_tour("/", 'planning_split_shift_week', login='hugo_user')
|
|
|
|
# 5. Verify the resulting slots after splitting
|
|
slots_aramis = self.env['planning.slot'].search_read([('resource_id', '=', employee_aramis.resource_id.id)],
|
|
fields=['start_datetime', 'end_datetime', 'allocated_hours'],
|
|
order='start_datetime ASC')
|
|
slots_athos = self.env['planning.slot'].search_read([('resource_id', '=', employee_athos.resource_id.id)],
|
|
fields=['start_datetime', 'end_datetime', 'allocated_hours'],
|
|
order='start_datetime ASC')
|
|
slots_porthos = self.env['planning.slot'].search_read([('resource_id', '=', employee_porthos.resource_id.id)],
|
|
fields=['start_datetime', 'end_datetime', 'allocated_hours'],
|
|
order='start_datetime ASC')
|
|
# After splitting: 2 slot assigned to Aramis, 3 to Athos and 4 to Porthos
|
|
self.assertEqual(len(slots_aramis), 2)
|
|
self.assertEqual(len(slots_athos), 3)
|
|
self.assertEqual(len(slots_porthos), 4, "Splitting a recurrent shift should only split one occurrence")
|
|
self.assertEqual([slots_aramis[0]['start_datetime'], slots_aramis[0]['end_datetime']], [start_date_normal, start_date_normal + relativedelta(hours=9)],
|
|
"When splitting a shift planned during resource's work schedule, resulting shifts should not start or end outside of this schedule.")
|
|
self.assertEqual([slots_aramis[1]['start_datetime'], slots_aramis[1]['end_datetime']], [start_date_normal + relativedelta(days=1), end_date_normal],
|
|
"When splitting a shift planned during resource's work schedule, resulting shifts should not start or end outside of this schedule.")
|
|
self.assertEqual([slots_athos[0]['start_datetime'], slots_athos[0]['end_datetime']], [start_date_late, start_date_late + relativedelta(seconds=1)],
|
|
"When splitting a shift starting after end of resource's work schedule at the end of the first day, first resulting shift should end one second after it starts.")
|
|
self.assertEqual([slots_athos[2]['start_datetime'], slots_athos[2]['end_datetime']], [end_date_early - relativedelta(seconds=1), end_date_early],
|
|
"When splitting a shift ending before the start of resource's work schedule at the end of the penultimate day, last resulting shift should start one second before it ends.")
|
|
self.assertEqual([slots_porthos[2]['start_datetime'], slots_porthos[2]['end_datetime']], [start_date_normal + relativedelta(weeks=1), end_date_normal + relativedelta(weeks=1)],
|
|
"Splitting a recurrent shift should only split one occurrence")
|