Skip to content

Commit

Permalink
[IMP] rma: allow return different product
Browse files Browse the repository at this point in the history
  • Loading branch information
sbejaoui committed Aug 29, 2024
1 parent 11fec64 commit b3b86fa
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 202 deletions.
107 changes: 28 additions & 79 deletions rma/models/rma.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,32 +328,14 @@ def _domain_location_id(self):
show_create_refund = fields.Boolean(
string="Show Create refund Button", compute="_compute_show_refund_replace"
)
# Replace fields, used when the delivery is created automatically
replace_warehouse_id = fields.Many2one(
"stock.warehouse",
help="Warehouse from which the replacement product will be shipped.",
compute="_compute_replace_warehouse_id",
store=True,
readonly=False,
)
replace_product_id = fields.Many2one(
return_product_id = fields.Many2one(
"product.product",
help="Product to be used as the replacement for the returned item.",
)
replace_product_uom_qty = fields.Float(
string="Replacement Quantity",
help="Quantity of the replacement product to be delivered.",
help="Product to be returned if it's different from the originally delivered "
"item.",
)
replace_product_uom = fields.Many2one(
"uom.uom",
string="Replacement UOM",
help="Unit of Measure for the replacement product.",
default=lambda self: self.env.ref("uom.product_uom_unit").id,
compute="_compute_replace_product_uom",
store=True,
readonly=False,
different_return_product = fields.Boolean(
related="operation_id.different_return_product"
)
show_replacement_fields = fields.Boolean(compute="_compute_show_replacement_fields")

@api.depends("company_id")
def _compute_replace_warehouse_id(self):
Expand All @@ -363,20 +345,6 @@ def _compute_replace_warehouse_id(self):
[("company_id", "=", rec.company_id.id)], limit=1
)

@api.depends(
"operation_id.action_create_delivery", "operation_id.different_return_product"
)
def _compute_show_replacement_fields(self):
for rec in self:
rec.show_replacement_fields = (
rec.operation_id.different_return_product
and rec.operation_id.action_create_delivery
in (
"automatic_on_confirm",
"automatic_after_receipt",
)
)

@api.depends("operation_id.action_create_receipt", "state", "reception_move_id")
def _compute_show_create_receipt(self):
for rec in self:
Expand Down Expand Up @@ -653,14 +621,6 @@ def _compute_product_uom(self):
else:
record.product_uom = False

@api.depends("replace_product_id")
def _compute_replace_product_uom(self):
for record in self:
if record.product_id:
record.replace_product_uom = record.replace_product_id.uom_id
else:
record.replace_product_uom = False

@api.depends("picking_id", "product_id", "company_id")
def _compute_location_id(self):
for record in self:
Expand Down Expand Up @@ -843,13 +803,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 Expand Up @@ -877,36 +848,6 @@ def action_create_receipt(self):
"res_id": self.reception_move_id.picking_id.id,
}

def _create_replace_or_return(self):
"""create a replace or return order based on the operation seetings"""
self.ensure_one()
if self.operation_id.different_return_product:
if (
not self.replace_product_id
or not self.replace_product_uom_qty
or not self.replace_warehouse_id
):
raise ValidationError(
_(
"The selected operation provides for the replacement with a "
"different product. Please complete the replacement "
"information."
)
)
self.create_replace(
fields.Datetime.now(),
self.replace_warehouse_id,
self.replace_product_id,
self.replace_product_uom_qty,
self.replace_product_uom,
)
else:
self.with_context(
rma_return_grouping=self.env.company.rma_return_grouping
).create_return(
fields.Datetime.now(), self.product_uom_qty, self.product_uom
)

def action_confirm(self):
"""Invoked when 'Confirm' button in rma form view is clicked."""
self._ensure_required_fields()
Expand All @@ -921,7 +862,11 @@ def action_confirm(self):
if rec.operation_id.action_create_receipt == "automatic_on_confirm":
rec._create_receipt()
if rec.operation_id.action_create_delivery == "automatic_on_confirm":
rec._create_replace_or_return()
rec.with_context(
rma_return_grouping=rec.env.company.rma_return_grouping
).create_return(
fields.Datetime.now(), rec.product_uom_qty, rec.product_uom
)
if rec.operation_id.action_create_refund == "automatic_on_confirm":
rec.action_refund()

Expand Down Expand Up @@ -1562,7 +1507,11 @@ def update_received_state_on_reception(self):
self._send_receipt_confirmation_email()
for rec in self:
if rec.operation_id.action_create_delivery == "automatic_after_receipt":
rec._create_replace_or_return()
rec.with_context(
rma_return_grouping=rec.env.company.rma_return_grouping
).create_return(
fields.Datetime.now(), rec.product_uom_qty, rec.product_uom
)
if rec.operation_id.action_create_refund == "automatic_after_receipt":
rec.action_refund()

Expand Down
12 changes: 5 additions & 7 deletions rma/tests/test_rma_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,13 @@ def test_07(self):
ValidationError, msg="Complete the replacement information"
):
rma.action_confirm()
self.assertTrue(rma.show_replacement_fields)
rma.replace_product_id = self.product_product.create(
{"name": "replace Product test 1", "type": "product"}
rma.return_product_id = self.product_product.create(
{"name": "return Product test 1", "type": "product"}
)
rma.replace_product_uom_qty = 1
rma.action_confirm()
self.assertEqual(rma.delivery_move_ids.product_id, rma.replace_product_id)
self.assertEqual(rma.delivery_move_ids.product_uom_qty, 1)
self.assertEqual(rma.state, "waiting_replacement")
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
13 changes: 7 additions & 6 deletions rma/views/rma_operation.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,20 @@
<group>
<field name="action_create_receipt" />

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

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

</group>
<group />

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

Expand Down
38 changes: 6 additions & 32 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 @@ -344,37 +349,6 @@
<field name="description" widget="html" colspan="4" />
</group>
</page>
<page
string="Replacement Product"
attrs="{'invisible': [('show_replacement_fields', '=', False)]}"
>
<group>
<field
name="replace_warehouse_id"
attrs="{'readonly': [('state', '!=', 'draft')], 'required': [('show_replacement_fields', '!=', False)]}"
/>
<field
name="replace_product_id"
attrs="{'readonly': [('state', '!=', 'draft')], 'required': [('show_replacement_fields', '!=', False)]}"
/>
<label
for="product_uom_qty"
attrs="{'readonly': [('state', '!=', 'draft')]}"
/>
<div class="o_row">
<field
name="replace_product_uom_qty"
attrs="{'readonly': [('state', '!=', 'draft')], 'required': [('show_replacement_fields', '!=', False)]}"
force_save="1"
/>
<field
name="replace_product_uom"
groups="uom.group_uom"
attrs="{'readonly': [('state', '!=', 'draft')], 'required': [('show_replacement_fields', '!=', False)]}"
force_save="1"
/></div>
</group>
</page>
</notebook>
<field name="sent" invisible="1" />
<field name="reception_move_id" invisible="1" />
Expand All @@ -383,7 +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="show_replacement_fields" 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
9 changes: 9 additions & 0 deletions rma/wizard/stock_picking_return.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ class ReturnPickingLine(models.TransientModel):
store=True,
readonly=False,
)
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="rma_operation_id.different_return_product"
)

@api.depends("wizard_id.rma_operation_id")
def _compute_rma_operation_id(self):
Expand All @@ -34,6 +42,7 @@ def _prepare_rma_vals(self):
"product_uom": self.product_id.uom_id.id,
"location_id": self.wizard_id.location_id.id or self.move_id.location_id.id,
"operation_id": self.rma_operation_id.id,
"return_product_id": self.return_product_id.id,
}


Expand Down
5 changes: 5 additions & 0 deletions rma/wizard/stock_picking_return_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
name="rma_operation_id"
attrs="{'column_invisible': [('parent.create_rma', '=', False)], 'required': [('parent.create_rma', '=', True), ('quantity', '>', 0)]}"
/>
<field
name="return_product_id"
attrs="{'column_invisible': [('parent.create_rma', '=', False)], 'invisible': [('different_return_product', '=', False)], 'required': [('different_return_product', '=', True)]}"
/>
<field name="different_return_product" invisible="1" />
</xpath>
<field name="product_return_moves" position="before">
<group name="group_rma">
Expand Down
26 changes: 25 additions & 1 deletion 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 @@ -248,8 +249,31 @@ def test_no_manual_refund_quantity_impact(self):
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()
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)
Loading

0 comments on commit b3b86fa

Please sign in to comment.