[FIX] stock: avoid recomputing the schedule_date too early

Steps to reproduce:
- Inventory -> Delivery -> New Planned transfer
- Add two lines with two different products and save
- Set different scheduled dates for each move
- Set the earliest move quantity_done to the demand
- Validate and create a backorder

Issue:
The done picking scheduled date will be changed to the latest move (that
is moved to the backorder).

This is due to a recompute of the picking's scheduled_date *before* the
remaining moves are assigned to the backorder.

Note:
The order on the `stock.move.line` had to be removed, as it forced a
recompute of the original picking *before* the assignation of the
remaining moves to the backorder.
What happens is :
- Updating the move will check its move lines
- To follow the SML order, it will need their pickings
- To follow the picking order, it will need their scheduled date
- Their scheduled dates can be out of date (since we already put some
moves to `done`)
- This will lead to a recompute of the original picking's scheduled date

Instead, what we do is adapt the changes from odoo/odoo#79069, moving
the order from the model to the reports where it's used.

opw-3346598

closes odoo/odoo#147330

X-original-commit: 92092420548cb68db03ac139c23608fc1aa3a7cd
Related: odoo/enterprise#53320
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
This commit is contained in:
clesgow
2023-12-26 15:49:37 +00:00
parent d8c95bddec
commit 1f1a95282d
5 changed files with 53 additions and 10 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ class StockMoveLine(models.Model):
_name = "stock.move.line"
_description = "Product Moves (Stock Move Line)"
_rec_name = "product_id"
_order = "result_package_id desc, location_id asc, location_dest_id asc, picking_id asc, id"
_order = "result_package_id desc, id"
picking_id = fields.Many2one(
'stock.picking', 'Transfer', auto_join=True,
+4 -5
View File
@@ -1261,14 +1261,13 @@ class Picking(models.Model):
'move_line_ids': [],
'backorder_id': picking.id
})
moves_to_backorder.write({'picking_id': backorder_picking.id, 'picked': False})
moves_to_backorder.move_line_ids.package_level_id.write({'picking_id': backorder_picking.id})
moves_to_backorder.mapped('move_line_ids').write({'picking_id': backorder_picking.id})
backorders |= backorder_picking
picking.message_post(
body=_('The backorder %s has been created.', backorder_picking._get_html_link())
)
moves_to_backorder.write({'picking_id': backorder_picking.id, 'picked': False})
moves_to_backorder.move_line_ids.package_level_id.write({'picking_id': backorder_picking.id})
# moves_to_backorder._do_unreserve()
moves_to_backorder.mapped('move_line_ids').write({'picking_id': backorder_picking.id})
backorders |= backorder_picking
if backorder_picking.picking_type_id.reservation_method == 'at_confirm':
bo_to_assign |= backorder_picking
if bo_to_assign:
@@ -109,7 +109,7 @@
</thead>
<tbody>
<!-- In case you come across duplicated lines, ask NIM or LAP -->
<tr t-foreach="o.move_line_ids_without_package" t-as="ml">
<tr t-foreach="o.move_line_ids_without_package.sorted(lambda ml: (ml.location_id.complete_name, ml.location_dest_id.complete_name))" t-as="ml">
<td>
<span t-field="ml.product_id.display_name">Customizable Desk</span><br/>
<span t-field="ml.product_id.description_picking">Description on transfer</span>
+45 -1
View File
@@ -1,10 +1,13 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import Command
from dateutil.relativedelta import relativedelta
from odoo import Command, fields
from odoo.exceptions import UserError
from odoo.tests import Form, new_test_user
from odoo.tests.common import TransactionCase
from odoo.addons.mail.tests.common import mail_new_test_user
class StockMove(TransactionCase):
@@ -60,6 +63,14 @@ class StockMove(TransactionCase):
'type': 'consu',
'categ_id': cls.env.ref('product.product_category_all').id,
})
cls.user_stock_user = mail_new_test_user(
cls.env,
name='Stock user',
login='stock_user',
email='s.u@example.com',
notification_type='inbox',
groups='stock.group_stock_user',
)
def gather_relevant(self, product_id, location_id, lot_id=None, package_id=None, owner_id=None, strict=False):
quants = self.env['stock.quant']._gather(product_id, location_id, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=strict)
@@ -6221,3 +6232,36 @@ class StockMove(TransactionCase):
self.assertRecordValues(receipt.move_ids.move_line_ids[-1], [
{'location_dest_id': child_location.id, 'product_id': self.product.id, 'quantity': 2},
])
def test_scheduled_date_after_backorder(self):
today = fields.Datetime.today()
with Form(self.env['stock.picking']) as picking_form:
picking_form.picking_type_id = self.env.ref('stock.picking_type_out')
with picking_form.move_ids_without_package.new() as move:
move.product_id = self.product
move.product_uom_qty = 1
move.date = today + relativedelta(day=5)
with picking_form.move_ids_without_package.new() as move:
move.product_id = self.product_consu
move.product_uom_qty = 1
move.date = today + relativedelta(day=10)
picking = picking_form.save()
# Set different scheduled dates for each move
move_product = picking.move_ids.filtered(lambda m: m.product_id == self.product)
move_product.date = today + relativedelta(day=5)
move_consu = picking.move_ids.filtered(lambda m: m.product_id == self.product_consu)
move_consu.date = today + relativedelta(day=10)
self.assertEqual(picking.scheduled_date, today + relativedelta(day=5))
picking.action_confirm()
# Complete one move and create a backorder with the remaining move
move_product.quantity = 1
move_consu.quantity = 0
backorder_wizard_dict = picking.button_validate()
backorder_wizard = Form(self.env[backorder_wizard_dict['res_model']].with_context(backorder_wizard_dict['context'])).save()
backorder_wizard.with_user(self.user_stock_user).process()
backorder = self.env['stock.picking'].search([('backorder_id', '=', picking.id)])
self.assertEqual(picking.scheduled_date, today + relativedelta(day=5))
self.assertEqual(backorder.scheduled_date, today + relativedelta(day=10))
+2 -2
View File
@@ -186,7 +186,7 @@
<field name="model">stock.move.line</field>
<field name="priority">1000</field>
<field name="arch" type="xml">
<tree editable="bottom" decoration-muted="state == 'done' and is_locked == True">
<tree editable="bottom" decoration-muted="state == 'done' and is_locked == True" default_order="result_package_id desc, location_id asc, location_dest_id asc, picking_id asc, id">
<field name="company_id" column_invisible="True" force_save="1"/>
<field name="picking_id" column_invisible="True" force_save="1"/>
<field name="move_id" column_invisible="True" force_save="1" />
@@ -241,7 +241,7 @@
<field name="model">stock.move.line</field>
<field name="priority">1000</field>
<field name="arch" type="xml">
<tree editable="bottom" decoration-muted="(state == 'done' and is_locked == True)" multi_edit="1">
<tree editable="bottom" decoration-muted="(state == 'done' and is_locked == True)" multi_edit="1" default_order="result_package_id desc, location_id asc, location_dest_id asc, picking_id asc, id">
<header>
<button class="btn-primary" name="action_put_in_pack" type="object" string="Put in Pack" groups="stock.group_tracking_lot"/>
</header>