A user can not buy a subcontracted product and directly deliver it
(dropship) to another subcontractor. Moreover, in such situation, the
received quantity is not correctly computed.
To reproduce the issue:
(Enable debug mode)
1. In Settings, enable "Storage Locations"
2. Create three products:
- P1:
- Storable
- With a vendor V1
- P2:
- Storable
- With a vendor V2
- P3:
- Consumable
3. Edit V1:
- Customer Location: Physical Locations/Subcontracting Location
4. Create two BoMs:
- Product: P1
- Type: Subcontracting
- Subcontractors: V1
- Components: 1 x P2
- Product: P2
- Type: Subcontracting
- Subcontractors: V2
- Components: 1 x P3
5. Create a PO:
- Vendor: V2
- Deliver To: Dropship
- Drop Ship Address: V1
- Products: 1 x P2
6. Confirm the PO
Error: a Validation Error is raised at `mrp.production` creation because
of a missing field (`picking_type_id`).
In some cases, when getting the values to create the MO, the basic
`_prepare_subcontract_mo_vals` does not return any `picking_type_id`.
That's the reason why an override has been added in
`/mrp_subcontracting_dropshipping` (see [1] for more details). Thanks to
this override, if the usage of the destination location is `customer`,
we know that we are in a "dropship" situation and we manually define the
`picking_type_id`:
https://github.com/odoo/odoo/blob/d73e70f22e47e81e59aff0c9f578aff260447256/addons/mrp_subcontracting_dropshipping/models/stock_picking.py#L15-L17
However, in the above case, the subcontracted stock move starts from a
subcontracted location and also goes to a subcontracted location
(because of step 3). As a result, the if-condition is not respected and
the `picking_type_id` is not defined.
Once this issue is solved, there is a second one: suppose the PO
confirmed. The user validates the transfer. New error: the received
quantity on the PO is not updated. This is because of an incorrect
condition in `/purchase_stock._compute_qty_received`:
https://github.com/odoo/odoo/blob/d0537e32e5aa4b0fe2ad674ab3ec7c42ae1a12f9/addons/purchase_stock/models/purchase.py#L306-L315
Added by [2] and modified by [3], this condition checks that:
- the destination location usage is `internal` (correct, this is a
subcontracting location)
- the source location usage is not `supplier` (correct, this is a
subcontracting location, so it is `internal`)
- the destination location is not part of the warehouse children (here
is the issue: the SM does not have any warehouse, so it gives a false
positive)
So, because of the incorrect third condition, the condition is
respected. And because `to_refund` is `False` (which is correct), we
don't do anything. That's the reason why the received quantity is not
updated.
[1] d73e70f22e47e81e59aff0c9f578aff260447256
[2] e6a1e240f1
[3] fd22fe221026e353aac7414348b029ae7e290b2f
OPW-2922546
closes odoo/odoo#102224
X-original-commit: a51b4158b964a11fa371a9eb8c877c9ec395f412
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
39 lines
1.8 KiB
Python
39 lines
1.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import models
|
|
|
|
|
|
class StockPicking(models.Model):
|
|
_inherit = 'stock.picking'
|
|
|
|
def _compute_is_dropship(self):
|
|
dropship_subcontract_pickings = self.filtered(lambda p: p.location_dest_id.is_subcontracting_location and p.location_id.usage == 'supplier')
|
|
dropship_subcontract_pickings.is_dropship = True
|
|
super(StockPicking, self - dropship_subcontract_pickings)._compute_is_dropship()
|
|
|
|
def _get_warehouse(self, subcontract_move):
|
|
if subcontract_move.sale_line_id:
|
|
return subcontract_move.sale_line_id.order_id.warehouse_id
|
|
return super(StockPicking, self)._get_warehouse(subcontract_move)
|
|
|
|
def _action_done(self):
|
|
res = super()._action_done()
|
|
self.move_ids.move_dest_ids._action_assign()
|
|
return res
|
|
|
|
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'
|
|
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
|
|
# customer (dropshipping). In that case, we can use a default warehouse to
|
|
# get the picking type
|
|
default_warehouse = self.env['stock.warehouse'].search([('company_id', '=', subcontract_move.company_id.id)], limit=1)
|
|
res['picking_type_id'] = default_warehouse.subcontracting_type_id.id,
|
|
return res
|