diff --git a/sell_only_by_packaging/README.rst b/sell_only_by_packaging/README.rst index 3c4506b1872..e76fe7009e7 100644 --- a/sell_only_by_packaging/README.rst +++ b/sell_only_by_packaging/README.rst @@ -34,11 +34,15 @@ sale orders. The creation/update of sale order line will be blocked (by constraints) if the data on the sale.order.line does not fit with the configuration of the product's packagings. -It's also possible to force the quantity to sell during creation/modification of the sale order line +It's also possible to force the quantity to sell/return during creation/modification of the sale order line if the "Force sale quantity" is ticked on the packaging and the "Sell only by packaging" is ticked on product. -For example, if your packaging is set to sell by 5 units and the employee fill -the quantity with 3, the quantity will be automatically replaced by 5 (it always rounds up). +For example, +- To sell packaging (fill positive product quantities), if your packaging is set to sell by 5 units and the employee fill +the quantity with 3, the quantity will be automatically replaced by 5 (it always rounds up to the nearest multiple of the packaging quantity). + +- To return packaging (fill negative product quantities), if your packaging is set with -5 units and the employee fill +the quantity with -3, the quantity will be automatically replaced by -5 (it always rounds down to the nearest multiple of the packaging quantity). .. IMPORTANT:: This is an alpha version, the data model and design can change at any time without warning. diff --git a/sell_only_by_packaging/models/product_product.py b/sell_only_by_packaging/models/product_product.py index 2a3474607b7..bf574e28f2c 100644 --- a/sell_only_by_packaging/models/product_product.py +++ b/sell_only_by_packaging/models/product_product.py @@ -52,9 +52,20 @@ def _convert_packaging_qty(self, qty, uom, packaging): and float_compare( qty / q, float_round(qty / q, precision_rounding=1.0), - precision_rounding=0.001, + precision_rounding=uom.rounding, ) != 0 ): - qty = qty - (qty % q) + q + forced_qty = qty - (qty % q) + q + # Support negative rounding + if ( + float_compare( + qty, + 0.0, + precision_rounding=uom.rounding, + ) + < 0 + ): + forced_qty -= q + return forced_qty return qty diff --git a/sell_only_by_packaging/readme/DESCRIPTION.rst b/sell_only_by_packaging/readme/DESCRIPTION.rst index e3c254218a6..317b24867fa 100644 --- a/sell_only_by_packaging/readme/DESCRIPTION.rst +++ b/sell_only_by_packaging/readme/DESCRIPTION.rst @@ -4,8 +4,12 @@ sale orders. The creation/update of sale order line will be blocked (by constraints) if the data on the sale.order.line does not fit with the configuration of the product's packagings. -It's also possible to force the quantity to sell during creation/modification of the sale order line +It's also possible to force the quantity to sell/return during creation/modification of the sale order line if the "Force sale quantity" is ticked on the packaging and the "Sell only by packaging" is ticked on product. -For example, if your packaging is set to sell by 5 units and the employee fill -the quantity with 3, the quantity will be automatically replaced by 5 (it always rounds up). +For example, +- To sell packaging (fill positive product quantities), if your packaging is set to sell by 5 units and the employee fill +the quantity with 3, the quantity will be automatically replaced by 5 (it always rounds up to the nearest multiple of the packaging quantity). + +- To return packaging (fill negative product quantities), if your packaging is set with -5 units and the employee fill +the quantity with -3, the quantity will be automatically replaced by -5 (it always rounds down to the nearest multiple of the packaging quantity). diff --git a/sell_only_by_packaging/tests/test_sale_only_by_packaging.py b/sell_only_by_packaging/tests/test_sale_only_by_packaging.py index 9b78426af62..63fc1cf96f1 100644 --- a/sell_only_by_packaging/tests/test_sale_only_by_packaging.py +++ b/sell_only_by_packaging/tests/test_sale_only_by_packaging.py @@ -89,6 +89,31 @@ def test_convert_packaging_qty(self): self.assertAlmostEqual( so_line.product_uom_qty, 220, places=self.precision ) + # Check with negative quantity + so_line.product_uom_qty = -52 + self.assertAlmostEqual( + so_line.product_uom_qty, -60, places=self.precision + ) + so_line.product_uom_qty = -40 + self.assertAlmostEqual( + so_line.product_uom_qty, -40, places=self.precision + ) + so_line.product_uom_qty = -38 + self.assertAlmostEqual( + so_line.product_uom_qty, -40, places=self.precision + ) + so_line.product_uom_qty = -22 + self.assertAlmostEqual( + so_line.product_uom_qty, -40, places=self.precision + ) + so_line.product_uom_qty = -72 + self.assertAlmostEqual( + so_line.product_uom_qty, -80, places=self.precision + ) + so_line.product_uom_qty = -209.98 + self.assertAlmostEqual( + so_line.product_uom_qty, -220, places=self.precision + ) def test_onchange_qty_is_not_pack_multiple(self): """Check package when qantity is not a multiple of package quantity.