Skip to content

Commit 75c42ab

Browse files
committed
Merge PR #450 into 18.0
Signed-off-by pedrobaeza
2 parents 896bc78 + de97b00 commit 75c42ab

45 files changed

Lines changed: 6874 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

rma_sale/README.rst

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
=============================================================
2+
Return Merchandise Authorization Management - Link with Sales
3+
=============================================================
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:0ace4968c86bee8d2caa4e6d41af6a02fa6258de8a826eecb3378fd4d68db1b8
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Production/Stable
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18+
:alt: License: AGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frma-lightgray.png?logo=github
20+
:target: https://github.com/OCA/rma/tree/18.0/rma_sale
21+
:alt: OCA/rma
22+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
23+
:target: https://translation.odoo-community.org/projects/rma-18-0/rma-18-0-rma_sale
24+
:alt: Translate me on Weblate
25+
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
26+
:target: https://runboat.odoo-community.org/builds?repo=OCA/rma&target_branch=18.0
27+
:alt: Try me on Runboat
28+
29+
|badge1| |badge2| |badge3| |badge4| |badge5|
30+
31+
This module allows you to link a sales order to an RMA. This can be done
32+
by creating an RMA from scratch and selecting the sales order, creating
33+
one or more RMAs from a sales order form view or from a sales order web
34+
portal page.
35+
36+
**Table of contents**
37+
38+
.. contents::
39+
:local:
40+
41+
Usage
42+
=====
43+
44+
To use this module, you need to:
45+
46+
1. Go to *RMA > Orders* and create a new RMA.
47+
2. Select a sales order to be linked to the RMA if you want.
48+
3. Now you can do the rest of the instructions described in the *readme*
49+
of the rma module.
50+
51+
If you want to create one or more RMAs from a sale order:
52+
53+
1. Go to *Sales > Orders > Orders*.
54+
2. Create a new sales order or select an existing one.
55+
3. If the sales order is in 'Sales Order' state you can see in the
56+
status bar a button labeled 'Create RMA', click it and a wizard will
57+
appear.
58+
4. Modify the data at your convenience and click on 'Accept' button.
59+
5. As many RMAs as lines with quantity greater than zero will be
60+
created. Those RMAs will be linked to the sales order.
61+
62+
The customer can also create RMAs from a sales order portal page:
63+
64+
1. Go to a confirmed sales order portal page.
65+
2. In the left sidebar you can see a button named 'Request RMAs'.
66+
3. By clicking on this button a popup will appear to allow you to define
67+
the quantity per product and delivery order line.
68+
4. Click on the 'Request RMAs' button and RMAs will be created linked to
69+
the sales order.
70+
71+
Single page RMA request:
72+
73+
1. Go to Sales > Configuration > Settings
74+
2. Check the 'Single page RMA request' box.
75+
3. On a sales order in the portal, clicking on 'Request RMAs' button
76+
will open a new page (not a popup).
77+
78+
Known issues / Roadmap
79+
======================
80+
81+
- When you try to request an RMA from a Sales Order in the portal, a
82+
popup appears and the inputs for the quantity doesn't allow decimal
83+
numbers. It would be good to have a component that allows that and at
84+
the same time keeps the constraint of not allowing a number greater
85+
than the order line product quantity.
86+
87+
Bug Tracker
88+
===========
89+
90+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/rma/issues>`_.
91+
In case of trouble, please check there if your issue has already been reported.
92+
If you spotted it first, help us to smash it by providing a detailed and welcomed
93+
`feedback <https://github.com/OCA/rma/issues/new?body=module:%20rma_sale%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
94+
95+
Do not contact contributors directly about support or help with technical issues.
96+
97+
Credits
98+
=======
99+
100+
Authors
101+
-------
102+
103+
* Tecnativa
104+
105+
Contributors
106+
------------
107+
108+
- `Tecnativa <https://www.tecnativa.com>`__:
109+
110+
- Ernesto Tejeda
111+
- Pedro M. Baeza
112+
- David Vidal
113+
- Víctor Martínez
114+
115+
- Chafique Delli <chafique.delli@akretion.com>
116+
- Giovanni Serra - Ooops <giovanni@ooops404.com>
117+
118+
Maintainers
119+
-----------
120+
121+
This module is maintained by the OCA.
122+
123+
.. image:: https://odoo-community.org/logo.png
124+
:alt: Odoo Community Association
125+
:target: https://odoo-community.org
126+
127+
OCA, or the Odoo Community Association, is a nonprofit organization whose
128+
mission is to support the collaborative development of Odoo features and
129+
promote its widespread use.
130+
131+
.. |maintainer-chienandalu| image:: https://github.com/chienandalu.png?size=40px
132+
:target: https://github.com/chienandalu
133+
:alt: chienandalu
134+
135+
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
136+
137+
|maintainer-chienandalu|
138+
139+
This module is part of the `OCA/rma <https://github.com/OCA/rma/tree/18.0/rma_sale>`_ project on GitHub.
140+
141+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

rma_sale/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
2+
3+
from . import controllers
4+
from . import models
5+
from . import wizard

rma_sale/__manifest__.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright 2020 Tecnativa - Ernesto Tejeda
2+
# Copyright 2022-2023 Tecnativa - Víctor Martínez
3+
# Copyright 2021-2023 Tecnativa - David Vidal
4+
# Copyright 2021-2023 Tecnativa - Pedro M. Baeza
5+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
6+
{
7+
"name": "Return Merchandise Authorization Management - Link with Sales",
8+
"summary": "Sale Order - Return Merchandise Authorization (RMA)",
9+
"version": "18.0.1.0.0",
10+
"development_status": "Production/Stable",
11+
"category": "RMA",
12+
"website": "https://github.com/OCA/rma",
13+
"author": "Tecnativa, Odoo Community Association (OCA)",
14+
"maintainers": ["chienandalu"],
15+
"license": "AGPL-3",
16+
"depends": ["rma", "sale_stock"],
17+
"data": [
18+
"security/ir.model.access.csv",
19+
"views/account_move_views.xml",
20+
"views/report_rma.xml",
21+
"views/rma_views.xml",
22+
"views/sale_views.xml",
23+
"views/sale_portal_template.xml",
24+
"views/res_config_settings_views.xml",
25+
"wizard/sale_order_rma_wizard_views.xml",
26+
],
27+
"assets": {
28+
"web.assets_frontend": [
29+
"/rma_sale/static/src/js/rma_portal_form.esm.js",
30+
"/rma_sale/static/src/scss/rma_sale.scss",
31+
],
32+
"web.assets_tests": [
33+
"/rma_sale/static/src/tests/*.js",
34+
],
35+
},
36+
}

rma_sale/controllers/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
2+
3+
from . import rma_portal
4+
from . import sale_portal

rma_sale/controllers/rma_portal.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright 2020 Tecnativa - Ernesto Tejeda
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
4+
from odoo.addons.rma.controllers.main import PortalRma
5+
6+
7+
class PortalRma(PortalRma):
8+
def _get_filter_domain(self, kw):
9+
res = super()._get_filter_domain(kw)
10+
if "sale_id" in kw:
11+
res.append(("order_id", "=", int(kw["sale_id"])))
12+
return res
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Copyright 2020 Tecnativa - Ernesto Tejeda
2+
# Copyright 2022 Tecnativa - Víctor Martínez
3+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
4+
5+
from odoo import Command, _, http
6+
from odoo.exceptions import AccessError, MissingError
7+
from odoo.http import request
8+
9+
from odoo.addons.sale.controllers.portal import CustomerPortal
10+
11+
12+
class CustomerPortal(CustomerPortal):
13+
@http.route(
14+
["/my/orders/<int:order_id>/requestrma"],
15+
type="http",
16+
auth="public",
17+
methods=["POST"],
18+
website=True,
19+
)
20+
def request_rma(self, order_id, access_token=None, **post):
21+
try:
22+
order_sudo = self._document_check_access(
23+
"sale.order", order_id, access_token=access_token
24+
)
25+
except (AccessError, MissingError):
26+
return request.redirect("/my")
27+
order_obj = request.env["sale.order"]
28+
wizard_obj = request.env["sale.order.rma.wizard"].sudo()
29+
wizard_line_field_types = {
30+
f: d["type"] for f, d in wizard_obj.line_ids.fields_get().items()
31+
}
32+
# Set wizard line vals
33+
mapped_vals = {}
34+
custom_vals = {}
35+
partner_shipping_id = post.pop("partner_shipping_id", False)
36+
if partner_shipping_id:
37+
try:
38+
partner_shipping_id = int(partner_shipping_id)
39+
except ValueError:
40+
partner_shipping_id = False
41+
for name, value in post.items():
42+
try:
43+
row, field_name = name.split("-", 1)
44+
if wizard_line_field_types.get(field_name) == "many2one":
45+
value = int(value) if value else False
46+
mapped_vals.setdefault(row, {}).update({field_name: value})
47+
# Catch possible form custom fields to add them to the RMA
48+
# description values
49+
except ValueError:
50+
custom_vals.update({name: value})
51+
# If no operation is filled, no RMA will be created
52+
line_vals = [
53+
Command.create(vals)
54+
for vals in mapped_vals.values()
55+
if vals.get("operation_id")
56+
]
57+
# Create wizard an generate rmas
58+
order = order_obj.browse(order_id).sudo()
59+
location_id = order.warehouse_id.rma_loc_id.id
60+
# Add custom fields text
61+
custom_description = ""
62+
if custom_vals:
63+
custom_description = r"<br \>---<br \>"
64+
custom_description += r"<br \>".join(
65+
[f"{x}: {y}" for x, y in custom_vals.items()]
66+
)
67+
wizard = wizard_obj.with_context(active_id=order_id).create(
68+
{
69+
"line_ids": line_vals,
70+
"location_id": location_id,
71+
"partner_shipping_id": partner_shipping_id,
72+
"custom_description": custom_description,
73+
}
74+
)
75+
user_has_group_portal = request.env.user.has_group(
76+
"base.group_portal"
77+
) or request.env.user.has_group("base.group_public")
78+
rma = wizard.sudo().create_rma(from_portal=True)
79+
for rec in rma:
80+
rec.origin += _(" (Portal)")
81+
# Add the user as follower of the created RMAs so they can later view them.
82+
rma.message_subscribe([request.env.user.partner_id.id])
83+
# Subscribe the user to the notification subtype so he receives the confirmation
84+
# note.
85+
rma.message_follower_ids.filtered(
86+
lambda x: x.partner_id == request.env.user.partner_id
87+
).subtype_ids += request.env.ref("rma.mt_rma_notification")
88+
if len(rma) == 0:
89+
route = order_sudo.get_portal_url()
90+
elif len(rma) == 1:
91+
route = rma._get_share_url() if user_has_group_portal else rma.access_url
92+
else:
93+
route = (
94+
order._get_share_url()
95+
if user_has_group_portal
96+
else "/my/rmas?sale_id=%d" % order_id
97+
)
98+
return request.redirect(route)
99+
100+
@http.route(
101+
["/my/requestrma/<int:order_id>"], type="http", auth="public", website=True
102+
)
103+
def request_sale_rma(self, order_id, access_token=None, **kw):
104+
"""Request RMA on a single page"""
105+
try:
106+
order_sudo = self._document_check_access(
107+
"sale.order", order_id, access_token=access_token
108+
)
109+
except (AccessError, MissingError):
110+
return request.redirect("/my")
111+
if order_sudo.state in ("draft", "sent", "cancel"):
112+
return request.redirect("/my")
113+
values = {
114+
"sale_order": order_sudo,
115+
"page_name": "request_rma",
116+
"default_url": order_sudo.get_portal_url(),
117+
"token": access_token,
118+
"partner_id": order_sudo.partner_id.id,
119+
}
120+
if order_sudo.company_id:
121+
values["res_company"] = order_sudo.company_id
122+
return request.render("rma_sale.request_rma_single_page", values)

0 commit comments

Comments
 (0)