[FIX] mrp_subcontracting: decrease done quantity
To reproduce the issue: 1. Create a subcontracted product P 2. Create and confirm a planned transfer with 10 x P 3. Set the done quantity to 8 4. Set the done quantity to 7 5. Open the detailed operation (i.e., the MO) Error: The producing quantity of the MO is 1, it should be 3 When setting a smaller done quantity than the demand (step 8), we update the expected quantity of the related MO, we set its producing quantity, and we create a backorder. When decreasing the done quantity, we update/cancel the related productions. But here is the issue: in the above case, we simply decrease the expected quantity of the backorder, so we just lose the cancelled quantity, the user "can't" produce this quantity anymore. In such situation (when decreasing the done quantity), we should consider the last production (i.e., the last backorder) as the WIP one. So, we should update/cancel the other productions and increase the expected quantity of this last backorder, so the user can produce it again. OPW-3557632 closes odoo/odoo#142513 Signed-off-by: William Henrotin (whe) <whe@odoo.com> Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
This commit is contained in:
committed by
clesgow
parent
803237a9bf
commit
ef604945d8
@@ -77,7 +77,7 @@ class StockMove(models.Model):
|
||||
move._auto_record_components(delta_qty)
|
||||
to_set_moves -= move
|
||||
elif float_compare(delta_qty, 0, precision_rounding=move.product_uom.rounding) < 0:
|
||||
move._reduce_subcontract_order_qty(abs(delta_qty))
|
||||
move.with_context(transfer_qty=True)._reduce_subcontract_order_qty(abs(delta_qty))
|
||||
if to_set_moves:
|
||||
super(StockMove, to_set_moves)._set_quantity()
|
||||
|
||||
@@ -295,8 +295,17 @@ class StockMove(models.Model):
|
||||
def _reduce_subcontract_order_qty(self, quantity_to_remove):
|
||||
self.ensure_one()
|
||||
productions = self.move_orig_ids.production_id.filtered(lambda p: p.state not in ('done', 'cancel'))[::-1]
|
||||
wip_production = productions[0] if self._context.get('transfer_qty') and len(productions) > 1 else self.env['mrp.production']
|
||||
|
||||
# Transfer removed qty to WIP production
|
||||
if wip_production:
|
||||
self.env['change.production.qty'].with_context(skip_activity=True).create({
|
||||
'mo_id': wip_production.id,
|
||||
'product_qty': wip_production.product_uom_qty + quantity_to_remove
|
||||
}).change_prod_qty()
|
||||
|
||||
# Cancel productions until reach new_quantity
|
||||
for production in productions:
|
||||
for production in (productions - wip_production):
|
||||
if quantity_to_remove >= production.product_qty:
|
||||
quantity_to_remove -= production.product_qty
|
||||
production.with_context(skip_activity=True).action_cancel()
|
||||
|
||||
@@ -837,6 +837,75 @@ class TestSubcontractingFlows(TestMrpSubcontractingCommon):
|
||||
{'product_qty': 3, 'state': 'cancel'},
|
||||
])
|
||||
|
||||
def test_decrease_quantity_done(self):
|
||||
self.bom.consumption = 'flexible'
|
||||
supplier_location = self.env.ref('stock.stock_location_suppliers')
|
||||
|
||||
receipt = self.env['stock.picking'].create({
|
||||
'partner_id': self.subcontractor_partner1.id,
|
||||
'location_id': supplier_location.id,
|
||||
'location_dest_id': self.warehouse.lot_stock_id.id,
|
||||
'picking_type_id': self.warehouse.in_type_id.id,
|
||||
'move_ids': [(0, 0, {
|
||||
'name': self.finished.name,
|
||||
'product_id': self.finished.id,
|
||||
'product_uom_qty': 10.0,
|
||||
'product_uom': self.finished.uom_id.id,
|
||||
'location_id': supplier_location.id,
|
||||
'location_dest_id': self.warehouse.lot_stock_id.id,
|
||||
})],
|
||||
})
|
||||
|
||||
receipt.action_confirm()
|
||||
productions = self.env['mrp.production'].search([('product_id', '=', self.finished.id)], order='id')
|
||||
self.assertRecordValues(productions, [
|
||||
{'qty_producing': 0.0, 'product_qty': 10.0, 'state': 'confirmed'},
|
||||
])
|
||||
|
||||
receipt.move_ids.quantity = 6
|
||||
productions = self.env['mrp.production'].search([('product_id', '=', self.finished.id)], order='id')
|
||||
self.assertEqual(receipt.move_ids.product_uom_qty, 10.0, 'Demand should not be impacted')
|
||||
self.assertRecordValues(productions, [
|
||||
{'qty_producing': 6.0, 'product_qty': 6.0, 'state': 'to_close'},
|
||||
{'qty_producing': 4.0, 'product_qty': 4.0, 'state': 'to_close'},
|
||||
])
|
||||
|
||||
receipt.move_ids.quantity = 9
|
||||
productions = self.env['mrp.production'].search([('product_id', '=', self.finished.id)], order='id')
|
||||
self.assertEqual(receipt.move_ids.product_uom_qty, 10.0, 'Demand should not be impacted')
|
||||
self.assertRecordValues(productions, [
|
||||
{'qty_producing': 6.0, 'product_qty': 6.0, 'state': 'to_close'},
|
||||
{'qty_producing': 3.0, 'product_qty': 3.0, 'state': 'to_close'},
|
||||
{'qty_producing': 1.0, 'product_qty': 1.0, 'state': 'to_close'},
|
||||
])
|
||||
|
||||
receipt.move_ids.quantity = 7
|
||||
productions = self.env['mrp.production'].search([('product_id', '=', self.finished.id)], order='id')
|
||||
self.assertEqual(receipt.move_ids.product_uom_qty, 10.0, 'Demand should not be impacted')
|
||||
self.assertRecordValues(productions, [
|
||||
{'qty_producing': 6.0, 'product_qty': 6.0, 'state': 'to_close'},
|
||||
{'qty_producing': 1.0, 'product_qty': 1.0, 'state': 'to_close'},
|
||||
{'qty_producing': 3.0, 'product_qty': 3.0, 'state': 'to_close'},
|
||||
])
|
||||
|
||||
receipt.move_ids.quantity = 4
|
||||
productions = self.env['mrp.production'].search([('product_id', '=', self.finished.id)], order='id')
|
||||
self.assertEqual(receipt.move_ids.product_uom_qty, 10.0, 'Demand should not be impacted')
|
||||
self.assertRecordValues(productions, [
|
||||
{'qty_producing': 4.0, 'product_qty': 4.0, 'state': 'to_close'},
|
||||
{'qty_producing': 1.0, 'product_qty': 1.0, 'state': 'cancel'},
|
||||
{'qty_producing': 6.0, 'product_qty': 6.0, 'state': 'to_close'},
|
||||
])
|
||||
|
||||
receipt.move_ids.quantity = 0
|
||||
productions = self.env['mrp.production'].search([('product_id', '=', self.finished.id)], order='id')
|
||||
self.assertEqual(receipt.move_ids.product_uom_qty, 10.0, 'Demand should not be impacted')
|
||||
self.assertRecordValues(productions, [
|
||||
{'qty_producing': 4.0, 'product_qty': 4.0, 'state': 'cancel'},
|
||||
{'qty_producing': 1.0, 'product_qty': 1.0, 'state': 'cancel'},
|
||||
{'qty_producing': 10.0, 'product_qty': 10.0, 'state': 'to_close'},
|
||||
])
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestSubcontractingTracking(TransactionCase):
|
||||
|
||||
Reference in New Issue
Block a user