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][ADD] rma_product_exchange #528

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
11 changes: 7 additions & 4 deletions rma/wizards/rma_make_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ def _get_procurement_data(self, item, group, qty, picking_type):
}
return procurement_data

@api.model
def _get_product(self, item):
return item.line_id.product_id

@api.model
def _create_procurement(self, item, picking_type):
errors = []
Expand All @@ -149,7 +153,7 @@ def _create_procurement(self, item, picking_type):
else:
qty = item.qty_to_deliver
values = self._get_procurement_data(item, group, qty, picking_type)
product = item.line_id.product_id
product = self._get_product(item)
if float_compare(qty, 0, product.uom_id.rounding) != 1:
raise ValidationError(
_(
Expand All @@ -162,16 +166,15 @@ def _create_procurement(self, item, picking_type):
procurements = []
try:
procurement = group.Procurement(
item.line_id.product_id,
product,
qty,
item.line_id.product_id.product_tmpl_id.uom_id,
product.product_tmpl_id.uom_id,
values.get("location_id"),
values.get("origin"),
values.get("origin"),
self.env.company,
values,
)

procurements.append(procurement)
# Trigger a route check with a mutable in the context that can be
# cleared after the first rule selection
Expand Down
34 changes: 34 additions & 0 deletions rma_product_exchange/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
:alt: License LGPL-3

====================
RMA Product Exchange
====================

This module allows you to:

#. to exchange one product for another in an RMA.

Usage
=====

Bug Tracker
===========

Bugs are tracked on `GitHub Issues
<https://github.com/Eficent/stock-rma/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.

Credits
=======

Contributors
------------

* Chafique DELLI <[email protected]>

Maintainer
----------

This module is maintained by Eficent
2 changes: 2 additions & 0 deletions rma_product_exchange/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import wizards
21 changes: 21 additions & 0 deletions rma_product_exchange/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2024 Akretion
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)

{
"name": "RMA Product Exchange",
"version": "16.0.1.0.0",
"license": "LGPL-3",
"category": "RMA",
"summary": "Manage RMA for product exchange",
"author": "Akretion, ForgeFlow",
"website": "https://github.com/ForgeFlow/stock-rma",
"depends": [
"rma",
],
"data": [
"views/rma_order_view.xml",
"views/rma_operation_view.xml",
"views/rma_order_line_view.xml",
],
"installable": True,
}
72 changes: 72 additions & 0 deletions rma_product_exchange/i18n/fr.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * rma_product_exchange
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-09-16 20:17+0000\n"
"PO-Revision-Date: 2024-09-16 20:17+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"

#. module: rma_product_exchange
#: model:ir.model.fields,help:rma_product_exchange.field_rma_operation__product_exchange
#: model:ir.model.fields,help:rma_product_exchange.field_rma_order_line__product_exchange
msgid "Check if you wish to authorize product exchange."
msgstr "Cochez si vous souhaitez autoriser l'échange de produit."

#. module: rma_product_exchange
#: model:ir.model.fields,field_description:rma_product_exchange.field_rma_order_line__new_product_id
msgid "New Product"
msgstr "Nouveau Produit"

#. module: rma_product_exchange
#: model:ir.model,name:rma_product_exchange.model_procurement_group
msgid "Procurement Group"
msgstr "Groupe d'approvisionnement"

#. module: rma_product_exchange
#: model:ir.model.fields,field_description:rma_product_exchange.field_rma_operation__product_exchange
#: model:ir.model.fields,field_description:rma_product_exchange.field_rma_order_line__product_exchange
msgid "Product Exchange"
msgstr "Echange de produit"

#. module: rma_product_exchange
#: model:ir.model,name:rma_product_exchange.model_rma_order_line
msgid "RMA"
msgstr ""

#. module: rma_product_exchange
#: model:ir.model,name:rma_product_exchange.model_rma_operation
msgid "RMA Operation"
msgstr "Opération RMA"

#. module: rma_product_exchange
#: model:ir.model.fields,help:rma_product_exchange.field_rma_order_line__new_product_id
msgid ""
"The new product selected will be shipped instead of the product initially "
"ordered."
msgstr ""
"Le nouveau produit sélectionné sera expédié à la place du produit initialement "
"commandé"
#. module: rma_product_exchange
#. odoo-python
#: code:addons/rma_product_exchange/models/rma_order_line.py:0
#, python-format
msgid ""
"The selected replacement product must have the same unit of measurement as "
"the initial product !"
msgstr ""
"Le produit de remplacement sélectionné doit avoir la même unité de mesure que "
"le produit initial !"

#. module: rma_product_exchange
#: model:ir.model,name:rma_product_exchange.model_rma_make_picking_wizard
msgid "Wizard to create Pickings from rma"
msgstr "Assistant pour créer des transferts à partir de rma"
2 changes: 2 additions & 0 deletions rma_product_exchange/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import rma_order_line
from . import rma_operation
11 changes: 11 additions & 0 deletions rma_product_exchange/models/rma_operation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright 2024 Akretion
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from odoo import fields, models


class RmaOperation(models.Model):
_inherit = "rma.operation"

product_exchange = fields.Boolean(
help="Check if you wish to authorize product exchange.", default=False
)
30 changes: 30 additions & 0 deletions rma_product_exchange/models/rma_order_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright 2024 Akretion
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError


class RmaOrderLine(models.Model):
_inherit = "rma.order.line"

new_product_id = fields.Many2one(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a help here to explain what will happen if the field is set ?
Explain that will impact the shipping

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@florian-dacosta , it's done.

comodel_name="product.product",
tracking=True,
help="The new product selected will be shipped "
"instead of the product initially ordered.",
)
product_exchange = fields.Boolean(related="operation_id.product_exchange")

@api.constrains("new_product_id")
def _check_new_product_id(self):
for record in self:
if (
record.new_product_id
and record.new_product_id.uom_id != record.product_id.uom_id
):
raise ValidationError(
_(
"The selected replacement product must "
"have the same unit of measurement as the initial product !"
)
)
1 change: 1 addition & 0 deletions rma_product_exchange/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_rma_product_exchange
28 changes: 28 additions & 0 deletions rma_product_exchange/tests/test_rma_product_exchange.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2024 Akretion
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)

from odoo.addons.rma.tests.test_rma import TestRma


class TestRmaProductExchange(TestRma):
@classmethod
def setUpClass(cls):
super().setUpClass()

def test_customer_rma_with_product_exchange(self):
self.rma_cust_replace_op_id.product_exchange = True
self.rma_customer_id.rma_line_ids.delivery_policy = "ordered"
self.rma_customer_id.rma_line_ids[0].new_product_id = self.product_id
self.rma_customer_id.rma_line_ids.action_rma_to_approve()
wizard = self.rma_make_picking.with_context(
**{
"active_ids": self.rma_customer_id.rma_line_ids.ids,
"active_model": "rma.order.line",
"picking_type": "outgoing",
"active_id": 1,
}
).create({})
wizard._create_picking()
res = self.rma_customer_id.action_view_out_shipments()
picking = self.env["stock.picking"].browse(res["res_id"])
self.assertEqual(picking.move_ids[0].product_id, self.product_id)
27 changes: 27 additions & 0 deletions rma_product_exchange/views/rma_operation_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>

<record id="rma_operation_tree" model="ir.ui.view">
<field name="model">rma.operation</field>
<field name="inherit_id" ref="rma.rma_operation_tree" />
<field name="arch" type="xml">
<field name="delivery_policy" position="after">
<field name="product_exchange" optional="show" />
</field>
</field>
</record>

<record id="rma_operation_form" model="ir.ui.view">
<field name="model">rma.operation</field>
<field name="inherit_id" ref="rma.rma_operation_form" />
<field name="arch" type="xml">
<xpath expr="//group[@name='policies']" position="inside">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be invisible if the delivery_policy is set to "no", because it is only used for delivery, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@florian-dacosta , it's fixed.

<field
name="product_exchange"
attrs="{'invisible':[('delivery_policy', '=', 'no')]}"
/>
</xpath>
</field>
</record>

</odoo>
21 changes: 21 additions & 0 deletions rma_product_exchange/views/rma_order_line_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>

<record id="view_rma_line_form" model="ir.ui.view">
<field name="model">rma.order.line</field>
<field name="inherit_id" ref="rma.view_rma_line_form" />
<field name="arch" type="xml">
<xpath
expr="//group[@name='product']/field[@name='product_id']"
position="after"
>
<field name="product_exchange" invisible="True" />
<field
name="new_product_id"
attrs="{'invisible':['|',('operation_id', '=', False),('product_exchange', '=', False)]}"
/>
</xpath>
</field>
</record>

</odoo>
19 changes: 19 additions & 0 deletions rma_product_exchange/views/rma_order_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_rma_form" model="ir.ui.view">
<field name="model">rma.order</field>
<field name="inherit_id" ref="rma.view_rma_form" />
<field name="arch" type="xml">
<xpath
expr="//field[@name='rma_line_ids']/tree/field[@name='product_id']"
position="after"
>
<field name="product_exchange" invisible="True" />
<field
name="new_product_id"
attrs="{'invisible':['|',('operation_id', '=', False),('product_exchange', '=', False)]}"
/>
</xpath>
</field>
</record>
</odoo>
1 change: 1 addition & 0 deletions rma_product_exchange/wizards/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import rma_make_picking
36 changes: 36 additions & 0 deletions rma_product_exchange/wizards/rma_make_picking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright (C) 2024 Akretion
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)

from odoo import api, models


class RmaMakePicking(models.TransientModel):
_inherit = "rma_make_picking.wizard"

@api.returns("rma.order.line")
def _prepare_item(self, line):
values = super()._prepare_item(line)
if (
self.env.context.get("picking_type") == "outgoing"
and line.product_exchange
and line.new_product_id
):
values["product_id"] = line.new_product_id.id
return values

@api.model
def _create_procurement(self, item, picking_type):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole override is useless for now, because rma_item context key is not used anywhere anymore, right ?
In if this the case, please, remove it!

if self.env.context.get("picking_type") == "outgoing":
self = self.with_context(rma_item=item)
return super()._create_procurement(item, picking_type)

@api.model
def _get_product(self, item):
product = super()._get_product(item)
if (
self.env.context.get("picking_type") == "outgoing"
and item.line_id.product_exchange
and item.line_id.new_product_id
):
product = item.line_id.new_product_id
return product
6 changes: 6 additions & 0 deletions setup/rma_product_exchange/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
Loading