Skip to content
Snippets Groups Projects
Commit ccf6973b authored by Pierrot (prro)'s avatar Pierrot (prro)
Browse files

[FIX] [hr,sale]_timesheet: update timesheet's partner from Task


How to reproduce the problem:
- Install hr_timesheet and create a project.
- Create a task in the project, and assign a Partner as the Customer
- In the Timesheet tab of the Task, add a new entry. Save the Task.
- Edit the task again and change the Customer. Save again.
-> the partner on the Timesheet entry did not change.

With sale_timesheet, the Sales Order Item of the timesheet entry can
be updated from the Sales Order Item of the Task, but it isn't the case
with the partner, which is not logical.

Solution : Now, the partner_id is computed and will automatically be
updated from the Task's Customer/partner_id. If sale_timesheet is
installed, it will first filter out the invoiced timesheet entry:
we don't want to change an already invoiced entry.

opw-2616784

closes odoo/odoo#78577

Signed-off-by: default avatarLTU-Odoo <IT-Ideas@users.noreply.github.com>
parent f34e4415
No related branches found
No related tags found
No related merge requests found
......@@ -48,11 +48,18 @@ class AccountAnalyticLine(models.Model):
employee_id = fields.Many2one('hr.employee', "Employee", domain=_domain_employee_id)
department_id = fields.Many2one('hr.department', "Department", compute='_compute_department_id', store=True, compute_sudo=True)
encoding_uom_id = fields.Many2one('uom.uom', compute='_compute_encoding_uom_id')
partner_id = fields.Many2one(compute='_compute_partner_id', store=True, readonly=False)
def _compute_encoding_uom_id(self):
for analytic_line in self:
analytic_line.encoding_uom_id = analytic_line.company_id.timesheet_encode_uom_id
@api.depends('task_id.partner_id', 'project_id.partner_id')
def _compute_partner_id(self):
for timesheet in self:
if timesheet.project_id:
timesheet.partner_id = timesheet.task_id.partner_id or timesheet.project_id.partner_id
@api.depends('task_id', 'task_id.project_id')
def _compute_project_id(self):
for line in self.filtered(lambda line: not line.project_id):
......
......@@ -3,6 +3,7 @@
from odoo.tests.common import TransactionCase
from odoo.exceptions import AccessError, UserError
from odoo.tests import tagged
class TestCommonTimesheet(TransactionCase):
......@@ -83,6 +84,7 @@ class TestCommonTimesheet(TransactionCase):
'user_id': self.user_manager.id,
})
@tagged('-at_install', 'post_install')
class TestTimesheet(TestCommonTimesheet):
def setUp(self):
......@@ -284,3 +286,23 @@ class TestTimesheet(TestCommonTimesheet):
}, {
'amount': -12.0,
}])
def test_recompute_partner_from_task_customer_change(self):
partner2 = self.env['res.partner'].create({
'name': 'Customer Task 2',
'email': 'customer2@task.com',
'phone': '43',
})
timesheet_entry = self.env['account.analytic.line'].create({
'project_id': self.project_customer.id,
'task_id': self.task1.id,
'name': 'my only timesheet',
'unit_amount': 4,
})
self.assertEqual(timesheet_entry.partner_id, self.partner, "The timesheet entry's partner should be equal to the task's partner/customer")
self.task1.write({'partner_id': partner2})
self.assertEqual(timesheet_entry.partner_id, partner2, "The timesheet entry's partner should still be equal to the task's partner/customer, after the change")
......@@ -61,6 +61,10 @@ class AccountAnalyticLine(models.Model):
def _compute_so_line(self):
for timesheet in self._get_not_billed(): # Get only the timesheets are not yet invoiced
timesheet.so_line = timesheet.project_id.allow_billable and timesheet._timesheet_determine_sale_line(timesheet.task_id, timesheet.employee_id, timesheet.project_id)
@api.depends('timesheet_invoice_id.state')
def _compute_partner_id(self):
super(AccountAnalyticLine, self._get_not_billed())._compute_partner_id()
def _get_not_billed(self):
return self.filtered(lambda t: not t.timesheet_invoice_id or t.timesheet_invoice_id.state == 'cancel')
......
......@@ -599,3 +599,75 @@ class TestSaleTimesheet(TestCommonSaleTimesheet):
self.assertEqual(timesheet_count1, 1, "One timesheet in project_global")
self.assertEqual(timesheet_count2, 1, "Still one timesheet in project_template")
self.assertEqual(len(task.timesheet_ids), 2, "The 2 timesheet still should be linked to task")
def test_change_customer_and_SOL_after_invoiced_timesheet(self):
sale_order1 = self.env['sale.order'].create({
'partner_id': self.partner_a.id,
'partner_invoice_id': self.partner_a.id,
'partner_shipping_id': self.partner_a.id,
'pricelist_id': self.company_data['default_pricelist'].id,
})
sale_order2 = self.env['sale.order'].create({
'partner_id': self.partner_b.id,
'partner_invoice_id': self.partner_b.id,
'partner_shipping_id': self.partner_b.id,
'pricelist_id': self.company_data['default_pricelist'].id,
})
so1_product_global_project_so_line = self.env['sale.order.line'].create({
'name': self.product_delivery_timesheet2.name,
'product_id': self.product_delivery_timesheet2.id,
'product_uom_qty': 50,
'product_uom': self.product_delivery_timesheet2.uom_id.id,
'price_unit': self.product_delivery_timesheet2.list_price,
'order_id': sale_order1.id,
})
so2_product_global_project_so_line = self.env['sale.order.line'].create({
'name': self.product_delivery_timesheet2.name,
'product_id': self.product_delivery_timesheet2.id,
'product_uom_qty': 20,
'product_uom': self.product_delivery_timesheet2.uom_id.id,
'price_unit': self.product_delivery_timesheet2.list_price,
'order_id': sale_order2.id,
})
sale_order1.action_confirm()
sale_order2.action_confirm()
task_so1 = self.env['project.task'].search([('sale_line_id', '=', so1_product_global_project_so_line.id)])
task_so2 = self.env['project.task'].search([('sale_line_id', '=', so2_product_global_project_so_line.id)])
self.assertEqual(self.partner_a, task_so1.partner_id, "The Customer of the first task should be equal to partner_a.")
self.assertEqual(self.partner_b, task_so2.partner_id, "The Customer of the second task should be equal to partner_b.")
self.assertEqual(sale_order1.partner_id, task_so1.partner_id, "The Customer of the first task should be equal to the Customer of the first Sales Order.")
self.assertEqual(sale_order2.partner_id, task_so2.partner_id, "The Customer of the second task should be equal to the Customer of the second Sales Order.")
task_so1_timesheet1 = self.env['account.analytic.line'].create({
'name': 'Test Line1',
'project_id': task_so1.project_id.id,
'task_id': task_so1.id,
'unit_amount': 5,
'employee_id': self.employee_user.id,
})
invoice = sale_order1._create_invoices()
invoice.action_post()
self.assertEqual(self.partner_a, task_so1_timesheet1.partner_id, "The Task's Timesheet entry should have the same partner than on the task 1 and Sales Order 1.")
task_so1_timesheet2 = self.env['account.analytic.line'].create({
'name': 'Test Line2',
'project_id': task_so1.project_id.id,
'task_id': task_so1.id,
'unit_amount': 3,
'employee_id': self.employee_user.id,
})
task_so1.write({
'partner_id': self.partner_b.id,
'sale_line_id': so2_product_global_project_so_line.id,
})
self.assertEqual(self.partner_a, task_so1_timesheet1.partner_id, "The Task's first Timesheet entry should not have changed as it was already invoiced (its partner should still be partner_a).")
self.assertEqual(self.partner_b, task_so1_timesheet2.partner_id, "The Task's second Timesheet entry should have its partner changed, as it was not invoiced and the Task's partner/customer changed.")
self.assertEqual(so1_product_global_project_so_line, task_so1_timesheet1.so_line, "The Task's first Timesheet entry should not have changed as it was already invoiced (its so_line should still be equal to the first Sales Order line).")
self.assertEqual(so2_product_global_project_so_line, task_so1_timesheet2.so_line, "The Task's second Timesheet entry should have it's so_line changed, as the Sales Order Item of the Task changed, and this entry was not invoiced.")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment