Skip to content

Commit

Permalink
[FIX] purchase_sale_inter_company: sync confirmed unlocked purchase u…
Browse files Browse the repository at this point in the history
…pdates

When the purchase user updates the PO after the SO is generated and
always if both are confirmed and unlocked, we sync the new lines to update the demand.

TT46773
  • Loading branch information
chienandalu authored and ntsirintanis committed Aug 27, 2024
1 parent bbb698a commit ff8af96
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 28 deletions.
1 change: 1 addition & 0 deletions purchase_sale_inter_company/static/description/index.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
Expand Down
40 changes: 12 additions & 28 deletions purchase_sale_stock_inter_company/models/stock_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,19 @@ def _action_done_intercompany_actions(self, purchase):
== ic_pick
).mapped("move_line_ids")
)
if len(move_lines) != len(po_move_lines):
note = (
if not len(move_lines) == len(po_move_lines):
note = _(
"Mismatch between move lines with the "
"corresponding PO %(purchase)s for assigning "
"quantities and lots from %(picking)s for product %(product)s"
) % {
"purchase": purchase.name,
"picking": pick.name,
"product": move.product_id.name,
}
"corresponding PO %s for assigning "
"quantities and lots from %s for product %s"
) % (purchase.name, pick.name, move.product_id.name)
# Configurable parameter so we don't lock the picking validation
if (
not self.env["ir.config_parameter"]
.sudo()
.get_param("purchase_sale_inter_company.soft_picking_mismatch")
):
raise UserError(note)
self.activity_schedule(
"mail.mail_activity_data_warning",
fields.Date.today(),
Expand Down Expand Up @@ -123,25 +126,6 @@ def button_validate(self):
)
return res

@api.model
def _prepare_picking_line_data(self, src_picking, dest_picking):
self.ensure_one()
if self.check_all_done(src_picking):
for line in src_picking.sudo().move_ids_without_package:
line.write({"quantity_done": line.reserved_availability})
for src_line in src_picking.sudo().move_ids_without_package:
if (
src_line.product_id
in dest_picking.sudo().move_ids_without_package.mapped("product_id")
and src_line.quantity_done > 0
):
dest_move = dest_picking.sudo().move_ids_without_package.filtered(
lambda m: m.product_id == src_line.product_id
)
dest_move.write(
{"quantity_done": dest_move.quantity_done + src_line.quantity_done}
)

def _sync_receipt_with_delivery(self, dest_company, sale_order):
self.ensure_one()
intercompany_user = dest_company.intercompany_sale_user_id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
# Copyright 2018-2019 Tecnativa - Carlos Dauden
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import re

from odoo.tests.common import Form

from odoo.addons.purchase_sale_inter_company.tests.test_inter_company_purchase_sale import (
TestPurchaseSaleInterCompany,
Expand Down Expand Up @@ -54,6 +56,12 @@ def setUpClass(cls):
)
cls.warehouse_d = cls._create_warehouse("CB-WD", cls.company_b)
cls.company_b.warehouse_id = cls.warehouse_c
cls.consumable_product_2 = cls.env["product.product"].create(
{
"name": "Consumable Product 2",
"type": "consu",
}
)
cls.stockable_product_serial = cls.env["product.product"].create(
{
"name": "Stockable Product Tracked by Serial",
Expand Down Expand Up @@ -253,3 +261,82 @@ def test_sync_picking_lot(self):
po_lots,
msg="Serial 333 already existed, a new one shouldn't have been created",
)

def test_update_open_sale_order(self):
"""
When the purchase user request extra product, the sale order gets synched if
it's open.
"""
purchase = self._create_purchase_order(
self.partner_company_b, self.consumable_product
)
purchase.picking_type_id = self.warehouse_a.in_type_id
sale = self._approve_po(purchase)
sale.action_confirm()
# Now we add an extra product to the PO and it will show up in the SO
po_form = Form(purchase)
with po_form.order_line.new() as line:
line.product_id = self.consumable_product_2
line.product_qty = 6
po_form.save()
# It's synched and the values match
synched_order_line = sale.order_line.filtered(
lambda x: x.product_id == self.consumable_product_2
)
self.assertTrue(
bool(synched_order_line),
"The line should have been created in the sale order",
)
self.assertEqual(
synched_order_line.product_uom_qty,
6,
"The quantity should be equal to the one set in the purchase order",
)
# Also the moves match as well
so_picking_id = sale.picking_ids
synched_move = so_picking_id.move_lines.filtered(
lambda x: x.product_id == self.consumable_product_2
)
self.assertTrue(
bool(synched_move),
"The move should have been created in the delivery order",
)
self.assertEqual(
synched_move.product_uom_qty,
6,
"The quantity should be equal to the one set in the purchase order",
)
# The quantity is synched as well
purchase_line = purchase.order_line.filtered(
lambda x: x.product_id == self.consumable_product_2
).sudo()
purchase_line.product_qty = 8
self.assertEqual(
synched_order_line.product_uom_qty,
8,
"The quantity should be equal to the one set in the purchase order",
)
self.assertEqual(
synched_move.product_uom_qty,
8,
"The quantity should synched to the one set in the purchase order",
)
# Let's decrease the quantity
purchase_line.product_qty = 3
self.assertEqual(
synched_order_line.product_uom_qty,
3,
"The quantity should decrease as it was in the purchase order",
)
self.assertEqual(
synched_move.product_uom_qty,
8,
"The quantity should remain as it was as it can't be decreased from the SO",
)
# A warning activity is scheduled in the picking
self.assertRegex(
so_picking_id.activity_ids.note,
re.compile(
"3.0 Units of Consumable Product 2.+instead of 8.0 Units", re.DOTALL
),
)

0 comments on commit ff8af96

Please sign in to comment.