diff --git a/addons/mrp_subcontracting_dropshipping/models/stock_picking.py b/addons/mrp_subcontracting_dropshipping/models/stock_picking.py index b81c9cd2819..4ae776d4e5d 100644 --- a/addons/mrp_subcontracting_dropshipping/models/stock_picking.py +++ b/addons/mrp_subcontracting_dropshipping/models/stock_picking.py @@ -24,7 +24,10 @@ class StockPicking(models.Model): def _prepare_subcontract_mo_vals(self, subcontract_move, bom): res = super()._prepare_subcontract_mo_vals(subcontract_move, bom) - if not res.get('picking_type_id') and subcontract_move.location_dest_id.usage == 'customer': + if not res.get('picking_type_id') and ( + subcontract_move.location_dest_id.usage == 'customer' + or subcontract_move.location_dest_id.is_subcontracting_location + ): # If the if-condition is respected, it means that `subcontract_move` is not # related to a specific warehouse. This can happen if, for instance, the user # confirms a PO with a subcontracted product that should be delivered to a diff --git a/addons/mrp_subcontracting_dropshipping/tests/test_purchase_subcontracting.py b/addons/mrp_subcontracting_dropshipping/tests/test_purchase_subcontracting.py index 769b9f33070..63534e5e4e9 100644 --- a/addons/mrp_subcontracting_dropshipping/tests/test_purchase_subcontracting.py +++ b/addons/mrp_subcontracting_dropshipping/tests/test_purchase_subcontracting.py @@ -248,3 +248,75 @@ class TestSubcontractingDropshippingFlows(TestMrpSubcontractingCommon): self.assertEqual(delivery.state, 'done') self.assertEqual(mo.state, 'done') self.assertEqual(po.order_line.qty_received, 1) + + def test_po_to_subcontractor(self): + """ + Create and confirm a PO with a subcontracted move. The bought product is + also a component of another subcontracted product. The picking type of + the PO is 'Dropship' and the delivery address is the other subcontractor + """ + subcontractor, super_subcontractor = self.env['res.partner'].create([ + {'name': 'Subcontractor'}, + {'name': 'SuperSubcontractor'}, + ]) + + super_product, product, component = self.env['product.product'].create([{ + 'name': 'Super Product', + 'type': 'product', + 'seller_ids': [(0, 0, {'partner_id': super_subcontractor.id})], + }, { + 'name': 'Product', + 'type': 'product', + 'seller_ids': [(0, 0, {'partner_id': subcontractor.id})], + }, { + 'name': 'Component', + 'type': 'consu', + }]) + + _, bom_product = self.env['mrp.bom'].create([{ + 'product_tmpl_id': super_product.product_tmpl_id.id, + 'product_qty': 1, + 'type': 'subcontract', + 'subcontractor_ids': [(6, 0, super_subcontractor.ids)], + 'bom_line_ids': [ + (0, 0, {'product_id': product.id, 'product_qty': 1}), + ], + }, { + 'product_tmpl_id': product.product_tmpl_id.id, + 'product_qty': 1, + 'type': 'subcontract', + 'subcontractor_ids': [(6, 0, subcontractor.ids)], + 'bom_line_ids': [ + (0, 0, {'product_id': component.id, 'product_qty': 1}), + ], + }]) + + dropship_picking_type = self.env['stock.picking.type'].search([ + ('company_id', '=', self.env.company.id), + ('default_location_src_id.usage', '=', 'supplier'), + ('default_location_dest_id.usage', '=', 'customer'), + ], limit=1, order='sequence') + + po = self.env['purchase.order'].create({ + "partner_id": subcontractor.id, + "picking_type_id": dropship_picking_type.id, + "dest_address_id": super_subcontractor.id, + "order_line": [(0, 0, { + 'product_id': product.id, + 'name': product.name, + 'product_qty': 1.0, + })], + }) + po.button_confirm() + + mo = self.env['mrp.production'].search([('bom_id', '=', bom_product.id)]) + self.assertEqual(mo.picking_type_id, self.warehouse.subcontracting_type_id) + + delivery = po.picking_ids + self.assertEqual(delivery.location_dest_id, super_subcontractor.property_stock_subcontractor) + self.assertTrue(delivery.is_dropship) + + delivery.move_line_ids.qty_done = 1.0 + delivery.button_validate() + + self.assertEqual(po.order_line.qty_received, 1.0) diff --git a/addons/purchase_stock/models/purchase.py b/addons/purchase_stock/models/purchase.py index ec47a056c67..a3a1dce3b40 100644 --- a/addons/purchase_stock/models/purchase.py +++ b/addons/purchase_stock/models/purchase.py @@ -331,6 +331,7 @@ class PurchaseOrderLine(models.Model): elif ( move.location_dest_id.usage == "internal" and move.location_id.usage != "supplier" + and move.warehouse_id and move.location_dest_id not in self.env["stock.location"].search( [("id", "child_of", move.warehouse_id.view_location_id.id)]