Files
enterprise-addons/timesheet_grid/tests/test_timesheet_timer.py
T

192 lines
11 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime
from dateutil.relativedelta import relativedelta
from freezegun import freeze_time
from odoo import fields
from odoo.tests import tagged
from odoo.addons.hr_timesheet.tests.test_timesheet import TestCommonTimesheet
@tagged('-at_install', 'post_install')
class TestTimesheetTimer(TestCommonTimesheet):
def test_start_timer_in_timesheet(self):
timesheet_without_task, timesheet = self.env['account.analytic.line'].with_user(self.user_employee).create([
{'name': '/', 'project_id': self.project_customer.id, 'employee_id': self.empl_employee.id},
{'name': '/', 'project_id': self.project_customer.id, 'task_id': self.task1.id, 'employee_id': self.empl_employee.id},
])
timesheet_without_task.action_timer_start()
timer = timesheet_without_task.user_timer_id
self.assertTrue(timer, 'A timer should created for this timesheet.')
self.assertEqual(timer.res_id, timesheet_without_task.id, 'The document linked to this timer should be the timesheet in which the user starts the timer.')
self.assertEqual(timer.res_model, timesheet_without_task._name, 'The document model should be the one of the timesheet in which the timer is launched.')
self.assertFalse(timer.parent_res_model, 'No Parent Document Model should be found since no task is linked to the timesheet in which the timer is launched.')
self.assertFalse(timer.parent_res_id, 'No Parent Document should be found since no task is linked to the timesheet in which the timer is launched.')
timesheet.action_timer_start()
self.assertFalse(timesheet_without_task.user_timer_id, 'The previous timer should be stopped and removed since another timer will be created and launched.')
timer = timesheet.user_timer_id
self.assertTrue(timer, 'A timer should created for this timesheet.')
self.assertEqual(timer.res_id, timesheet.id, 'The document linked to this timer should be the timesheet in which the user starts the timer.')
self.assertEqual(timer.res_model, timesheet._name, 'The document model should be the one of the timesheet in which the timer is launched.')
self.assertEqual(timer.parent_res_model, 'project.task', 'The parent document model should be the `project.task` model.')
self.assertEqual(timer.parent_res_id, self.task1.id, 'The parent document should be the task linked to the timesheet in which the timer is launched.')
def test_timer_in_task(self):
""" Test the timer on a task """
task = self.task1.with_user(self.user_employee)
self.assertTrue(task.display_timesheet_timer, 'The timer should be available in that task.')
task.action_timer_start()
self.assertTrue(task.is_timer_running, 'The timer should be running and so the stop button appears on the task')
action = task.action_timer_stop()
self.assertEqual(action['res_model'], 'hr.timesheet.stop.timer.confirmation.wizard')
wizard = self.env['hr.timesheet.stop.timer.confirmation.wizard'] \
.with_context(action['context']) \
.with_user(self.user_employee) \
.new({})
wizard.action_save_timesheet()
self.assertFalse(task.timer_start, 'The stop button on the task is invisible')
self.assertFalse(task.is_timer_running, 'The timer should be removed and so it is obviously no longer running.')
def test_timer_sync_timesheet_to_task(self):
""" Test sync between timesheet and task """
timesheet = self.env['account.analytic.line'].with_user(self.user_employee).create({
'name': "my timesheet 1",
'project_id': self.project_customer.id,
'task_id': self.task1.id,
'date': fields.Date.today(),
'unit_amount': 2.0,
'employee_id': self.empl_employee.id,
})
# Start the timer on timesheet
timesheet.action_timer_start()
self.assertTrue(timesheet.is_timer_running, 'Timer should be started on timesheet')
# Stop the timer from the task through the wizard
task = self.task1.with_user(self.user_employee)
self.assertTrue(task.user_timer_id, 'The timer in the task should be the one of the timesheet.')
action = task.action_timer_stop()
self.assertEqual(action['res_model'], 'hr.timesheet.stop.timer.confirmation.wizard')
wizard = self.env['hr.timesheet.stop.timer.confirmation.wizard'] \
.with_context(action['context']) \
.with_user(self.user_employee) \
.new({})
wizard.action_save_timesheet()
self.assertFalse(timesheet.is_timer_running, 'Timer should be stoped on Timesheet')
def test_timer_sync_task_to_timesheet(self):
""" Start the timer from the task and stop the timer from the timesheet """
# start timer from the task
task = self.task1.with_user(self.user_employee)
with freeze_time(datetime.now() - relativedelta(minutes=1)):
task.action_timer_start()
self.assertTrue(bool(task.user_timer_id), 'A timer should be generated in the task.')
timesheet = task.user_timer_id._get_related_document()
self.assertIn(timesheet, task.timesheet_ids, 'A timesheet should be generated in the task in which the timer is started.')
# stop timer from the timesheet
timesheet.with_user(self.user_employee).action_timer_stop(True)
self.assertFalse(task.user_timer_id, 'Timer should be stopped on ticket')
self.assertGreater(timesheet.unit_amount, 0.0, 'unit_amount should be greated than his last value')
def test_switch_timer_task(self):
"""
Stop the running timer and log the timesheet entry on task when same user start the timer on another task
"""
task1 = self.task1.copy()
task2 = self.task1.copy()
# Start the timer on task1
with freeze_time(datetime.now() - relativedelta(minutes=1)):
task1.with_user(self.user_employee).action_timer_start()
# Start the timer on task2
task2.with_user(self.user_employee).action_timer_start()
self.assertFalse(task1.timer_start, 'Timer should be stoped on task1')
self.assertEqual(len(task1.timesheet_ids), 1, 'Timesheet entry should be logged to the task1')
self.assertEqual(len(task2.timesheet_ids), 1, 'Timesheet entry should be logged to the task2')
def test_update_timesheet(self):
""" Test if when the task is updated on the timesheet, the timer is also updated """
timesheet = self.env['account.analytic.line'].with_user(self.user_employee).create({'name': '/', 'project_id': self.project_customer.id})
timesheet.action_timer_start()
timer = timesheet.user_timer_id
self.assertTrue(bool(timer))
self.assertFalse(timer.parent_res_model)
self.assertFalse(timer.parent_res_id)
timesheet.write({'task_id': self.task1.id})
self.assertEqual(timer.parent_res_model, 'project.task')
self.assertEqual(timer.parent_res_id, self.task1.id)
def test_update_project_on_task_linked_to_timesheet_with_timer_running(self):
""" Test if when the project is updated on the task linked to the timesheet with timer running, the timer is also updated """
timesheet = self.env['account.analytic.line'] \
.with_user(self.user_employee) \
.create({
'name': '/',
'project_id': self.project_customer.id,
'task_id': self.task1.id,
})
timesheet.action_timer_start()
timer = timesheet.user_timer_id
self.assertTrue(bool(timer))
self.assertEqual(timer.res_id, timesheet.id)
self.assertEqual(timer.res_model, timesheet._name)
self.assertEqual(timer.parent_res_model, 'project.task')
self.assertEqual(timer.parent_res_id, self.task1.id)
timesheet_project, non_timesheetable_project = self.env['project.project'].create([
{'name': 'Timesheet Project', 'allow_timesheets': True},
{'name': 'Non Timesheet Project', 'allow_timesheets': False},
])
self.task1.write({'project_id': timesheet_project.id})
self.assertTrue(self.task1.with_user(self.user_employee).is_timer_running)
self.assertEqual(timer.parent_res_model, 'project.task')
self.assertEqual(timer.parent_res_id, self.task1.id)
self.task1.write({'project_id': non_timesheetable_project.id})
self.task1.invalidate_recordset()
self.assertFalse(self.task1.with_user(self.user_employee).is_timer_running)
self.assertFalse(timesheet.exists(), 'The timesheet should be removed since the timesheet has unit amount equals to 0.')
def test_multi_company_start_timer(self):
company = self.env['res.company'].create({'name': 'Company Test'})
project = self.env['project.project'].create({
'name': 'Test Project in Company Test',
'allow_timesheets': True,
})
task = self.env['project.task'].create({
'name': 'Test Task in Company Test',
'project_id': project.id,
'company_id': company.id,
}).with_user(self.user_employee)
self.assertFalse(self.task1.timesheet_ids)
task1 = self.task1.with_user(self.user_employee)
task1.action_timer_start()
timer = task1.user_timer_id
self.assertTrue(bool(timer))
self.assertEqual(timer.parent_res_model, 'project.task')
self.assertEqual(timer.parent_res_id, task1.id)
timesheet_with_timer_running = self.env[timer.res_model].browse(timer.res_id)
self.assertTrue(timesheet_with_timer_running, 'A timer should generate a timesheet')
self.assertEqual(timesheet_with_timer_running.task_id, task1, 'The timesheet generated by the timer should be linked to the task1.')
self.user_employee.company_ids += company
self.env['hr.employee'].create({
'name': 'Employee Test Company',
'user_id': self.user_employee.id,
'company_id': company.id,
})
task.with_company(company).action_timer_start()
timer = task.user_timer_id
self.assertTrue(bool(timer))
self.assertEqual(timer.parent_res_model, 'project.task')
self.assertEqual(timer.parent_res_id, task.id)
self.assertFalse(task1.user_timer_id, 'The previous timer should be stopped since another timer is started.')
self.assertTrue(timesheet_with_timer_running, 'A timesheet should still be there even if the timer is stopped.')
self.assertFalse(timesheet_with_timer_running.with_user(self.user_employee).user_timer_id)