Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0][IMP] rma_sale: Display the allowed quantity to return in the RMA wizard #407

Open
wants to merge 1 commit into
base: 16.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions rma_sale/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ Contributors

* Chafique Delli <[email protected]>
* Giovanni Serra - Ooops <[email protected]>
* Souheil Bejaoui - ACSONE SA/NV <[email protected]>
* Jacques-Etienne Baudoux - BCIM <[email protected]>

Maintainers
~~~~~~~~~~~
Expand Down
4 changes: 4 additions & 0 deletions rma_sale/controllers/sale_portal.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def request_rma(self, order_id, access_token=None, **post):
except (AccessError, MissingError):
return request.redirect("/my")
order_obj = request.env["sale.order"]
order_line_obj = request.env["sale.order.line"]
wizard_obj = request.env["sale.order.rma.wizard"].sudo()
wizard_line_field_types = {
f: d["type"] for f, d in wizard_obj.line_ids.fields_get().items()
Expand All @@ -48,6 +49,9 @@ def request_rma(self, order_id, access_token=None, **post):
# description values
except ValueError:
custom_vals.update({name: value})
for vals in mapped_vals.values():
sale_line = order_line_obj.browse(vals.get("sale_line_id")).sudo()
vals["allowed_quantity"] = sale_line.qty_delivered
# If no operation is filled, no RMA will be created
line_vals = [
(0, 0, vals) for vals in mapped_vals.values() if vals.get("operation_id")
Expand Down
1 change: 1 addition & 0 deletions rma_sale/models/sale.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def _prepare_rma_wizard_line_vals(self, data):
return {
"product_id": data["product"].id,
"quantity": data["quantity"],
"allowed_quantity": data["quantity"],
"sale_line_id": data["sale_line_id"].id,
"uom_id": data["uom"].id,
"picking_id": data["picking"] and data["picking"].id,
Expand Down
2 changes: 2 additions & 0 deletions rma_sale/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@

* Chafique Delli <[email protected]>
* Giovanni Serra - Ooops <[email protected]>
* Souheil Bejaoui - ACSONE SA/NV <[email protected]>
* Jacques-Etienne Baudoux - BCIM <[email protected]>
2 changes: 2 additions & 0 deletions rma_sale/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@ <h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
</li>
<li>Chafique Delli &lt;<a class="reference external" href="mailto:chafique.delli&#64;akretion.com">chafique.delli&#64;akretion.com</a>&gt;</li>
<li>Giovanni Serra - Ooops &lt;<a class="reference external" href="mailto:giovanni&#64;ooops404.com">giovanni&#64;ooops404.com</a>&gt;</li>
<li>Souheil Bejaoui - ACSONE SA/NV &lt;<a class="reference external" href="mailto:souheil.bejaoui&#64;acsone.eu">souheil.bejaoui&#64;acsone.eu</a>&gt;</li>
<li>Jacques-Etienne Baudoux - BCIM &lt;<a class="reference external" href="mailto:je&#64;bcim.be">je&#64;bcim.be</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
Expand Down
1 change: 1 addition & 0 deletions rma_sale/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@

from . import test_rma_sale
from . import test_rma_sale_portal
from . import test_rma_sale_allowed_qty
1 change: 1 addition & 0 deletions rma_sale/tests/test_rma_sale.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ def test_create_rma_from_so_portal_user(self):
"product_id": order.order_line.product_id.id,
"sale_line_id": order.order_line.id,
"quantity": order.order_line.product_uom_qty,
"allowed_quantity": order.order_line.qty_delivered,
"uom_id": order.order_line.product_uom.id,
"picking_id": order.picking_ids[0].id,
"operation_id": operation.id,
Expand Down
110 changes: 110 additions & 0 deletions rma_sale/tests/test_rma_sale_allowed_qty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Copyright 2024 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import Command
from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase


class TestRmaSaleQuantityAllowed(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.warehouse = cls.env.ref("stock.warehouse0")
cls.loc_stock = cls.warehouse.lot_stock_id
cls.partner1 = cls.env["res.partner"].create({"name": "Partner"})
cls.p1 = cls.env["product.product"].create(
{"name": "Unittest P1", "type": "product"}
)
cls.so = cls.env["sale.order"].create(
{
"partner_id": cls.partner1.id,
"order_line": [
Command.create(
{
"name": cls.p1.name,
"product_id": cls.p1.id,
"product_uom_qty": 5,
"price_unit": 50,
},
)
],
}
)
cls.env["stock.quant"].with_context(inventory_mode=True).create(
{
"product_id": cls.p1.id,
"inventory_quantity": 10,
"location_id": cls.loc_stock.id,
}
)._apply_inventory()
cls.so.action_confirm()
cls.picking = cls.so.picking_ids[0]

def _get_rma_wizard(self):
action = self.so.action_create_rma()
return self.env[action.get("res_model")].browse(action.get("res_id"))

def _deliver(self, qty):
self.picking.move_line_ids.qty_done = qty
self.picking._action_done()
self.assertEqual(self.picking.state, "done")
self.assertEqual(self.so.order_line.qty_delivered, qty)

def test_1(self):
"""
Test rma wizard:
- fully deliver the so
- open rma wizard
expected:
- qty proposed: 5
- allowed qty 5
- qty 0 if is_return_all = False
"""
self._deliver(5)
wizard = self._get_rma_wizard()
self.assertEqual(len(wizard.line_ids), 1)
self.assertEqual(wizard.line_ids.quantity, 5)
self.assertEqual(wizard.line_ids.allowed_quantity, 5)
wizard.is_return_all = False
self.assertEqual(wizard.line_ids.quantity, 0)
wizard.is_return_all = True
self.assertEqual(wizard.line_ids.quantity, 5)

def test_2(self):
"""
Test rma wizard:
- partially deliver the so
- open rma wizard
expected:
- qty proposed: 3
- allowed qty 3
- qty 0 if is_return_all = False
"""
self._deliver(3)
wizard = self._get_rma_wizard()
self.assertEqual(len(wizard.line_ids), 1)
self.assertEqual(wizard.line_ids.quantity, 3)
self.assertEqual(wizard.line_ids.allowed_quantity, 3)
wizard.is_return_all = False
self.assertEqual(wizard.line_ids.quantity, 0)
wizard.is_return_all = True
self.assertEqual(wizard.line_ids.quantity, 3)

def test_3(self):
"""
Test rma wizard:
Try to return more than the allowed qty
"""
self._deliver(3)
wizard = self._get_rma_wizard()
self.assertEqual(len(wizard.line_ids), 1)
self.assertEqual(wizard.line_ids.quantity, 3)
self.assertEqual(wizard.line_ids.allowed_quantity, 3)
with self.assertRaises(
ValidationError, msg="You can't exceed the allowed quantity"
):
wizard.line_ids.quantity = 5
wizard.line_ids.quantity = 1
36 changes: 36 additions & 0 deletions rma_sale/wizard/sale_order_rma_wizard.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda
# Copyright 2022 Tecnativa - Víctor Martínez
# Copyright 2024 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import SUPERUSER_ID, _, api, fields, models
from odoo.exceptions import ValidationError
from odoo.tools.float_utils import float_compare


class SaleOrderRmaWizard(models.TransientModel):
Expand Down Expand Up @@ -50,6 +53,7 @@ def _domain_location_id(self):
custom_description = fields.Text(
help="Values coming from portal RMA request form custom fields",
)
is_return_all = fields.Boolean(string="Return All?", default=True)

def create_rma(self, from_portal=False):
self.ensure_one()
Expand Down Expand Up @@ -130,7 +134,11 @@ class SaleOrderLineRmaWizard(models.TransientModel):
quantity = fields.Float(
digits="Product Unit of Measure",
required=True,
compute="_compute_quantity",
store=True,
readonly=False,
)
allowed_quantity = fields.Float(digits="Product Unit of Measure", readonly=True)
uom_id = fields.Many2one(
comodel_name="uom.uom",
string="Unit of Measure",
Expand Down Expand Up @@ -158,6 +166,14 @@ class SaleOrderLineRmaWizard(models.TransientModel):
)
description = fields.Text()

@api.depends("wizard_id.is_return_all", "allowed_quantity")
def _compute_quantity(self):
for rec in self:
if not rec.wizard_id.is_return_all:
rec.quantity = 0
else:
rec.quantity = rec.allowed_quantity

@api.depends("wizard_id.operation_id")
def _compute_operation_id(self):
for rec in self:
Expand Down Expand Up @@ -200,6 +216,26 @@ def _compute_allowed_picking_ids(self):
lambda x: x.state == "done"
)

@api.constrains("quantity", "allowed_quantity")
def _check_quantity(self):
precision = self.env["decimal.precision"].precision_get(
"Product Unit of Measure"
)
for rec in self:
if (
float_compare(
rec.quantity, rec.allowed_quantity, precision_digits=precision
)
== 1
):
raise ValidationError(
_(
"You can't exceed the allowed quantity for returning product "
"%(product)s.",
product=rec.product_id.display_name,
)
)

def _prepare_rma_values(self):
self.ensure_one()
partner_shipping = (
Expand Down
2 changes: 2 additions & 0 deletions rma_sale/wizard/sale_order_rma_wizard_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
<field name="arch" type="xml">
<form>
<group>
<field name="is_return_all" widget="boolean_toggle" />
<field name="operation_id" />
<field name="line_ids" nolabel="1" colspan="2">
<tree editable="bottom">
<field name="order_id" invisible="1" />
<field name="allowed_product_ids" invisible="1" />
<field name="product_id" options="{'no_create': True}" />
<field name="quantity" />
<field name="allowed_quantity" />
<field name="uom_category_id" invisible="1" />
<field
name="uom_id"
Expand Down
3 changes: 1 addition & 2 deletions rma_sale_mrp/tests/test_rma_sale_mrp.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,8 @@ def test_create_rma_from_so(self):
# be 0 at this time
wizard = self._rma_sale_wizard(order)
self.assertEqual(wizard.line_ids.quantity, 0)
wizard.line_ids.quantity = 1
with self.assertRaises(ValidationError):
wizard.create_and_open_rma()
wizard.line_ids.quantity = 1

def test_report_rma(self):
wizard = self._rma_sale_wizard(self.sale_order)
Expand Down
Loading