1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/appointment/tests/test_appointment_gantt.py
2024-12-10 09:04:09 +07:00

266 lines
12 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime, timedelta
import pytz
from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.addons.resource.models.utils import Intervals
from odoo.tests import users
from .common import AppointmentCommon
class AppointmentGanttTestCommon(AppointmentCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.partners = cls.env['res.partner'].create([{
'name': 'gantt attendee 1'
}, {
'name': 'gantt attendee 2'
}])
# create some appointments and users to ensure they are not linked to anything else
[cls.user_bob, cls.user_john] = [mail_new_test_user(
cls.env,
company_id=cls.company_admin.id,
email='bob@aptgantt.lan',
groups='base.group_user',
name='bob',
login='bob@aptgantt.lan',
), mail_new_test_user(
cls.env,
company_id=cls.company_admin.id,
email='john@aptgantt.lan',
groups='base.group_user',
name='john',
login='john@aptgantt.lan',
)]
cls.apt_users = cls.user_bob + cls.user_john
cls.apt_resource_calendar = cls.env['resource.calendar'].create([{
'name': 'Gantt Test Apt Resource Calendar',
'company_id': False,
'hours_per_day': 24,
'attendance_ids': [
(0, 0, {
'name': f'{nday} Morning',
'dayofweek': str(nday),
'hour_from': 0,
'hour_to': 12,
'day_period': 'morning',
}) for nday in range(6)] + [
(0, 0, {
'name': f'{nday} Afternoon',
'dayofweek': str(nday),
'hour_from': 12,
'hour_to': 24,
'day_period': 'afternoon',
}) for nday in range(6)]
}])
cls.apt_resource_1, cls.apt_resource_2 = cls.env['appointment.resource'].create([{
'capacity': 1,
'name': 'Resource 1',
'resource_calendar_id': cls.apt_resource_calendar.id,
}, {
'capacity': 2,
'name': 'Resource 2',
'resource_calendar_id': cls.apt_resource_calendar.id,
}])
cls.apt_types = cls.env['appointment.type'].create([{
'appointment_tz': 'UTC',
'name': 'bob apt type',
'staff_user_ids': [(4, cls.user_bob.id)],
}, {
'appointment_tz': 'UTC',
'name': 'nouser apt type',
'staff_user_ids': [],
}, {
'appointment_tz': 'UTC',
'name': 'resource apt type',
'resource_ids': [(4, cls.apt_resource_1.id), (4, cls.apt_resource_2.id)],
'schedule_based_on': 'resources',
'resource_manage_capacity': True,
}])
cls.resource_apt_types = cls.apt_types[2]
cls.gantt_context = {'appointment_booking_gantt_show_all_resources': True}
cls.gantt_domain = [('appointment_type_id', 'in', cls.apt_types.ids)]
class AppointmentGanttTest(AppointmentGanttTestCommon):
@users('apt_manager')
def test_default_assign_user_attendees(self):
"""
1> To check, Single attendee should be set as an organizer by default.
(This is typically applied when selecting a specific slot in the
appointment kanban.)
2> (special gantt case) The current user should be an attendee if
he is set as the organizer.
"""
# context while clicking the 'New' btn
no_attendees_context = {
'booking_gantt_create_record': True,
'appointment_default_assign_user_attendees': True,
'default_partner_ids': [],
}
# context while clicking the time slot of the staff user
single_attendee_context = {
**no_attendees_context,
'default_partner_ids': [self.user_bob.partner_id.id],
}
# Case 1: Specify a single attendee, simulating clicking a slot on the gantt view
event_with_partner = self.env['calendar.event'].with_context(single_attendee_context).create({
'name': 'event with partner',
'appointment_type_id': self.apt_types[0].id,
})
# Case 2: Create an appointment without specifying attendees
event_without_partner = self.env['calendar.event'].with_context(no_attendees_context).create({
'name': 'event without partner',
'appointment_type_id': self.apt_types[0].id,
})
# Case 1 check
self.assertEqual(
event_with_partner.user_id,
self.user_bob,
"Single attendee should be set as an organizer by default",
)
# Case 2 check
self.assertEqual(
event_without_partner.user_id,
self.apt_manager,
"The current user should be an organizer",
)
self.assertEqual(
event_without_partner.attendee_ids.partner_id,
self.apt_manager.partner_id,
"If we don't specify an attendee, the current user should be set as an attendee",
)
def test_gantt_empty_groups(self):
"""Check that the data sent to gantt includes the right groups in the context of appointments."""
gantt_data = self.env['calendar.event'].with_context(self.gantt_context).get_gantt_data(
self.gantt_domain, ['partner_ids'], {}
)
group_partner_ids = [group['partner_ids'][0] for group in gantt_data['groups']]
self.assertIn(self.user_bob.partner_id.id, group_partner_ids,
'Staff assigned to a user-scheduled appointment type should be shown in the default groups')
self.assertNotIn(self.user_john.partner_id.id, group_partner_ids,
'Staff not assigned to any appointment type should be hidden')
# add john as a staff user of an appointment type -> in the default groups
self.apt_types[1].staff_user_ids = self.user_john
gantt_data = self.env['calendar.event'].with_context(self.gantt_context).get_gantt_data(
self.gantt_domain, ['partner_ids'], {}
)
group_partner_ids = [group['partner_ids'][0] for group in gantt_data['groups']]
self.assertIn(self.user_bob.partner_id.id, group_partner_ids)
self.assertIn(self.user_john.partner_id.id, group_partner_ids)
# have default appointment in context -> only show staff assigned to that type
context = self.gantt_context | {'default_appointment_type_id': self.apt_types[0].id}
gantt_data = self.env['calendar.event'].with_context(context).get_gantt_data(
self.gantt_domain, ['partner_ids'], {}
)
group_partner_ids = [group['partner_ids'][0] for group in gantt_data['groups']]
self.assertIn(self.user_bob.partner_id.id, group_partner_ids)
self.assertNotIn(self.user_john.partner_id.id, group_partner_ids, 'Should only display staff assigned to the default apt type.')
def test_gantt_hide_non_staff(self):
"""Check that only the attendees that are part of the staff are used to compute the gantt data.
The other attendees, such as the website visitors that created the meeting,
are excluded and should not be displayed as gantt rows.
"""
meeting = self._create_meetings(
self.apt_users[0],
[(self.reference_monday, self.reference_monday + timedelta(hours=1), False)],
self.apt_types[0].id
)
meeting.partner_ids += self.partners[0]
gantt_data = self.env['calendar.event'].with_context(self.gantt_context).get_gantt_data(
self.gantt_domain, ['partner_ids'], {}
)
group_partner_ids = [group['partner_ids'][0] for group in gantt_data['groups']]
self.assertNotIn(self.partners[0].id, group_partner_ids, 'Attendees with no users should be hidden from the grouping.')
self.assertIn(self.user_bob.partner_id.id, group_partner_ids)
self.assertNotIn(self.user_john.partner_id.id, group_partner_ids)
self.assertEqual(gantt_data['records'], [{'id': meeting.id}])
@users('staff_user_bxls')
def test_gantt_resource_unavailabilities_multi_company(self):
"""Check that resources outside of allowed companies don't get calendar unavailabilities."""
company_a = self.env.company
company_b = self.env['res.company'].sudo().create({
'name': 'Gantt Test Company B',
})
self.env.user.sudo().company_ids += company_a + company_b
resource_calendar_unavailabilities = Intervals([
(datetime(2022, 2, 14, 11, 00, tzinfo=pytz.UTC), datetime(2022, 2, 14, 11, 0, tzinfo=pytz.UTC), set()),
])
for allowed_company_ids, res_1_company, res_2_company, res_1_unavailabilities, res_2_unavailabilities in [
([], False, False, resource_calendar_unavailabilities, resource_calendar_unavailabilities),
([], False, company_a, resource_calendar_unavailabilities, resource_calendar_unavailabilities),
(company_a.ids, False, company_a, resource_calendar_unavailabilities, resource_calendar_unavailabilities),
(company_b.ids, company_a, company_a, [], []),
(company_b.ids, company_a, company_b, [], resource_calendar_unavailabilities),
([company_a.id, company_b.id], company_a, company_b, resource_calendar_unavailabilities, resource_calendar_unavailabilities),
]:
with self.subTest(
allowed_company_ids=allowed_company_ids,
resource_1_company=res_1_company,
resource_2_company=res_2_company,
):
self.apt_resource_1.sudo().company_id = res_1_company
self.apt_resource_2.sudo().company_id = res_2_company
unavailabilities = self.env['calendar.event'].with_context(self.gantt_context | {
'allowed_company_ids': allowed_company_ids
}).gantt_unavailability(
self.reference_monday.replace(hour=0),
self.reference_monday.replace(hour=23),
'day',
group_bys=['resource_ids'],
rows=[{
'groupedBy': ['resource_ids'],
'resId': self.apt_resource_1.id,
'rows': [],
}, {
'groupedBy': ['resource_ids'],
'resId': self.apt_resource_2.id,
'rows': [],
}]
)
self.assertListEqual(
list(Intervals([(unavailability['start'], unavailability['stop'], set())
for unavailability in unavailabilities[0]['unavailabilities']])),
list(res_1_unavailabilities)
)
self.assertListEqual(
list(Intervals([(unavailability['start'], unavailability['stop'], set())
for unavailability in unavailabilities[1]['unavailabilities']])),
list(res_2_unavailabilities)
)
def test_gantt_without_attendees(self):
meeting = self._create_meetings(
self.user_john[0],
[(self.reference_monday, self.reference_monday + timedelta(hours=1), False)],
self.apt_types[0].id
)
meeting.partner_ids = False
gantt_data = self.env['calendar.event'].with_context(self.gantt_context).get_gantt_data(
self.gantt_domain, ['partner_ids'], {}
)
group_partner_ids = [group['partner_ids'][0] for group in gantt_data['groups']]
self.assertIn(self.user_bob.partner_id.id, group_partner_ids)
self.assertNotIn(self.user_john.partner_id.id, group_partner_ids)
self.assertEqual(gantt_data['records'], [{'id': meeting.id}])