[FIX] stock, mrp_subcontracting_purchase: fix subcontract location after dest. update
Steps to reproduce:
- Install mrp and purchase
- Go to "Inventory / Configuration / Settings"
- Activate "Storage Locations"
- Go to "Inventory / Configuration / Warehouse Management / Operations Types"
- Edit "Receipts" type by activating "Show Detailed Operations"
- Go to "Manufactoring / Configuration / Settings"
- Activate "Subcontracting"
- Create product: (e.g. Product XYZ)
* Product Type: Storable Product
- Create a BoM for Product XYZ:
* BoM Type: Subcontracting
* Subcontractors: [any] (e.g. Azure Interior)
- Create a PO:
* Vendor: Azure Interior
* Products: 2 x Product XYZ
- Confirm the PO
- Open the picking from PO via the Receipt smart button
- In "Operations" tab, set done to 1
- On the picking form, change the destination location (e.g. WH/Stock/Shelf1)
- Save
- In "Detailed Operations" tab, a line should have appeared
- Select the same destination location on that line (i.e. WH/Stock/Shelf1)
- Validate the picking and create a backorder for the remaining quantity to produce
- Go to "Inventory / Reporting / Locations"
- Check the locations of Product XYZ (Search Product: XYZ - Group by: Location)
=> The "On Hand Quantity" for Product XYZ is as followed:
* Virtual Locations/Production: -1.00 (correct)
* WH/Stock/Shelf1: 1.00 (correct)
- Open the backorder picking from PO via the Receipt smart button
- Record the production of the remaining unit
- Validate the picking
- Go to "Inventory / Reporting / Locations"
- Check the locations of Product XYZ
Issue:
The "On Hand Quantity" for Product XYZ is as followed:
* Partners/Vendors: -1.00 (incorrect, it should be empty)
* Physical Locations/Subcontracting Location: 1.00 (incorrect, it should be 0.00)
* Virtual Locations/Production: -2.00 (correct)
* WH/Stock/Shelf1: 2.00 (correct)
Cause:
When the PO is confirmed, the stock picking and the stock move are created, they both
have the same source and destination locations.
However, in an overridden method from "mrp_subcontracting" module, a check is performed
on the move to determine if it is a subcontract.
If it is the case, its source location is set to the subcontractor location and so, the
source location of the picking and the move is not the same anymore.
When the destination location is changed on the picking, an onchange is triggering an
update of the destination location AND the source location of the move to the values
coming from the picking, erasing the subcontractor location set on the move.
The issue only happens for the backorder, because the source location update is not
propagated to the stock move lines.
In the case of the original picking, the move lines were already created with the
subcontractor location as source location.
But when the backorder is created, the move lines are created with the values coming
from a move without the subcontractor location.
Solution:
Do not propagate "location_id" from the picking to the subcontracting moves.
opw-3777379
closes odoo/odoo#161011
X-original-commit: e0f7577da1a42512d2fdc5ee316f27a1ce040522
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Anh Thao Pham (pta) <pta@odoo.com>
This commit is contained in:
@@ -196,6 +196,13 @@ msgid ""
|
||||
" subcontracting portal view"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_subcontracting
|
||||
#. odoo-python
|
||||
#: code:addons/mrp_subcontracting/models/stock_picking.py:0
|
||||
#, python-format
|
||||
msgid "Locations to update"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_subcontracting
|
||||
#: model:ir.model.fields,field_description:mrp_subcontracting.field_res_partner__production_ids
|
||||
#: model:ir.model.fields,field_description:mrp_subcontracting.field_res_users__production_ids
|
||||
@@ -619,6 +626,13 @@ msgstr ""
|
||||
msgid "You cannot write on fields %s in mrp.production."
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_subcontracting
|
||||
#. odoo-python
|
||||
#: code:addons/mrp_subcontracting/models/stock_picking.py:0
|
||||
#, python-format
|
||||
msgid "You might want to update the locations of this transfer's operations"
|
||||
msgstr ""
|
||||
|
||||
#. module: mrp_subcontracting
|
||||
#. odoo-python
|
||||
#: code:addons/mrp_subcontracting/models/mrp_production.py:0
|
||||
|
||||
@@ -181,3 +181,20 @@ class StockPicking(models.Model):
|
||||
finished_move.write({'move_dest_ids': [(4, move.id, False)]})
|
||||
|
||||
all_mo.action_assign()
|
||||
|
||||
@api.onchange('location_id', 'location_dest_id')
|
||||
def _onchange_locations(self):
|
||||
moves = self.move_ids | self.move_ids_without_package
|
||||
moves.filtered(lambda m: m.is_subcontract).update({
|
||||
"location_dest_id": self.location_dest_id,
|
||||
})
|
||||
moves.filtered(lambda m: not m.is_subcontract).update({
|
||||
"location_id": self.location_id,
|
||||
"location_dest_id": self.location_dest_id,
|
||||
})
|
||||
if self._origin.location_id != self.location_id and any(line.quantity for line in self.move_ids.move_line_ids):
|
||||
return {'warning': {
|
||||
'title': _("Locations to update"),
|
||||
'message': _("You might want to update the locations of this transfer's operations"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -810,3 +810,62 @@ class MrpSubcontractingPurchaseTest(TestMrpSubcontractingCommon):
|
||||
self.assertEqual(bom_data['lines']['leftover_capacity'], 1)
|
||||
# 01/16 + 2 x 2 days (for components and for final product) = 01/20
|
||||
self.assertEqual(bom_data['lines']['leftover_date'], '01/20/2024')
|
||||
|
||||
def test_location_after_dest_location_update_backorder_production(self):
|
||||
"""
|
||||
Buy 2 subcontracted products.
|
||||
Receive 1 product after changing the destination location.
|
||||
Create a backorder.
|
||||
Receive the last one.
|
||||
Check the locations.
|
||||
"""
|
||||
grp_multi_loc = self.env.ref('stock.group_stock_multi_locations')
|
||||
self.env.user.write({'groups_id': [Command.link(grp_multi_loc.id)]})
|
||||
subcontract_loc = self.env.company.subcontracting_location_id
|
||||
production_loc = self.finished.property_stock_production
|
||||
final_loc = self.env['stock.location'].create({
|
||||
'name': 'Final location',
|
||||
'location_id': self.env.ref('stock.warehouse0').lot_stock_id.id,
|
||||
})
|
||||
# buy 2 subcontracted products
|
||||
po = self.env['purchase.order'].create({
|
||||
'partner_id': self.subcontractor_partner1.id,
|
||||
'order_line': [Command.create({
|
||||
'name': self.finished.name,
|
||||
'product_id': self.finished.id,
|
||||
'product_qty': 2.0,
|
||||
'product_uom': self.finished.uom_id.id,
|
||||
'price_unit': 1.0,
|
||||
})],
|
||||
})
|
||||
po.button_confirm()
|
||||
|
||||
receipt = po.picking_ids
|
||||
# receive 1 subcontracted product
|
||||
receipt.move_ids.quantity = 1
|
||||
receipt_form = Form(receipt)
|
||||
# change the destination location
|
||||
receipt_form.location_dest_id = final_loc
|
||||
receipt_form.save()
|
||||
# change the destination location on the move line too
|
||||
receipt.move_line_ids.location_dest_id = final_loc
|
||||
# create the backorder
|
||||
backorder_wizard_dict = receipt.button_validate()
|
||||
backorder_wizard = Form(self.env[backorder_wizard_dict['res_model']].with_context(backorder_wizard_dict['context'])).save()
|
||||
backorder_wizard.process()
|
||||
backorder = receipt.backorder_ids
|
||||
# test the stock quantities after receiving 1 product
|
||||
stock_quants = self.env['stock.quant'].search([('product_id', '=', self.finished.id)])
|
||||
self.assertEqual(len(stock_quants), 3)
|
||||
self.assertEqual(stock_quants.filtered(lambda q: q.location_id == final_loc).quantity, 1.0)
|
||||
self.assertEqual(stock_quants.filtered(lambda q: q.location_id == subcontract_loc).quantity, 0.0)
|
||||
self.assertEqual(stock_quants.filtered(lambda q: q.location_id == production_loc).quantity, -1.0)
|
||||
# receive the last subcontracted product
|
||||
backorder.move_ids.quantity = 1
|
||||
backorder.button_validate()
|
||||
# test the final stock quantities
|
||||
stock_quants = self.env['stock.quant'].search([('product_id', '=', self.finished.id)])
|
||||
self.assertEqual(len(stock_quants), 3)
|
||||
self.assertEqual(stock_quants.filtered(lambda q: q.location_id == final_loc).quantity, 2.0)
|
||||
self.assertEqual(stock_quants.filtered(lambda q: q.location_id == subcontract_loc).quantity, 0.0)
|
||||
self.assertEqual(stock_quants.filtered(lambda q: q.location_id == production_loc).quantity, -2.0)
|
||||
|
||||
@@ -4533,6 +4533,13 @@ msgstr ""
|
||||
msgid "Locations"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock
|
||||
#. odoo-python
|
||||
#: code:addons/stock/models/stock_picking.py:0
|
||||
#, python-format
|
||||
msgid "Locations to update"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock
|
||||
#: model:ir.actions.server,name:stock.action_toggle_is_locked
|
||||
msgid "Lock/Unlock"
|
||||
|
||||
@@ -813,7 +813,7 @@ class Picking(models.Model):
|
||||
})
|
||||
if self._origin.location_id != self.location_id and any(line.quantity for line in self.move_ids.move_line_ids):
|
||||
return {'warning': {
|
||||
'title': 'Locations to update',
|
||||
'title': _("Locations to update"),
|
||||
'message': _("You might want to update the locations of this transfer's operations")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user