[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:
@@ -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)
|
||||
|
||||
@@ -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():
|
||||
|
||||
Reference in New Issue
Block a user