[FIX] stock,{stock,mrp}_account: add SML with kit to draft picking

If account is installed, it is not possible to scan a kit and
validate the picking

To reproduce the issue:
(Need stock_barcode_mrp)
1. Create two products P_kit, P_compo:
   - P_kit:
     - Barcode: 123
2. Create a kit-type BoM
3. Barcode > Operations > Receipts, Create
4. Scan 123
5. Validate

Error: an error message is displayed ("Record does not exist or has
been deleted")

When validating the receipt, it creates the SML_kit and its SM_kit.
Both are in draft state. So, we validate SM_kit. In
`/stock_account._action_done`, we add SM_kit to a dict
(`valued_moves`) and we then call the `super` method:
https://github.com/odoo/odoo/blob/33fa9cff038691a98ca840fe0d72484da16276ba/addons/stock_account/models/stock_move.py#L244-L257
In `/stock._action_done`, because of the state of SM, we confirm it:
https://github.com/odoo/odoo/blob/24f2e3f73498e5eb180a6793de6c25efd414aadb/addons/stock/models/stock_move.py#L1517-L1518
And, therefore, we explode SM_kit:
https://github.com/odoo/odoo/blob/5f8da70b5b1f313e9b676846e55e84621f55e734/addons/mrp/models/stock_move.py#L239-L240
This creates SM_compo and unlink SM_kit. However, there are two issues:
- In `/stock._action_done`, we don't keep any reference to SM_compo.
  The method will not return it and `/stock_account._action_done`
  will not create any layer, if needed, for that SM_compo
- In `/stock_account._action_done`, we don't consider that SM_kit
  may have been deleted. As a result, we keep using it:
  https://github.com/odoo/odoo/blob/33fa9cff038691a98ca840fe0d72484da16276ba/addons/stock_account/models/stock_move.py#L266-L271
  This is the reason why an error will be raised

OPW-3015933

closes odoo/odoo#108762

closes odoo/odoo#112814

X-original-commit: c78666e3fbd06bc7a7899ccaa6e562bf3072e955
Related: odoo/enterprise#37137
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
This commit is contained in:
Adrien Widart (awt)
2023-02-16 11:35:50 +01:00
parent 2865cc6119
commit d645518638
3 changed files with 37 additions and 2 deletions
@@ -316,3 +316,35 @@ class TestMrpValuationStandard(TestMrpValuationCommon):
self.assertEqual(self.product1.quantity_svl, 2)
self._make_out_move(self.product1, 1)
self.assertEqual(self.product1.value_svl, 15)
def test_validate_draft_kit(self):
"""
Create a draft receipt, add a kit to its move lines and directly
validate it. From client side, such a behaviour is possible with
the Barcode app.
"""
self.component.product_tmpl_id.categ_id.property_cost_method = 'average'
self.product1.type = 'consu'
self.bom.type = 'phantom'
self.component.standard_price = 1424
receipt = self.env['stock.picking'].create({
'location_id': self.customer_location.id,
'location_dest_id': self.stock_location.id,
'picking_type_id': self.picking_type_in.id,
'move_line_ids': [(0, 0, {
'product_id': self.product1.id,
'qty_done': 1,
'product_uom_id': self.product1.uom_id.id,
'location_id': self.customer_location.id,
'location_dest_id': self.stock_location.id,
})]
})
receipt.button_validate()
self.assertEqual(receipt.state, 'done')
self.assertRecordValues(receipt.move_ids, [
{'product_id': self.component.id, 'quantity_done': 1, 'state': 'done'},
])
self.assertEqual(self.component.qty_available, 1)
self.assertEqual(self.component.value_svl, 1424)
+2 -2
View File
@@ -1761,8 +1761,8 @@ Please change the quantity done or the rounding precision of your unit of measur
return extra_move | self
def _action_done(self, cancel_backorder=False):
self.filtered(lambda move: move.state == 'draft')._action_confirm() # MRP allows scrapping draft moves
moves = self.exists().filtered(lambda x: x.state not in ('done', 'cancel'))
moves = self.filtered(lambda move: move.state == 'draft')._action_confirm() # MRP allows scrapping draft moves
moves = (self | moves).exists().filtered(lambda x: x.state not in ('done', 'cancel'))
moves_ids_todo = OrderedSet()
# Cancel moves where necessary ; we should do it before creating the extra moves because
@@ -252,6 +252,9 @@ class StockMove(models.Model):
res = super(StockMove, self)._action_done(cancel_backorder=cancel_backorder)
# '_action_done' might have deleted some exploded stock moves
valued_moves = {value_type: moves.exists() for value_type, moves in valued_moves.items()}
# '_action_done' might have created an extra move to be valued
for move in res - self:
for valued_type in self._get_valued_types():