[FIX] sale_timesheet : unlink timesheet from invoice when deleting

invoice line

Steps:
- Create 2 service products with "Invoicing based on timesheet" & " Create a task in sales order's project"
- Create a SO with both products > confirm
- Add hours to both tasks
- Create invoice > remove one invoice line > Save

Issue:
- The removed invoice line is still appearing in the Timesheet stat button

Cause:
- account_analytic_line.timesheet_invoice_id is set to the invoice when the invoice is created
- It is not reset to False when the line is removed from the invoice

Fix:
- Reset it to False when the move the line is removed from invoice

opw-2668814

closes odoo/odoo#81831

X-original-commit: a391ea82091cd4cd62914d7e21fa54f5670126c9
Signed-off-by: Laurent Stukkens (ltu) <ltu@odoo.com>
This commit is contained in:
Audric Onockx (auon)
2021-12-23 16:43:06 +00:00
parent b0bf660c77
commit 197b7eddd7
2 changed files with 63 additions and 0 deletions
@@ -96,3 +96,33 @@ class AccountMoveLine(models.Model):
('project_id', '!=', False),
'|', ('timesheet_invoice_id', '=', False), ('timesheet_invoice_id.state', '=', 'cancel')
]
def unlink(self):
move_line_read_group = self.env['account.move.line'].search_read([
('move_id.move_type', '=', 'out_invoice'),
('move_id.state', '=', 'draft'),
('sale_line_ids.product_id.invoice_policy', '=', 'delivery'),
('sale_line_ids.product_id.service_type', '=', 'timesheet'),
('id', 'in', self.ids)],
['move_id', 'sale_line_ids'])
sale_line_ids_per_move = defaultdict(lambda: self.env['sale.order.line'])
for move_line in move_line_read_group:
sale_line_ids_per_move[move_line['move_id'][0]] += self.env['sale.order.line'].browse(move_line['sale_line_ids'])
timesheet_read_group = self.sudo().env['account.analytic.line'].read_group([
('timesheet_invoice_id.move_type', '=', 'out_invoice'),
('timesheet_invoice_id.state', '=', 'draft'),
('timesheet_invoice_id', 'in', self.move_id.ids)],
['timesheet_invoice_id', 'so_line', 'ids:array_agg(id)'],
['timesheet_invoice_id', 'so_line'],
lazy=False)
timesheet_ids = []
for timesheet in timesheet_read_group:
move_id = timesheet['timesheet_invoice_id'][0]
if timesheet['so_line'][0] in sale_line_ids_per_move[move_id].ids:
timesheet_ids += timesheet['ids']
self.sudo().env['account.analytic.line'].browse(timesheet_ids).write({'timesheet_invoice_id': False})
super().unlink()
@@ -688,3 +688,36 @@ class TestSaleTimesheet(TestCommonSaleTimesheet):
('res_id', '=', sale_order.id),
])
self.assertEqual(len(message_sent), 1, 'Sale Timesheet: An email should only be sent to the saleperson when the state of the sale order change to upselling')
def test_unlink_timesheet(self):
sale_order = 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,
})
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_order.id,
})
sale_order.action_confirm()
task = so_line.task_id
# let's log some timesheets
analytic_line = self.env['account.analytic.line'].create({
'name': 'Test Line',
'project_id': task.project_id.id,
'task_id': task.id,
'unit_amount': 50,
'employee_id': self.employee_manager.id,
})
move = sale_order._create_invoices()
self.assertEqual(analytic_line.timesheet_invoice_id, move, "The timesheet should be linked to move")
move.with_context(check_move_validity=False).line_ids[0].unlink()
self.assertFalse(analytic_line.timesheet_invoice_id, "The timesheet should have been unlinked from move")