[FIX] l10n_it_stock_ddt: calculate link between invoice and deliveries

Steps to reproduce the bug:
- Install [l10n_it_ddt]
- Create a storable product “P1”
- Create a SO for “P1” with qty 3
- Deliver 1 unit and create a backorder
- Generate the invoice for the delivered qty: 1
- Post the invoice
- smart button with the link to DDT n°1 appears
- Deliver the remaining 2 units
- Create the second invoice
- Post the invoice

Problem:
The link to DDT appears but with the 2 pickings, whereas in this case
only the 2nd picking is linked to the invoice.

Before using the `account.move.line` records, we sorted them by date
in order to always use the first created one to link it with the first
picking created, however if two `account.move.line` were created in
the same days, they will be ordered randomly, so we also have to
sort them by id if the date is the same.

opw-2968401

closes odoo/odoo#100998

X-original-commit: e8e99c05696308422183516e68c0b9ed5495d7ca
Signed-off-by: Josse Colpaert <jco@odoo.com>
Signed-off-by: Djamel Touati (otd) <otd@odoo.com>
This commit is contained in:
Touati Djamel (otd)
2022-09-27 12:43:44 +02:00
parent 7e9445ae7b
commit eafabb58c3
2 changed files with 48 additions and 2 deletions
@@ -31,11 +31,11 @@ class AccountMove(models.Model):
invoice_line_pickings.setdefault(done_moves_related.picking_id, []).append(line_count)
else:
total_invoices = done_moves_related.mapped('sale_line_id.invoice_lines').filtered(
lambda l: l.move_id.state == 'posted' and l.move_id.move_type == 'out_invoice').sorted(lambda l: l.move_id.invoice_date)
lambda l: l.move_id.state == 'posted' and l.move_id.move_type == 'out_invoice').sorted(lambda l: (l.move_id.invoice_date, l.move_id.id))
total_invs = [(i.product_uom_id._compute_quantity(i.quantity, i.product_id.uom_id), i) for i in total_invoices]
inv = total_invs.pop(0)
# Match all moves and related invoice lines FIFO looking for when the matched invoice_line matches line
for move in done_moves_related.sorted(lambda m: m.date):
for move in done_moves_related.sorted(lambda m: (m.date, m.id)):
rounding = move.product_uom.rounding
move_qty = move.product_qty
while (float_compare(move_qty, 0, precision_rounding=rounding) > 0):
@@ -100,3 +100,49 @@ class TestDDT(TestSaleCommon):
# But is consistently broken after recent cleanings in sale
# with the flush & invalidate, it always breaks, even without the cleanings
# self.assertEqual(self.inv2.l10n_it_ddt_ids.ids, (pickx1 | pickx2).ids, 'DDTs should be linked to the invoice')
def test_ddt_flow_2(self):
"""
Test that the link between the invoice lines and the deliveries linked to the invoice
through the link with the sale order is calculated correctly.
"""
so = self.env['sale.order'].create({
'partner_id': self.partner_a.id,
'order_line': [(0, 0, {
'product_id': self.product_a.id,
'product_uom_qty': 3,
'product_uom': self.product_a.uom_id.id,
'price_unit': self.product_a.list_price,
'tax_id': self.company_data['default_tax_sale']
}
)],
'pricelist_id': self.company_data['default_pricelist'].id,
'picking_policy': 'direct',
})
so.action_confirm()
# deliver partially
picking_1 = so.picking_ids
picking_1.move_ids.write({'quantity_done': 1})
wiz_act = picking_1.button_validate()
wiz = Form(self.env[wiz_act['res_model']].with_context(wiz_act['context'])).save()
wiz.process()
invoice_1 = so._create_invoices()
invoice_form = Form(invoice_1)
with invoice_form.invoice_line_ids.edit(0) as line:
line.quantity = 1.0
invoice_1 = invoice_form.save()
invoice_1.action_post()
picking_2 = so.picking_ids.filtered(lambda p: p.state != 'done')
picking_2.move_ids.write({'quantity_done': 2})
picking_2.button_validate()
invoice_2 = so._create_invoices()
invoice_2.action_post()
# Invalidate the cache to ensure the lines will be fetched in the right order.
picking_2.invalidate_model()
self.assertEqual(invoice_1.l10n_it_ddt_ids.ids, picking_1.ids, 'DDT picking_1 should be linked to the invoice_1')
self.assertEqual(invoice_2.l10n_it_ddt_ids.ids, picking_2.ids, 'DDT picking_2 should be linked to the invoice_2')