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

375 lines
21 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from freezegun import freeze_time
from odoo.fields import Command
from odoo.tests.common import users, tagged
from .gantt_reschedule_dates_common import ProjectEnterpriseGanttRescheduleCommon, fake_now
@tagged('gantt_reschedule')
@freeze_time(fake_now)
class TestGanttRescheduleOnTasks(ProjectEnterpriseGanttRescheduleCommon):
def test_gantt_reschedule_date_not_active(self):
""" This test purpose is to ensure that auto shift date feature is not active when it shouldn't:
* When the task has no project (either the moved task or the linked one (depend_on_ids or dependent_ids).
* When the calculated planned_start_date is prior to now.
"""
def test_task_3_dates_unchanged(task_1_new_planned_dates, failed_message, domain_force=False, **context):
task_1 = self.task_1.with_context(context) if domain_force else self.task_1.with_context(**context)
task_1.write(task_1_new_planned_dates)
self.gantt_reschedule_backward(self.task_1, self.task_3)
self.assertEqual(self.task_3_planned_date_begin, self.task_3.planned_date_begin, failed_message)
self.assertEqual(self.task_3_date_deadline, self.task_3.date_deadline, failed_message)
task_1.write({
'planned_date_begin': self.task_1_planned_date_begin,
'date_deadline': self.task_1_date_deadline,
})
self.task_4.depend_on_ids = [Command.clear()]
# Checks that no date shift is made when the moved task has no project_id
failed_message = "The auto shift date feature should not be triggered after having moved a task that " \
"does not have a project_id."
project_id = self.task_1.project_id
self.task_1.write({
'project_id': False
})
test_task_3_dates_unchanged(self.task_1_date_gantt_reschedule_trigger, failed_message)
self.task_1.write({
'project_id': project_id.id
})
# Checks that no date shift is made when the linked task has no project_id
failed_message = "The auto shift date feature should not be triggered on tasks (depend_on_ids/dependent_ids) " \
"that do have a project_id."
project_id = self.task_3.project_id
self.task_3.write({
'project_id': False
})
test_task_3_dates_unchanged(self.task_1_date_gantt_reschedule_trigger, failed_message)
self.task_3.write({
'project_id': project_id.id
})
# Checks that no date shift is made when the new planned_date is prior to the current datetime.
with freeze_time(self.task_1_no_date_gantt_reschedule_trigger['planned_date_begin'] + relativedelta(weeks=1)):
failed_message = "The auto shift date feature should not trigger any changes when the new planned_date " \
"is prior to the current datetime."
test_task_3_dates_unchanged(self.task_1_date_gantt_reschedule_trigger, failed_message)
def test_gantt_reschedule_dependent_task(self):
""" This test purpose is to ensure that a task B that depends on a task A is shifted forward, up to after
A date_deadline field value.
"""
self.task_1.write(self.task_1_date_gantt_reschedule_trigger)
self.gantt_reschedule_forward(self.task_1, self.task_3)
failed_message = "The auto shift date feature should move forward a dependent tasks."
self.assertTrue(self.task_1.date_deadline <= self.task_3.planned_date_begin, failed_message)
def test_gantt_reschedule_depend_on_task(self):
""" This test purpose is to ensure that a task A that depends on a task B is shifted backward, up to before
B planned_date_start field value.
"""
self.task_3.write(self.task_3_date_gantt_reschedule_trigger)
self.gantt_reschedule_backward(self.task_1, self.task_3)
failed_message = "The auto shift date feature should move backward a task the moved task depends on."
self.assertTrue(self.task_3.planned_date_begin >= self.task_1.date_deadline, failed_message)
@users('admin')
# @warmup
def test_gantt_reschedule_on_dependent_task_with_allocated_hours(self):
""" This test purpose is to ensure that the task planned_date_fields (begin/end) are calculated accordingly to
the allocated_hours if any. So if a dependent task has to be move forward up to before an unavailable period
of time and that its allocated_hours is such that the date_deadline would fall into that unavailable
period, then the date_deadline will be push forward after the unavailable period so that the
allocated_hours constraint is met.
"""
self.task_1.write({
'planned_date_begin': self.task_3_planned_date_begin,
'date_deadline': self.task_3_planned_date_begin + (self.task_1_date_deadline - self.task_1_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(20):
# self.env.invalidate_all()
self.gantt_reschedule_forward(self.task_1, self.task_3)
failed_message = ("The auto shift date feature should take the allocated_hours into account and update the"
"date_deadline accordingly when moving a task forward.")
self.assertEqual(
self.task_3.date_deadline, self.task_3_date_deadline + relativedelta(days=1, hour=9),
failed_message
)
@users('admin')
# @warmup
def test_gantt_reschedule_on_task_depending_on_with_allocated_hours(self):
""" This test purpose is to ensure that the task planned_date_fields (planned_date_begin/date_deadline) are calculated accordingly to
the allocated_hours if any. So if a task, that the current task depends on, has to be move backward up to
after an unavailable period of time and that its allocated_hours is such that the date_deadline would fall
into that unavailable period, then the planned_date_begin will be push backward before the unavailable
period so that the allocated_hours constraint is met.
"""
new_task_3_begin_date = self.task_1_date_deadline - timedelta(hours=2)
self.task_3.write({
'planned_date_begin': new_task_3_begin_date,
'date_deadline': new_task_3_begin_date + (self.task_3_date_deadline - self.task_3_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(38):
# self.env.invalidate_all()
self.gantt_reschedule_backward(self.task_1, self.task_3)
failed_message = ("The auto shift date feature should take the allocated_hours into account and update the"
"planned_date_begin accordingly when moving a task backward.")
self.assertEqual(self.task_1.planned_date_begin,
self.task_1_planned_date_begin + relativedelta(days=-1, hour=16), failed_message)
@users('admin')
# @warmup
def test_gantt_reschedule_on_dependent_task_without_allocated_hours(self):
""" This test purpose is to ensure that the interval made by the task planned_date_fields (begin/end) is
preserved when no allocated_hours is set.
"""
self.task_3.write({
'allocated_hours': 0,
})
self.task_1.write({
'planned_date_begin': self.task_3_planned_date_begin,
'date_deadline': self.task_3_planned_date_begin + (
self.task_1_date_deadline - self.task_1_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(38):
# self.env.invalidate_all()
self.gantt_reschedule_backward(self.task_1, self.task_3)
failed_message = "When allocated_hours=0, the auto shift date feature should preserve the time interval between" \
"planned_date_begin and date_deadline when moving a task forward."
self.assertEqual(self.task_3.date_deadline - self.task_3.planned_date_begin,
self.task_3_date_deadline - self.task_3_planned_date_begin, failed_message)
@users('admin')
# @warmup
def test_gantt_reschedule_on_task_depending_on_without_allocated_hours(self):
""" This test purpose is to ensure that the interval made by the task planned_date_fields (begin/end) is
preserved when no allocated_hours is set.
"""
new_task_3_begin_date = self.task_1_date_deadline - timedelta(hours=2)
self.task_1.write({
'allocated_hours': 0,
})
self.task_3.write({
'planned_date_begin': new_task_3_begin_date,
'date_deadline': new_task_3_begin_date + (self.task_3_date_deadline - self.task_3_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(20):
# self.env.invalidate_all()
self.gantt_reschedule_forward(self.task_1, self.task_3)
failed_message = "The auto shift date feature should take the allocated_hours into account and update the" \
"planned_date_begin accordingly when moving a task backward."
self.assertEqual(self.task_1.date_deadline - self.task_1.planned_date_begin,
self.task_1_date_deadline - self.task_1_planned_date_begin, failed_message)
@users('admin')
# @warmup
def test_gantt_reschedule_next_work_time_with_allocated_hours(self):
""" This test purpose is to ensure that computed dates are in accordance with the user resource_calendar
if any is set, or with the user company resource_calendar if not.
"""
new_task_1_planned_date_begin = self.task_3_planned_date_begin + timedelta(hours=1)
self.task_1.write({
'planned_date_begin': new_task_1_planned_date_begin,
'date_deadline': new_task_1_planned_date_begin + (
self.task_1_date_deadline - self.task_1_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(20):
# self.env.invalidate_all()
self.gantt_reschedule_forward(self.task_1, self.task_3)
failed_message = "The auto shift date feature should take the user company resource_calendar into account."
self.assertEqual(self.task_3.planned_date_begin,
self.task_3_planned_date_begin + relativedelta(days=1, hour=8), failed_message)
@users('admin')
# @warmup
def test_gantt_reschedule_previous_work_time_with_allocated_hours(self):
""" This test purpose is to ensure that computed dates are in accordance with the user resource_calendar
if any is set, or with the user company resource_calendar if not.
"""
new_task_3_begin_date = self.task_1_planned_date_begin - timedelta(hours=1)
self.task_3.write({
'planned_date_begin': new_task_3_begin_date,
'date_deadline': new_task_3_begin_date + (self.task_3_date_deadline - self.task_3_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(38):
# self.env.invalidate_all()
self.gantt_reschedule_backward(self.task_1, self.task_3)
failed_message = "The auto shift date feature should take the user company resource_calendar into account."
self.assertEqual(self.task_1.date_deadline,
self.task_1_date_deadline + relativedelta(days=-1, hour=17), failed_message)
@users('admin')
# @warmup
def test_gantt_reschedule_next_work_time_without_allocated_hours(self):
""" This test purpose is to ensure that computed dates are in accordance with the user resource_calendar
if any is set, or with the user company resource_calendar if not.
"""
new_task_1_planned_date_begin = self.task_3_planned_date_begin + timedelta(hours=1)
self.task_3.write({
'allocated_hours': 0,
})
self.task_1.write({
'planned_date_begin': new_task_1_planned_date_begin,
'date_deadline': new_task_1_planned_date_begin + (self.task_1_date_deadline - self.task_1_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(20):
# self.env.invalidate_all()
self.gantt_reschedule_forward(self.task_1, self.task_3)
failed_message = "The auto shift date feature should take the user company resource_calendar into account."
self.assertEqual(self.task_3.planned_date_begin,
self.task_3_planned_date_begin + relativedelta(days=1, hour=8), failed_message)
@users('admin')
# @warmup
def test_gantt_reschedule_previous_work_time_without_allocated_hours(self):
""" This test purpose is to ensure that computed dates are in accordance with the user resource_calendar
if any is set, or with the user company resource_calendar if not.
"""
new_task_3_begin_date = self.task_1_planned_date_begin - timedelta(hours=1)
self.task_1.write({
'allocated_hours': 0,
})
self.task_3.write({
'planned_date_begin': new_task_3_begin_date,
'date_deadline': new_task_3_begin_date + (self.task_3_date_deadline - self.task_3_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(38):
# self.env.invalidate_all()
self.gantt_reschedule_backward(self.task_1, self.task_3)
failed_message = "The auto shift date feature should take the user company resource_calendar into account."
self.assertEqual(self.task_1.date_deadline,
self.task_1_date_deadline + relativedelta(days=-1, hour=17), failed_message)
@users('admin')
# @warmup
def test_gantt_reschedule_next_work_time_long_leaves(self):
""" This test purpose is to ensure that computed dates are in accordance with the user resource_calendar
if any is set, or with the user company resource_calendar if not. This test is made on a long leave period
to ensure that it works when the new dates are further than the default fetched data. This test focuses on
ensuring that a task is pushed forward up to after the holiday leave period when a task that it depends on
is moved so that it creates an overlap between, the tasks.
"""
self.task_3.write({
'planned_date_begin': self.task_4_planned_date_begin,
'date_deadline': self.task_4_planned_date_begin + (self.task_3_date_deadline - self.task_3_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(37):
# self.env.invalidate_all()
self.gantt_reschedule_forward(self.task_3, self.task_4)
failed_message = "The auto shift date feature should take the user company resource_calendar into account and" \
"works also for long periods (requiring extending the search interval period)."
self.assertEqual(self.task_4.planned_date_begin,
self.task_4_planned_date_begin + relativedelta(month=8, day=2, hour=8), failed_message)
@users('admin')
# @warmup
def test_gantt_reschedule_previous_work_time_long_leaves(self):
""" This test purpose is to ensure that computed dates are in accordance with the user resource_calendar
if any is set, or with the user company resource_calendar if not. This test is made on a long leave period
to ensure that it works when the new dates are further than the default fetched data. This test focuses on
ensuring that a task is pushed backward up to before the holiday leave period when a dependent task is moved
so that it creates an overlap between the tasks.
"""
self.task_6.write({
'planned_date_begin': self.task_5_planned_date_begin,
'date_deadline': self.task_5_planned_date_begin + (
self.task_6_date_deadline - self.task_6_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(31):
# self.env.invalidate_all()
self.gantt_reschedule_backward(self.task_5, self.task_6)
failed_message = "The auto shift date feature should take the user company resource_calendar into account and" \
"works also for long periods (requiring extending the search interval period)."
self.assertEqual(self.task_5.date_deadline,
self.task_5_date_deadline + relativedelta(month=6, day=30, hour=17), failed_message)
@users('admin')
# @warmup
def test_gantt_reschedule_cascading_forward(self):
""" This test purpose is to ensure that the cascade is well supported on dependent tasks
(task A move impacts B that moves forwards and then impacts C that is moved forward).
"""
new_task_3_planned_date_begin = self.task_4_planned_date_begin - timedelta(hours=1)
self.task_3.write({
'planned_date_begin': new_task_3_planned_date_begin,
'date_deadline': new_task_3_planned_date_begin + (self.task_3_date_deadline - self.task_3_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(43):
# self.env.invalidate_all()
self.gantt_reschedule_forward(self.task_3, self.task_4)
failed_message = "The auto shift date feature should handle correctly dependencies cascades."
self.assertEqual(self.task_4.planned_date_begin,
self.task_3.date_deadline, failed_message)
self.assertEqual(self.task_4.date_deadline,
self.task_4_planned_date_begin + relativedelta(month=8, day=2, hour=9), failed_message)
self.assertEqual(self.task_5.planned_date_begin,
self.task_4.date_deadline, failed_message)
self.assertEqual(self.task_5.date_deadline,
self.task_5_date_deadline + relativedelta(days=1, hour=9), failed_message)
@users('admin')
# @warmup
def test_gantt_reschedule_cascading_backward(self):
""" This test purpose is to ensure that the cascade is well supported on tasks that the current task depends on
(task A move impacts B that moves backward and then impacts C that is moved backward).
"""
new_task_6_planned_date_begin = self.task_5_planned_date_begin + timedelta(hours=1)
self.task_6.write({
'planned_date_begin': new_task_6_planned_date_begin,
'date_deadline': new_task_6_planned_date_begin + (self.task_6_date_deadline - self.task_6_planned_date_begin),
})
# FIXME as indeterminately fails. Suspected indeterminate cache invalidation.
# with self.assertQueryCount(35):
# self.env.invalidate_all()
self.gantt_reschedule_backward(self.task_5, self.task_6)
failed_message = "The auto shift date feature should handle correctly dependencies cascades."
self.assertEqual(self.task_5.date_deadline,
new_task_6_planned_date_begin, failed_message)
self.assertEqual(self.task_5.planned_date_begin,
datetime(year=2021, month=6, day=29, hour=9), failed_message)
self.assertEqual(self.task_4.date_deadline,
self.task_5.planned_date_begin, failed_message)
self.assertEqual(self.task_4.planned_date_begin,
datetime(year=2021, month=6, day=28, hour=16), failed_message)
def test_gantt_reschedule_project_user(self):
""" This test purpose is to ensure that the project user has the sufficient rights to trigger a gantt
reschedule.
"""
new_task_6_planned_date_begin = self.task_5_planned_date_begin + timedelta(hours=1)
self.task_6.with_user(self.user_projectuser).write({
'planned_date_begin': new_task_6_planned_date_begin,
'date_deadline': new_task_6_planned_date_begin + (self.task_6_date_deadline - self.task_6_planned_date_begin),
})
self.gantt_reschedule_backward(self.task_5, self.task_6)
failed_message = "The auto shift date feature should handle correctly dependencies cascades."
self.assertEqual(self.task_5.date_deadline,
new_task_6_planned_date_begin, failed_message)
self.assertEqual(self.task_5.planned_date_begin,
datetime(year=2021, month=6, day=29, hour=9), failed_message)
self.assertEqual(self.task_4.date_deadline,
self.task_5.planned_date_begin, failed_message)
self.assertEqual(self.task_4.planned_date_begin,
datetime(year=2021, month=6, day=28, hour=16), failed_message)