[FIX] {sale,sale_purchase,purchase}_stock: cancel SO linked with a PO

When the user cancels a SO, if there is an associated PO, there won't be
any activity logged on the PO about the SO cancellation.

To reproduce the issue:
1. Unarchive the MTO route
2. Create a product P:
    - Type: Storable
    - Routes: MTO & Buy
    - Add a vendor V
3. Create and confirm a SO with 1 x P
    - Note: a PO is generated
4. Cancel the SO
5. Open the PO

Error: There isn't any information about the cancellation of the SO. An
activity should be added to the PO.

Since [1], if the PO is a draft, we no longer log an activity when the
quantity of the related SO is reduced:
https://github.com/odoo/odoo/blob/3bd9b7a77a1e0e05ea479945d5cd8085f6981feb/addons/purchase_stock/models/stock.py#L103-L105

However, when cancelling a SO, we call the activity logger:
https://github.com/odoo/odoo/blob/846ad1f978fe36db892a9902bb4657c2079d1756/addons/sale_stock/models/sale_order.py#L184-L189
So, since the PO is not yet confirmed, we ignore it and do not log any
activity

[1] bda3225c6cc27bb2c2933eda3cc68c6f9708daf3

OPW-2820242

closes odoo/odoo#90553

X-original-commit: de485a39c9ee88aa31f9330a468ad31cc05842bc
Signed-off-by: Steve Van Essche <svs@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
This commit is contained in:
Adrien Widart
2022-05-05 16:22:52 +02:00
parent 3025f90e99
commit 63ef74bdee
4 changed files with 50 additions and 2 deletions
+2 -1
View File
@@ -101,7 +101,8 @@ class StockMove(models.Model):
self.write({'created_purchase_line_id': False})
def _get_upstream_documents_and_responsibles(self, visited):
if self.created_purchase_line_id and self.created_purchase_line_id.state not in ('draft', 'done', 'cancel'):
if self.created_purchase_line_id and self.created_purchase_line_id.state not in ('done', 'cancel') \
and (self.created_purchase_line_id.state != 'draft' or self._context.get('include_draft_documents')):
return [(self.created_purchase_line_id.order_id, self.created_purchase_line_id.order_id.user_id, visited)]
elif self.purchase_line_id and self.purchase_line_id.state not in ('done', 'cancel'):
return[(self.purchase_line_id.order_id, self.purchase_line_id.order_id.user_id, visited)]
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_sale_purchase_stock_flow
@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests.common import TransactionCase, Form
class TestSalePurchaseStockFlow(TransactionCase):
def test_cancel_so_with_draft_po(self):
"""
Sell a MTO+Buy product -> a PO is generated
Cancel the SO -> an activity should be added to the PO
"""
mto_route = self.env.ref('stock.route_warehouse0_mto')
buy_route = self.env.ref('purchase_stock.route_warehouse0_buy')
mto_route.active = True
vendor = self.env['res.partner'].create({
'name': 'Super Vendor'
})
product = self.env['product.product'].create({
'name': 'SuperProduct',
'type': 'product',
'route_ids': [(6, 0, (mto_route + buy_route).ids)],
'seller_ids': [(0, 0, {
'partner_id': vendor.id,
})],
})
so_form = Form(self.env['sale.order'])
so_form.partner_id = self.env.user.partner_id
with so_form.order_line.new() as line:
line.product_id = product
so = so_form.save()
so.action_confirm()
po = self.env['purchase.order'].search([('partner_id', '=', vendor.id)])
so.action_cancel()
self.assertTrue(po.activity_ids)
self.assertIn(so.name, po.activity_ids.note)
+1 -1
View File
@@ -191,7 +191,7 @@ class SaleOrder(models.Model):
for sale_order in self:
if sale_order.state == 'sale' and sale_order.order_line:
sale_order_lines_quantities = {order_line: (order_line.product_uom_qty, 0) for order_line in sale_order.order_line}
documents = self.env['stock.picking']._log_activity_get_documents(sale_order_lines_quantities, 'move_ids', 'UP')
documents = self.env['stock.picking'].with_context(include_draft_documents=True)._log_activity_get_documents(sale_order_lines_quantities, 'move_ids', 'UP')
self.picking_ids.filtered(lambda p: p.state != 'done').action_cancel()
if documents:
filtered_documents = {}