Skip to content

Commit

Permalink
[IMP] rma: allow standard refund
Browse files Browse the repository at this point in the history
  • Loading branch information
sbejaoui committed Aug 29, 2024
1 parent 4d23c6e commit e912c52
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 3 deletions.
24 changes: 22 additions & 2 deletions rma/models/rma.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,14 @@ def _domain_location_id(self):
show_create_refund = fields.Boolean(
string="Show Create refund Button", compute="_compute_show_refund_replace"
)
return_product_id = fields.Many2one(
"product.product",
help="Product to be returned if it's different from the originally delivered "
"item.",
)
different_return_product = fields.Boolean(
related="operation_id.different_return_product"
)

@api.depends("operation_id.action_create_receipt", "state", "reception_move_id")
def _compute_show_create_receipt(self):
Expand Down Expand Up @@ -774,6 +782,7 @@ def _prepare_reception_procurement_vals(self, group=None):
vals = self._prepare_common_procurement_vals(group=group)
vals["route_ids"] = self.warehouse_id.rma_in_route_id
vals["rma_receiver_ids"] = [(6, 0, self.ids)]
vals["to_refund"] = self.operation_id.action_create_refund == "update_quantity"
if self.move_id:
vals["origin_returned_move_id"] = self.move_id.id
return vals
Expand All @@ -787,13 +796,24 @@ def _prepare_reception_procurements(self):
group = rma.procurement_group_id
if not group:
group = group_model.create(rma._prepare_procurement_group_vals())
product = self.product_id
if self.different_return_product:
if not self.return_product_id:
raise ValidationError(
_(
"The selected operation requires a return product different"
" from the originally delivered item. Please select the "
"product to return."
)
)
product = self.return_product_id
procurements.append(
group_model.Procurement(
rma.product_id,
product,
rma.product_uom_qty,
rma.product_uom,
rma.location_id,
rma.product_id.display_name,
product.display_name,
group.name,
rma.company_id,
rma._prepare_reception_procurement_vals(group),
Expand Down
5 changes: 5 additions & 0 deletions rma/models/rma_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ class RmaOperation(models.Model):
default="automatic_on_confirm",
help="Define how the receipt action should be handled.",
)
different_return_product = fields.Boolean(
help="If checked, allows the return of a product different from the one "
"originally ordered. Used if the delivery is created automatically",
)
action_create_delivery = fields.Selection(
[
("manual_on_confirm", "Manually on Confirm"),
Expand All @@ -36,6 +40,7 @@ class RmaOperation(models.Model):
("automatic_on_confirm", "Automatically on Confirm"),
("manual_after_receipt", "Manually After Receipt"),
("automatic_after_receipt", "Automatically After Receipt"),
("update_quantity", "Update Quantities"),
],
string="Refund Action",
default="manual_after_receipt",
Expand Down
54 changes: 54 additions & 0 deletions rma/tests/test_rma_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,13 @@ def test_07(self):
ValidationError, msg="Complete the replacement information"
):
rma.action_confirm()
rma.return_product_id = self.product_product.create(
{"name": "return Product test 1", "type": "product"}
)
rma.action_confirm()
self.assertEqual(rma.delivery_move_ids.product_id, rma.product_id)
self.assertEqual(rma.reception_move_id.product_id, rma.return_product_id)
self.assertEqual(rma.state, "waiting_return")

def test_08(self):
"""test refund, manually after confirm"""
Expand Down Expand Up @@ -233,3 +239,51 @@ def test_13(self):
rma.reception_move_id.picking_id._action_done()
self.assertEqual(rma.state, "received")
self.assertFalse(rma.delivery_move_ids)

def test_14(self):
"""if the refund action is not ment to update quantity, return picking line
to_refund field should be False"""
self.operation.action_create_refund = "manual_after_receipt"
origin_delivery = self._create_delivery()
stock_return_picking_form = Form(
self.env["stock.return.picking"].with_context(
active_ids=origin_delivery.ids,
active_id=origin_delivery.id,
active_model="stock.picking",
)
)
stock_return_picking_form.create_rma = True
stock_return_picking_form.rma_operation_id = self.operation
return_wizard = stock_return_picking_form.save()
return_line = return_wizard.product_return_moves.filtered(
lambda m, p=self.product: m.product_id == p
)
self.assertEqual(return_line.rma_operation_id, self.operation)
picking_action = return_wizard.create_returns()
reception = self.env["stock.picking"].browse(picking_action["res_id"])
move = reception.move_ids.filtered(lambda m, p=self.product: m.product_id == p)
self.assertFalse(move.to_refund)

def test_15(self):
"""if the refund action is ment to update quantity, return picking line
to_refund field should be True"""
self.operation.action_create_refund = "update_quantity"
origin_delivery = self._create_delivery()
stock_return_picking_form = Form(
self.env["stock.return.picking"].with_context(
active_ids=origin_delivery.ids,
active_id=origin_delivery.id,
active_model="stock.picking",
)
)
stock_return_picking_form.create_rma = True
stock_return_picking_form.rma_operation_id = self.operation
return_wizard = stock_return_picking_form.save()
return_line = return_wizard.product_return_moves.filtered(
lambda m, p=self.product: m.product_id == p
)
self.assertEqual(return_line.rma_operation_id, self.operation)
picking_action = return_wizard.create_returns()
reception = self.env["stock.picking"].browse(picking_action["res_id"])
move = reception.move_ids.filtered(lambda m, p=self.product: m.product_id == p)
self.assertTrue(move.to_refund)
9 changes: 8 additions & 1 deletion rma/views/rma_operation.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@
<field name="action_create_receipt" />

</group>
<group />
<group>
<field
name="different_return_product"
widget="boolean_toggle"
attrs="{'invisible': [('action_create_receipt', '=', False)]}"
/>
</group>
<group>
<field name="action_create_delivery" />

</group>
<group />

<group>
<field name="action_create_refund" />

Expand Down
6 changes: 6 additions & 0 deletions rma/views/rma_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@
force_save="1"
attrs="{'readonly': ['|', ('picking_id', '!=', False), ('state', '!=', 'draft')]}"
/>
<field
name="return_product_id"
force_save="1"
attrs="{'readonly': ['|', ('picking_id', '!=', False), ('state', '!=', 'draft')], 'invisible': [('different_return_product', '=', False)], 'required': [('different_return_product', '=', True)]}"
/>
<field name="uom_category_id" invisible="1" />
<label for="product_uom_qty" />
<div class="o_row">
Expand Down Expand Up @@ -352,6 +357,7 @@
<field name="show_create_refund" invisible="1" />
<field name="show_create_return" invisible="1" />
<field name="show_create_replace" invisible="1" />
<field name="different_return_product" invisible="1" />
<field name="can_be_split" invisible="1" />
<field name="can_be_locked" invisible="1" />
<field name="can_be_finished" invisible="1" />
Expand Down
7 changes: 7 additions & 0 deletions rma_sale/models/rma.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,10 @@ def _prepare_delivery_procurements(self, scheduled_date=None, qty=None, uom=None
return super()._prepare_delivery_procurements(
scheduled_date=scheduled_date, qty=qty, uom=uom
)

def _prepare_reception_procurement_vals(self, group=None):
"""This method is used only for reception and a specific RMA IN route."""
vals = super()._prepare_reception_procurement_vals(group=group)
if self.move_id and self.move_id.sale_line_id:
vals["sale_line_id"] = self.move_id.sale_line_id.id
return vals
55 changes: 55 additions & 0 deletions rma_sale/tests/test_rma_sale.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Copyright 2023 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo.exceptions import ValidationError
from odoo.tests import Form, TransactionCase
from odoo.tests.common import users

Expand Down Expand Up @@ -222,3 +223,57 @@ def test_report_rma(self):
res = str(res[0])
self.assertRegex(res, self.sale_order.name)
self.assertRegex(res, operation.name)

def test_manual_refund_no_quantity_impact(self):
"""If the operation is meant for a manual refund, the delivered quantity
should not be updated."""
self.operation.action_create_refund = "manual_after_receipt"
order = self.sale_order
order_line = order.order_line
self.assertEqual(order_line.qty_delivered, 5)
wizard = self._rma_sale_wizard(order)
rma = self.env["rma"].browse(wizard.create_and_open_rma()["res_id"])
self.assertEqual(rma.reception_move_id.sale_line_id, order_line)
rma.action_confirm()
rma.reception_move_id.quantity_done = rma.product_uom_qty
rma.reception_move_id.picking_id._action_done()
self.assertEqual(order.order_line.qty_delivered, 5)

def test_no_manual_refund_quantity_impact(self):
"""If the operation is meant for a manual refund, the delivered quantity
should not be updated."""
self.operation.action_create_refund = "update_quantity"
order = self.sale_order
order_line = order.order_line
self.assertEqual(order_line.qty_delivered, 5)
wizard = self._rma_sale_wizard(order)
rma = self.env["rma"].browse(wizard.create_and_open_rma()["res_id"])
self.assertEqual(rma.reception_move_id.sale_line_id, order_line)
self.assertFalse(rma.can_be_refunded)
rma.reception_move_id.quantity_done = rma.product_uom_qty
rma.reception_move_id.picking_id._action_done()
self.assertEqual(order.order_line.qty_delivered, 0)

def test_return_different_product(self):
self.operation.action_create_delivery = False
self.operation.different_return_product = True
self.operation.action_create_refund = "update_quantity"
order = self.sale_order
order_line = order.order_line
self.assertEqual(order_line.qty_delivered, 5)
wizard = self._rma_sale_wizard(order)
with self.assertRaises(
ValidationError, msg="Complete the replacement information"
):
rma = self.env["rma"].browse(wizard.create_and_open_rma()["res_id"])
return_product = self.product_product.create(
{"name": "return Product test 1", "type": "product"}
)
wizard.line_ids.return_product_id = return_product
rma = self.env["rma"].browse(wizard.create_and_open_rma()["res_id"])
self.assertEqual(rma.reception_move_id.sale_line_id, order_line)
self.assertEqual(rma.reception_move_id.product_id, return_product)
self.assertFalse(rma.can_be_refunded)
rma.reception_move_id.quantity_done = rma.product_uom_qty
rma.reception_move_id.picking_id._action_done()
self.assertEqual(order.order_line.qty_delivered, 5)
9 changes: 9 additions & 0 deletions rma_sale/wizard/sale_order_rma_wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ class SaleOrderLineRmaWizard(models.TransientModel):
comodel_name="sale.order.line",
)
description = fields.Text()
return_product_id = fields.Many2one(
"product.product",
help="Product to be returned if it's different from the originally delivered "
"item.",
)
different_return_product = fields.Boolean(
related="operation_id.different_return_product"
)

@api.depends("wizard_id.operation_id")
def _compute_operation_id(self):
Expand Down Expand Up @@ -223,4 +231,5 @@ def _prepare_rma_values(self):
"product_uom": self.uom_id.id,
"operation_id": self.operation_id.id,
"description": description,
"return_product_id": self.return_product_id.id,
}
5 changes: 5 additions & 0 deletions rma_sale/wizard/sale_order_rma_wizard_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@
name="operation_id"
attrs="{'required': [('quantity', '>', 0)]}"
/>
<field
name="return_product_id"
attrs="{'invisible': [('different_return_product', '=', False)], 'required': [('different_return_product', '=', True)]}"
/>
<field name="different_return_product" invisible="1" />
</tree>
</field>
</group>
Expand Down

0 comments on commit e912c52

Please sign in to comment.