[IMP] *_timesheet: don't modify past timesheet when transfering task
Impacted modules: hr_timesheet, sale_timesheet When task is changing project or sale order line, we don't want anymore to change the linked timesheet. We now consider a timesheet is done in a specific time at certain condition that does not have to change when the environment is modified afterwards. So, a timesheet linked to an analytic account for a certain project on a task (and mybe linked to a SO line) will still be linked to the same object if the task is billed with another SO or move into a new project. The idea is task actual configuration (project, AA, SO line) are the default value at timesheet creation. As consequences, timesheet from another project can be linked to a task that does not belong to that project. Project and task can be modified thougth the UI of timesheet app. SO line and analytic account of a timesheet can not be modified as they are more sensitive field (in a business point of view), especially for invoiced timesheets. This commit revert opw-1803811, as at that time the 'inheritS' between project and AA was still effective, and there was only one billable type (task rate) for task. The introduction of 'employee rate' billing type will complicate timesheet transfert. Tasks #34703
This commit is contained in:
@@ -135,22 +135,16 @@ class Task(models.Model):
|
||||
for task in self:
|
||||
task.subtask_effective_hours = sum(child_task.effective_hours + child_task.subtask_effective_hours for child_task in task.child_ids)
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# ORM
|
||||
# ---------------------------------------------------------
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
result = super(Task, self).write(values)
|
||||
# reassign project_id on related timesheet lines
|
||||
if 'project_id' in values:
|
||||
project_id = values.get('project_id')
|
||||
# a timesheet must have an analytic account (and a project)
|
||||
if self and not project_id:
|
||||
# a timesheet must have an analytic account (and a project)
|
||||
if 'project_id' in values and self and not values.get('project_id'):
|
||||
raise UserError(_('This task must be part of a project because they some timesheets are linked to it.'))
|
||||
account_id = self.env['project.project'].browse(project_id).sudo().analytic_account_id
|
||||
self.sudo().mapped('timesheet_ids').write({
|
||||
'project_id': project_id,
|
||||
'account_id': account_id.id,
|
||||
'company_id': account_id.company_id.id,
|
||||
})
|
||||
return result
|
||||
return super(Task, self).write(values)
|
||||
|
||||
@api.model
|
||||
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
|
||||
|
||||
@@ -146,7 +146,7 @@ class TestTimesheet(TestCommonTimesheet):
|
||||
self.assertEquals(timesheet1.user_id, self.user_employee2, 'Changing timesheet employee should change the related user')
|
||||
|
||||
def test_transfert_project(self):
|
||||
""" Test transfert task with timesheet to another project """
|
||||
""" Transfert task with timesheet to another project should not modified past timesheets (they are still linked to old project. """
|
||||
Timesheet = self.env['account.analytic.line']
|
||||
# create a second project
|
||||
self.project_customer2 = self.env['project.project'].create({
|
||||
@@ -174,9 +174,9 @@ class TestTimesheet(TestCommonTimesheet):
|
||||
|
||||
timesheet_count1 = Timesheet.search_count([('project_id', '=', self.project_customer.id)])
|
||||
timesheet_count2 = Timesheet.search_count([('project_id', '=', self.project_customer2.id)])
|
||||
self.assertEquals(timesheet_count1, 0, "No timesheet in project 1")
|
||||
self.assertEquals(timesheet_count2, 1, "One timesheet in project 2")
|
||||
self.assertEquals(len(self.task1.timesheet_ids), 1, "The timesheet should be linked to task 1")
|
||||
self.assertEquals(timesheet_count1, 1, "Still one timesheet in project 1")
|
||||
self.assertEquals(timesheet_count2, 0, "No timesheet in project 2")
|
||||
self.assertEquals(len(self.task1.timesheet_ids), 1, "The timesheet still should be linked to task 1")
|
||||
|
||||
# it is forbidden to set a task with timesheet without project
|
||||
with self.assertRaises(UserError):
|
||||
|
||||
@@ -92,16 +92,6 @@ class ProjectTask(models.Model):
|
||||
if not task.sale_line_id.is_service or task.sale_line_id.is_expense:
|
||||
raise ValidationError(_('You cannot link the order item %s - %s to this task because it is a re-invoiced expense.' % (task.sale_line_id.order_id.id, task.sale_line_id.product_id.name)))
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
result = super(ProjectTask, self).write(values)
|
||||
# reassign SO line on related timesheet lines
|
||||
if 'sale_line_id' in values:
|
||||
self.sudo().mapped('timesheet_ids').write({
|
||||
'so_line': values['sale_line_id']
|
||||
})
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
if any(task.sale_line_id for task in self):
|
||||
|
||||
@@ -160,11 +160,8 @@ class TestSaleService(TestCommonSaleTimesheetNoChart):
|
||||
|
||||
# make task non billable
|
||||
task_serv2.write({'sale_line_id': False})
|
||||
self.assertTrue(all([billing_type == 'non_billable' for billing_type in timesheets.mapped('timesheet_invoice_type')]), "Timesheet to a non billable task should be non billable too")
|
||||
|
||||
# make task billable again
|
||||
task_serv2.write({'sale_line_id': so_line_deliver_global_project.id})
|
||||
self.assertTrue(all([billing_type == 'billable_time' for billing_type in timesheets.mapped('timesheet_invoice_type')]), "Timesheet to a billable time task should be billable")
|
||||
self.assertTrue(all([billing_type == 'billable_time' for billing_type in timesheets.mapped('timesheet_invoice_type')]), "billable type of timesheet should not change when tranfering task into another project")
|
||||
self.assertEqual(task_serv2.timesheet_ids.mapped('so_line'), so_line_deliver_global_project, "Old timesheet are not modified when changing the task SO line")
|
||||
|
||||
# invoice SO, and validate invoice
|
||||
invoice_id = self.sale_order.action_invoice_create()[0]
|
||||
@@ -173,7 +170,7 @@ class TestSaleService(TestCommonSaleTimesheetNoChart):
|
||||
|
||||
# try to update timesheets, catch error 'You cannot modify invoiced timesheet'
|
||||
with self.assertRaises(UserError):
|
||||
task_serv2.write({'sale_line_id': False})
|
||||
timesheets.write({'so_line': False})
|
||||
|
||||
def test_delivered_quantity(self):
|
||||
# create SO line and confirm it
|
||||
|
||||
Reference in New Issue
Block a user