From 1094633127418b03c5e77dd04bb332ae1230186f Mon Sep 17 00:00:00 2001
From: Ernesto Tejeda
Date: Wed, 24 Jun 2020 09:28:59 -0400
Subject: [PATCH 01/52] [ADD] rma_sale: new module
[UPD] Update rma_sale.pot
[ADD] icon.png
---
rma_sale/README.rst | 117 +++++
rma_sale/__init__.py | 5 +
rma_sale/__manifest__.py | 25 +
rma_sale/controllers/__init__.py | 4 +
rma_sale/controllers/rma_portal.py | 13 +
rma_sale/controllers/sale_portal.py | 40 ++
rma_sale/i18n/es.po | 337 +++++++++++++
rma_sale/i18n/rma_sale.pot | 305 ++++++++++++
rma_sale/models/__init__.py | 4 +
rma_sale/models/rma.py | 83 ++++
rma_sale/models/sale.py | 129 +++++
rma_sale/readme/CONTRIBUTORS.rst | 5 +
rma_sale/readme/DESCRIPTION.rst | 4 +
rma_sale/readme/USAGE.rst | 25 +
rma_sale/static/description/icon.png | Bin 0 -> 9455 bytes
rma_sale/static/description/index.html | 459 ++++++++++++++++++
rma_sale/static/src/scss/rma_sale.scss | 5 +
rma_sale/tests/__init__.py | 3 +
rma_sale/tests/test_rma_sale.py | 68 +++
rma_sale/views/assets.xml | 8 +
rma_sale/views/report_rma.xml | 17 +
rma_sale/views/rma_views.xml | 20 +
rma_sale/views/sale_portal_template.xml | 126 +++++
rma_sale/views/sale_views.xml | 27 ++
rma_sale/wizard/__init__.py | 3 +
rma_sale/wizard/sale_order_rma_wizard.py | 172 +++++++
.../wizard/sale_order_rma_wizard_views.xml | 51 ++
27 files changed, 2055 insertions(+)
create mode 100644 rma_sale/README.rst
create mode 100644 rma_sale/__init__.py
create mode 100644 rma_sale/__manifest__.py
create mode 100644 rma_sale/controllers/__init__.py
create mode 100644 rma_sale/controllers/rma_portal.py
create mode 100644 rma_sale/controllers/sale_portal.py
create mode 100644 rma_sale/i18n/es.po
create mode 100644 rma_sale/i18n/rma_sale.pot
create mode 100644 rma_sale/models/__init__.py
create mode 100644 rma_sale/models/rma.py
create mode 100644 rma_sale/models/sale.py
create mode 100644 rma_sale/readme/CONTRIBUTORS.rst
create mode 100644 rma_sale/readme/DESCRIPTION.rst
create mode 100644 rma_sale/readme/USAGE.rst
create mode 100644 rma_sale/static/description/icon.png
create mode 100644 rma_sale/static/description/index.html
create mode 100644 rma_sale/static/src/scss/rma_sale.scss
create mode 100644 rma_sale/tests/__init__.py
create mode 100644 rma_sale/tests/test_rma_sale.py
create mode 100644 rma_sale/views/assets.xml
create mode 100644 rma_sale/views/report_rma.xml
create mode 100644 rma_sale/views/rma_views.xml
create mode 100644 rma_sale/views/sale_portal_template.xml
create mode 100644 rma_sale/views/sale_views.xml
create mode 100644 rma_sale/wizard/__init__.py
create mode 100644 rma_sale/wizard/sale_order_rma_wizard.py
create mode 100644 rma_sale/wizard/sale_order_rma_wizard_views.xml
diff --git a/rma_sale/README.rst b/rma_sale/README.rst
new file mode 100644
index 00000000..1e67d920
--- /dev/null
+++ b/rma_sale/README.rst
@@ -0,0 +1,117 @@
+=============================================================
+Return Merchandise Authorization Management - Link with Sales
+=============================================================
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
+ :target: https://odoo-community.org/page/development-status
+ :alt: Beta
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+ :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frma-lightgray.png?logo=github
+ :target: https://github.com/OCA/rma/tree/12.0/rma_sale
+ :alt: OCA/rma
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/rma-12-0/rma-12-0-rma_sale
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
+ :target: https://runbot.odoo-community.org/runbot/145/12.0
+ :alt: Try me on Runbot
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This module allows you to link a sales order to an RMA.
+This can be done by creating an RMA from scratch and selecting the sales
+order, creating one or more RMAs from a sales order form view or from a sales
+order web portal page.
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Usage
+=====
+
+To use this module, you need to:
+
+#. Go to *RMA > Orders* and create a new RMA.
+#. Select a sales order to be linked to the RMA if you want.
+#. Now you can do the rest of the instructions described in the
+ *readme* of the rma module.
+
+If you want to create one or more RMAs from a sale order:
+
+#. Go to *Sales > Orders > Orders*.
+#. Create a new sales order or select an existing one.
+#. If the sales order is in 'Sales Order' state you can see in the status bar
+ a button labeled 'Create RMA', click it and a wizard will appear.
+#. Modify the data at your convenience and click on 'Accept' button.
+#. As many RMAs as lines with quantity greater than zero will be created.
+ Those RMAs will be linked to the sales order.
+
+The customer can also create RMAs from a sales order portal page:
+
+#. Go to a confirmed sales order portal page.
+#. In the left sidebar you can see a button named 'Request RMAs'.
+#. By clicking on this button a popup will appear to allow you to define
+ the quantity per product and delivery order line.
+#. Click on the 'Request RMAs' button and RMAs will be created linked to
+ the sales order.
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub 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 `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Tecnativa
+
+Contributors
+~~~~~~~~~~~~
+
+* `Tecnativa `_:
+
+ * Ernesto Tejeda
+ * Pedro M. Baeza
+ * David Vidal
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://odoo-community.org
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+.. |maintainer-ernestotejeda| image:: https://github.com/ernestotejeda.png?size=40px
+ :target: https://github.com/ernestotejeda
+ :alt: ernestotejeda
+
+Current `maintainer `__:
+
+|maintainer-ernestotejeda|
+
+This module is part of the `OCA/rma `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/rma_sale/__init__.py b/rma_sale/__init__.py
new file mode 100644
index 00000000..57055b3c
--- /dev/null
+++ b/rma_sale/__init__.py
@@ -0,0 +1,5 @@
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from . import controllers
+from . import models
+from . import wizard
diff --git a/rma_sale/__manifest__.py b/rma_sale/__manifest__.py
new file mode 100644
index 00000000..0c0efb2a
--- /dev/null
+++ b/rma_sale/__manifest__.py
@@ -0,0 +1,25 @@
+# Copyright 2020 Tecnativa - Ernesto Tejeda
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+{
+ "name": "Return Merchandise Authorization Management - Link with Sales",
+ "summary": "Sale Order - Return Merchandise Authorization (RMA)",
+ "version": "12.0.1.0.0",
+ "development_status": "Beta",
+ "category": "RMA",
+ "website": "https://github.com/OCA/rma",
+ "author": "Tecnativa, Odoo Community Association (OCA)",
+ "maintainers": ["ernestotejeda"],
+ "license": "AGPL-3",
+ "depends": [
+ "rma",
+ "sale",
+ ],
+ "data": [
+ "views/assets.xml",
+ "views/report_rma.xml",
+ "views/rma_views.xml",
+ "views/sale_views.xml",
+ "views/sale_portal_template.xml",
+ "wizard/sale_order_rma_wizard_views.xml",
+ ],
+}
diff --git a/rma_sale/controllers/__init__.py b/rma_sale/controllers/__init__.py
new file mode 100644
index 00000000..c3c3eb4d
--- /dev/null
+++ b/rma_sale/controllers/__init__.py
@@ -0,0 +1,4 @@
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from . import rma_portal
+from . import sale_portal
diff --git a/rma_sale/controllers/rma_portal.py b/rma_sale/controllers/rma_portal.py
new file mode 100644
index 00000000..505ab5c4
--- /dev/null
+++ b/rma_sale/controllers/rma_portal.py
@@ -0,0 +1,13 @@
+# Copyright 2020 Tecnativa - Ernesto Tejeda
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo.addons.rma.controllers.main import PortalRma
+
+
+class PortalRma(PortalRma):
+
+ def _get_filter_domain(self, kw):
+ res = super()._get_filter_domain(kw)
+ if 'sale_id' in kw:
+ res.append(('order_id', '=', int(kw['sale_id'])))
+ return res
diff --git a/rma_sale/controllers/sale_portal.py b/rma_sale/controllers/sale_portal.py
new file mode 100644
index 00000000..1ce25893
--- /dev/null
+++ b/rma_sale/controllers/sale_portal.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import http, _
+from odoo.exceptions import AccessError, MissingError
+from odoo.http import request
+from odoo.addons.sale.controllers.portal import CustomerPortal
+
+
+class CustomerPortal(CustomerPortal):
+ @http.route(['/my/orders//requestrma'], type='http',
+ auth="public", methods=['POST'], website=True)
+ def request_rma(self, order_id, access_token=None, **post):
+ try:
+ order_sudo = self._document_check_access('sale.order', order_id,
+ access_token=access_token)
+ except (AccessError, MissingError):
+ return request.redirect('/my')
+ order_obj = request.env['sale.order']
+ wizard_obj = request.env['sale.order.rma.wizard']
+ # Set wizard line vals
+ mapped_vals = {}
+ for name, value in post.items():
+ row, field_name = name.split('-', 1)
+ mapped_vals.setdefault(row, {}).update({field_name: value})
+ line_vals = [(0, 0, vals) for vals in mapped_vals.values()]
+ # Create wizard an generate rmas
+ location_id = order_obj.browse(order_id).warehouse_id.rma_loc_id.id
+ wizard = wizard_obj.with_context(active_id=order_id).create({
+ 'line_ids': line_vals,
+ 'location_id': location_id
+ })
+ rma = wizard.create_rma(from_portal=True)
+ for rec in rma:
+ rec.origin += _(' (Portal)')
+ if len(rma) == 0:
+ route = order_sudo.get_portal_url()
+ else:
+ route = "/my/rmas?sale_id=%d" % order_id
+ return request.redirect(route)
diff --git a/rma_sale/i18n/es.po b/rma_sale/i18n/es.po
new file mode 100644
index 00000000..0d3e1091
--- /dev/null
+++ b/rma_sale/i18n/es.po
@@ -0,0 +1,337 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * rma_sale
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-07-01 04:40+0000\n"
+"PO-Revision-Date: 2020-07-01 00:41-0400\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: \n"
+"X-Generator: Poedit 2.0.6\n"
+
+#. module: rma_sale
+#: code:addons/rma_sale/controllers/sale_portal.py:35
+#, python-format
+msgid " (Portal)"
+msgstr ""
+
+#. module: rma_sale
+#: code:addons/rma_sale/wizard/sale_order_rma_wizard.py:48
+#, python-format
+msgid " has been created."
+msgstr " ha sido creado."
+
+#. module: rma_sale
+#: code:addons/rma_sale/wizard/sale_order_rma_wizard.py:50
+#, python-format
+msgid " have been created."
+msgstr " han sido creados."
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "×"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid " Request RMAs"
+msgstr " Solicitar RMAs"
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid " Request RMAs"
+msgstr " Solicitar RMAs"
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid " Cancel"
+msgstr " Cancelar"
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_content
+msgid ""
+""
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid ""
+"\n"
+" If an RMA has already been created for a "
+"product in this sales order, it will not\n"
+" be possible to create another one from the "
+"web portal.\n"
+" "
+msgstr ""
+"\n"
+" Si ya se ha creado un RMA para un producto "
+"de esta orden de venta, no será\n"
+" posible crear otro desde el portal web.\n"
+" "
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_content
+msgid "RMA"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.report_rma_document
+msgid "Requested operation:"
+msgstr "Operación solicitada:"
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.portal_rma_page
+msgid "Requested operation"
+msgstr "Operación solicitada:"
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.report_rma_document
+msgid "Sale order:"
+msgstr "Orden de venta:"
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.portal_rma_page
+msgid "Sale order"
+msgstr "Orden de venta"
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.=sale_order_rma_wizard_form_view
+msgid "Accept"
+msgstr "Aceptar"
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.=sale_order_rma_wizard_form_view
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__uom_category_id
+msgid "Category"
+msgstr "Categoría"
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Close"
+msgstr "Cerrar"
+
+#. module: rma_sale
+#: model:ir.model.fields,help:rma_sale.field_sale_order_line_rma_wizard__uom_category_id
+msgid ""
+"Conversion between Units of Measure can only occur if they belong to the "
+"same category. The conversion will be made based on the ratios."
+msgstr ""
+"La conversión entre las unidades de medidas sólo pueden ocurrir si "
+"pertenecen a la misma categoría. La conversión se basará en los ratios "
+"establecidos."
+
+#. module: rma_sale
+#: code:addons/rma_sale/models/sale.py:48
+#: model_terms:ir.ui.view,arch_db:rma_sale.view_order_form
+#, python-format
+msgid "Create RMA"
+msgstr "Crear RMA"
+
+#. module: rma_sale
+#: model:ir.actions.act_window,name:rma_sale.sale_order_create_rma_action
+msgid "Create RMAs"
+msgstr "Crear RMA"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__create_uid
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__create_date
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__create_date
+msgid "Created on"
+msgstr "Creado el"
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Delivery"
+msgstr "Entrega"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__picking_id
+msgid "Delivery order"
+msgstr "Orden de entrega"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__display_name
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__display_name
+msgid "Display Name"
+msgstr "Nombre mostrado"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__domain_move_ids
+msgid "Domain Move"
+msgstr "Dominio de movimientos"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__domain_picking_ids
+msgid "Domain Picking"
+msgstr "Dominio de entregas"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__domain_product_ids
+msgid "Domain Product"
+msgstr "Dominio de productos"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__id
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__id
+msgid "ID"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_stock_move__is_sale_delivery
+#, fuzzy
+#| msgid "Delivery"
+msgid "Is Sale Delivery"
+msgstr "Es entrega de orden de venta"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard____last_update
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard____last_update
+msgid "Last Modified on"
+msgstr "Última modificación en"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__write_uid
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__write_uid
+msgid "Last Updated by"
+msgstr "Última actualización por"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__write_date
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__write_date
+msgid "Last Updated on"
+msgstr "Última actualización el"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__line_ids
+msgid "Lines"
+msgstr "Líneas"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__move_id
+msgid "Move"
+msgstr "Movimiento"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__order_id
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__order_id
+msgid "Order"
+msgstr "Orden"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__picking_id
+msgid "Origin Delivery"
+msgstr "Orden de Entrega"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__move_id
+msgid "Origin move"
+msgstr "Movimiento"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__picking_ids
+msgid "Picking"
+msgstr "Dominio de órdenes de entrega"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__product_id
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__product_id
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Product"
+msgstr "Producto"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__quantity
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Quantity"
+msgstr "Cantidad"
+
+#. module: rma_sale
+#: model:ir.model,name:rma_sale.model_rma
+#: model_terms:ir.ui.view,arch_db:rma_sale.view_order_form
+msgid "RMA"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order__rma_count
+msgid "RMA count"
+msgstr "Cantidad de RMAs"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__location_id
+msgid "RMA location"
+msgstr "Ubicación de RMA"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order__rma_ids
+msgid "RMAs"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Request RMAs"
+msgstr "Solicitar RMAs"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__operation_id
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Requested operation"
+msgstr "Operación solicitada"
+
+#. module: rma_sale
+#: model:ir.model,name:rma_sale.model_sale_order
+#: model:ir.model.fields,field_description:rma_sale.field_rma__order_id
+msgid "Sale Order"
+msgstr "Pedido de venta"
+
+#. module: rma_sale
+#: model:ir.model,name:rma_sale.model_sale_order_line_rma_wizard
+msgid "Sale Order Line Rma Wizard"
+msgstr "Linea de Asistente de Orden de Venta - RMA "
+
+#. module: rma_sale
+#: model:ir.model,name:rma_sale.model_sale_order_rma_wizard
+msgid "Sale Order Rma Wizard"
+msgstr "Asistente de Orden de Venta - RMA"
+
+#. module: rma_sale
+#: model:ir.model,name:rma_sale.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "Línea de pedido de venta"
+
+#. module: rma_sale
+#: model:ir.model,name:rma_sale.model_stock_move
+msgid "Stock Move"
+msgstr "Movimiento"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__uom_id
+msgid "Unit of Measure"
+msgstr "Unidad de medida"
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__wizard_id
+msgid "Wizard"
+msgstr "Asistente"
+
+#. module: rma_sale
+#: code:addons/rma_sale/models/sale.py:34
+#, python-format
+msgid "You may only create RMAs from a confirmed or done sale order."
+msgstr "Solo puedes crear RMAs desde una orden de venta confirmada o hecha."
diff --git a/rma_sale/i18n/rma_sale.pot b/rma_sale/i18n/rma_sale.pot
new file mode 100644
index 00000000..3de688c5
--- /dev/null
+++ b/rma_sale/i18n/rma_sale.pot
@@ -0,0 +1,305 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * rma_sale
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.0\n"
+"Report-Msgid-Bugs-To: \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_sale
+#: code:addons/rma_sale/controllers/sale_portal.py:35
+#, python-format
+msgid " (Portal)"
+msgstr ""
+
+#. module: rma_sale
+#: code:addons/rma_sale/wizard/sale_order_rma_wizard.py:48
+#, python-format
+msgid " has been created."
+msgstr ""
+
+#. module: rma_sale
+#: code:addons/rma_sale/wizard/sale_order_rma_wizard.py:50
+#, python-format
+msgid " have been created."
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "×"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid " Request RMAs"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid " Request RMAs"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid " Cancel"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_content
+msgid ""
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "\n"
+" If an RMA has already been created for a product in this sales order, it will not\n"
+" be possible to create another one from the web portal.\n"
+" "
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_content
+msgid "RMA"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.report_rma_document
+msgid "Requested operation:"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.portal_rma_page
+msgid "Requested operation"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.report_rma_document
+msgid "Sale order:"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.portal_rma_page
+msgid "Sale order"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.=sale_order_rma_wizard_form_view
+msgid "Accept"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__allowed_move_ids
+msgid "Allowed Move"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__allowed_picking_ids
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__allowed_picking_ids
+msgid "Allowed Picking"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__allowed_product_ids
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__allowed_product_ids
+msgid "Allowed Product"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.=sale_order_rma_wizard_form_view
+msgid "Cancel"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__uom_category_id
+msgid "Category"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Close"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,help:rma_sale.field_sale_order_line_rma_wizard__uom_category_id
+msgid "Conversion between Units of Measure can only occur if they belong to the same category. The conversion will be made based on the ratios."
+msgstr ""
+
+#. module: rma_sale
+#: code:addons/rma_sale/models/sale.py:48
+#: model_terms:ir.ui.view,arch_db:rma_sale.view_order_form
+#, python-format
+msgid "Create RMA"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.actions.act_window,name:rma_sale.sale_order_create_rma_action
+msgid "Create RMAs"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__create_uid
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__create_date
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__create_date
+msgid "Created on"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Delivery"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__picking_id
+msgid "Delivery order"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__display_name
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__id
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__id
+msgid "ID"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard____last_update
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__write_uid
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__write_date
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__line_ids
+msgid "Lines"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__move_id
+msgid "Move"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__order_id
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__order_id
+msgid "Order"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__picking_id
+msgid "Origin Delivery"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__move_id
+msgid "Origin move"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_rma__product_id
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__product_id
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Product"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__quantity
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Quantity"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model,name:rma_sale.model_rma
+#: model_terms:ir.ui.view,arch_db:rma_sale.view_order_form
+msgid "RMA"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order__rma_count
+msgid "RMA count"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__location_id
+msgid "RMA location"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order__rma_ids
+msgid "RMAs"
+msgstr ""
+
+#. module: rma_sale
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Request RMAs"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__operation_id
+#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
+msgid "Requested operation"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model,name:rma_sale.model_sale_order
+#: model:ir.model.fields,field_description:rma_sale.field_rma__order_id
+msgid "Sale Order"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model,name:rma_sale.model_sale_order_line_rma_wizard
+msgid "Sale Order Line Rma Wizard"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model,name:rma_sale.model_sale_order_rma_wizard
+msgid "Sale Order Rma Wizard"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model,name:rma_sale.model_sale_order_line
+msgid "Sales Order Line"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__uom_id
+msgid "Unit of Measure"
+msgstr ""
+
+#. module: rma_sale
+#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__wizard_id
+msgid "Wizard"
+msgstr ""
+
+#. module: rma_sale
+#: code:addons/rma_sale/models/sale.py:34
+#, python-format
+msgid "You may only create RMAs from a confirmed or done sale order."
+msgstr ""
+
diff --git a/rma_sale/models/__init__.py b/rma_sale/models/__init__.py
new file mode 100644
index 00000000..d8e54bcb
--- /dev/null
+++ b/rma_sale/models/__init__.py
@@ -0,0 +1,4 @@
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from . import rma
+from . import sale
diff --git a/rma_sale/models/rma.py b/rma_sale/models/rma.py
new file mode 100644
index 00000000..c647e771
--- /dev/null
+++ b/rma_sale/models/rma.py
@@ -0,0 +1,83 @@
+# Copyright 2020 Tecnativa - Ernesto Tejeda
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import api, fields, models
+
+
+class Rma(models.Model):
+ _inherit = "rma"
+
+ order_id = fields.Many2one(
+ comodel_name='sale.order',
+ string='Sale Order',
+ domain="["
+ " ('partner_id', 'child_of', commercial_partner_id),"
+ " ('state', 'in', ['sale', 'done']),"
+ "]",
+ readonly=True,
+ states={'draft': [('readonly', False)]},
+ )
+ allowed_picking_ids = fields.Many2many(
+ comodel_name='stock.picking',
+ compute="_compute_allowed_picking_ids",
+ )
+ picking_id = fields.Many2one(
+ domain="[('id', 'in', allowed_picking_ids)]",
+ )
+ allowed_move_ids = fields.Many2many(
+ comodel_name='sale.order.line',
+ compute="_compute_allowed_move_ids",
+ )
+ move_id = fields.Many2one(
+ domain="[('id', 'in', allowed_move_ids)]",
+ )
+ allowed_product_ids = fields.Many2many(
+ comodel_name='product.product',
+ compute="_compute_allowed_product_ids",
+ )
+ product_id = fields.Many2one(
+ domain="[('id', 'in', allowed_product_ids)]",
+ )
+
+ @api.depends('partner_id', 'order_id')
+ def _compute_allowed_picking_ids(self):
+ domain = [('state', '=', 'done'),
+ ('picking_type_id.code', '=', 'outgoing')]
+ for rec in self:
+ # if rec.partner_id:
+ commercial_partner = rec.partner_id.commercial_partner_id
+ domain.append(('partner_id', 'child_of', commercial_partner.id))
+ if rec.order_id:
+ domain.append(('sale_id', '=', rec.order_id.id))
+ rec.allowed_picking_ids = self.env['stock.picking'].search(domain)
+
+ @api.depends('order_id', 'picking_id')
+ def _compute_allowed_move_ids(self):
+ for rec in self:
+ if rec.order_id:
+ order_move = rec.order_id.order_line.mapped('move_ids')
+ rec.allowed_move_ids = order_move.filtered(
+ lambda r: r.picking_id == self.picking_id).ids
+ else:
+ rec.allowed_move_ids = self.picking_id.move_lines.ids
+
+ @api.depends('order_id')
+ def _compute_allowed_product_ids(self):
+ for rec in self:
+ if rec.order_id:
+ order_product = rec.order_id.order_line.mapped('product_id')
+ rec.allowed_product_ids = order_product.filtered(
+ lambda r: r.type in ['consu', 'product']).ids
+ else:
+ rec.allowed_product_ids = self.env['product.product'].search(
+ [('type', 'in', ['consu', 'product'])]).ids
+
+ @api.onchange("partner_id")
+ def _onchange_partner_id(self):
+ res = super()._onchange_partner_id()
+ self.order_id = False
+ return res
+
+ @api.onchange('order_id')
+ def _onchange_order_id(self):
+ self.product_id = self.picking_id = False
diff --git a/rma_sale/models/sale.py b/rma_sale/models/sale.py
new file mode 100644
index 00000000..25cd223a
--- /dev/null
+++ b/rma_sale/models/sale.py
@@ -0,0 +1,129 @@
+# Copyright 2020 Tecnativa - Ernesto Tejeda
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import _, fields, models
+from odoo.exceptions import ValidationError
+
+
+class SaleOrder(models.Model):
+ _inherit = "sale.order"
+
+ # RMAs that were created from a sale order
+ rma_ids = fields.One2many(
+ comodel_name='rma',
+ inverse_name='order_id',
+ string='RMAs',
+ copy=False,
+ )
+ rma_count = fields.Integer(
+ string='RMA count',
+ compute='_compute_rma_count',
+ )
+
+ def _compute_rma_count(self):
+ rma_data = self.env['rma'].read_group(
+ [('order_id', 'in', self.ids)], ['order_id'], ['order_id'])
+ mapped_data = dict(
+ [(r['order_id'][0], r['order_id_count']) for r in rma_data])
+ for record in self:
+ record.rma_count = mapped_data.get(record.id, 0)
+
+ def action_create_rma(self):
+ self.ensure_one()
+ if self.state not in ['sale', 'done']:
+ raise ValidationError(_("You may only create RMAs from a "
+ "confirmed or done sale order."))
+ wizard_obj = self.env['sale.order.rma.wizard']
+ line_vals = [(0, 0, {
+ 'product_id': data['product'].id,
+ 'quantity': data['quantity'],
+ 'uom_id': data['uom'].id,
+ 'picking_id': data['picking'] and data['picking'].id,
+ }) for data in self.get_delivery_rma_data()]
+ wizard = wizard_obj.with_context(active_id=self.id).create({
+ 'line_ids': line_vals,
+ 'location_id': self.warehouse_id.rma_loc_id.id
+ })
+ return {
+ 'name': _('Create RMA'),
+ 'type': 'ir.actions.act_window',
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'sale.order.rma.wizard',
+ 'res_id': wizard.id,
+ 'target': 'new',
+ }
+
+ def action_view_rma(self):
+ self.ensure_one()
+ action = self.env.ref('rma.rma_action').read()[0]
+ rma = self.rma_ids
+ if len(rma) == 1:
+ action.update(
+ res_id=rma.id,
+ view_mode="form",
+ )
+ else:
+ action['domain'] = [('id', 'in', rma.ids)]
+ return action
+
+ def get_delivery_rma_data(self):
+ self.ensure_one()
+ data = []
+ for line in self.order_line:
+ data += line.prepare_sale_rma_data()
+ return data
+
+ def get_portal_delivery_rma_data(self):
+ self.ensure_one()
+ data = []
+
+ rma_product = self.rma_ids.mapped('product_id')
+ for line in self.order_line.filtered(
+ lambda r: r.product_id not in rma_product):
+ data += line.prepare_sale_rma_data()
+ return data
+
+
+class SaleOrderLine(models.Model):
+ _inherit = "sale.order.line"
+
+ def get_delivery_move(self):
+ self.ensure_one()
+ return self.move_ids.filtered(lambda r: (
+ self.product_id == r.product_id
+ and r.state == 'done'
+ and not r.scrapped
+ and r.location_dest_id.usage == "customer"
+ and (not r.origin_returned_move_id
+ or (r.origin_returned_move_id and r.to_refund))
+ ))
+
+ def prepare_sale_rma_data(self):
+ self.ensure_one()
+ product = self.product_id
+ if self.product_id.type != 'product':
+ return {}
+ moves = self.get_delivery_move()
+ data = []
+ if moves:
+ for move in moves:
+ qty = move.product_uom_qty
+ move_dest = move.move_dest_ids.filtered(
+ lambda r: r.state in ['partially_available',
+ 'assigned', 'done'])
+ qty -= sum(move_dest.mapped('product_uom_qty'))
+ data.append({
+ 'product': product,
+ 'quantity': qty,
+ 'uom': move.product_uom,
+ 'picking': move.picking_id,
+ })
+ else:
+ data.append({
+ 'product': product,
+ 'quantity': self.qty_delivered,
+ 'uom': self.product_uom,
+ 'picking': False,
+ })
+ return data
diff --git a/rma_sale/readme/CONTRIBUTORS.rst b/rma_sale/readme/CONTRIBUTORS.rst
new file mode 100644
index 00000000..d4052271
--- /dev/null
+++ b/rma_sale/readme/CONTRIBUTORS.rst
@@ -0,0 +1,5 @@
+* `Tecnativa `_:
+
+ * Ernesto Tejeda
+ * Pedro M. Baeza
+ * David Vidal
diff --git a/rma_sale/readme/DESCRIPTION.rst b/rma_sale/readme/DESCRIPTION.rst
new file mode 100644
index 00000000..baff386c
--- /dev/null
+++ b/rma_sale/readme/DESCRIPTION.rst
@@ -0,0 +1,4 @@
+This module allows you to link a sales order to an RMA.
+This can be done by creating an RMA from scratch and selecting the sales
+order, creating one or more RMAs from a sales order form view or from a sales
+order web portal page.
diff --git a/rma_sale/readme/USAGE.rst b/rma_sale/readme/USAGE.rst
new file mode 100644
index 00000000..fd3026cc
--- /dev/null
+++ b/rma_sale/readme/USAGE.rst
@@ -0,0 +1,25 @@
+To use this module, you need to:
+
+#. Go to *RMA > Orders* and create a new RMA.
+#. Select a sales order to be linked to the RMA if you want.
+#. Now you can do the rest of the instructions described in the
+ *readme* of the rma module.
+
+If you want to create one or more RMAs from a sale order:
+
+#. Go to *Sales > Orders > Orders*.
+#. Create a new sales order or select an existing one.
+#. If the sales order is in 'Sales Order' state you can see in the status bar
+ a button labeled 'Create RMA', click it and a wizard will appear.
+#. Modify the data at your convenience and click on 'Accept' button.
+#. As many RMAs as lines with quantity greater than zero will be created.
+ Those RMAs will be linked to the sales order.
+
+The customer can also create RMAs from a sales order portal page:
+
+#. Go to a confirmed sales order portal page.
+#. In the left sidebar you can see a button named 'Request RMAs'.
+#. By clicking on this button a popup will appear to allow you to define
+ the quantity per product and delivery order line.
+#. Click on the 'Request RMAs' button and RMAs will be created linked to
+ the sales order.
diff --git a/rma_sale/static/description/icon.png b/rma_sale/static/description/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d
GIT binary patch
literal 9455
zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~!
zVpnB`o+K7|Al`Q_U;eD$B
zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA
z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__
zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_
zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I
z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U
z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)(
z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH
zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW
z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx
zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h
zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9
zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz#
z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA
zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K=
z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS
zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C
zuVl&0duN<;uOsB3%T9Fp8t{ED108)`y_~Hnd9AUX7h-H?jVuU|}My+C=TjH(jKz
zqMVr0re3S$H@t{zI95qa)+Crz*5Zj}Ao%4Z><+W(nOZd?gDnfNBC3>M8WE61$So|P
zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO
z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1
zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_
zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8
zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ>
zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN
z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h
zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d
zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB
zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz
z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I
zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X
zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD
z#z-)AXwSRY?OPefw^iI+
z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd
z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs
z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I
z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$
z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV
z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s
zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6
zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u
zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q
zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH
zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c
zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT
zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+
z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ
zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy
zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC)
zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a
zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x!
zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X
zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8
z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A
z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H
zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n=
z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK
z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z
zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h
z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD
z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW
zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@
zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz
z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y<
zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X
zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6
zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6%
z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(|
z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ
z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H
zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6
z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d}
z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A
zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB
z
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
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I
literal 0
HcmV?d00001
diff --git a/rma_sale/static/description/index.html b/rma_sale/static/description/index.html
new file mode 100644
index 00000000..aaaca20d
--- /dev/null
+++ b/rma_sale/static/description/index.html
@@ -0,0 +1,459 @@
+
+
+
+
+
+
+Return Merchandise Authorization Management - Link with Sales
+
+
+
+
+
Return Merchandise Authorization Management - Link with Sales
+
+
+
+
This module allows you to link a sales order to an RMA.
+This can be done by creating an RMA from scratch and selecting the sales
+order, creating one or more RMAs from a sales order form view or from a sales
+order web portal page.
Bugs are tracked on GitHub 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.
+
Do not contact contributors directly about support or help with technical issues.
OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
When you try to request an RMA from a Sales Order in the portal,
+a popup appears and the inputs for the quantity doesn’t allow
+decimal numbers. It would be good to have a component that allows
+that and at the same time keeps the constraint of not allowing a
+number greater than the order line product quantity.
Bugs are tracked on GitHub 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
@@ -423,15 +434,15 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
Do not contact contributors directly about support or help with technical issues.
OCA, or the Odoo Community Association, is a nonprofit organization whose
diff --git a/rma_sale/views/sale_portal_template.xml b/rma_sale/views/sale_portal_template.xml
index fad64c85..c361b63f 100644
--- a/rma_sale/views/sale_portal_template.xml
+++ b/rma_sale/views/sale_portal_template.xml
@@ -17,13 +17,20 @@
×
-
+
- If an RMA has already been created for a product in this sales order, it will not
- be possible to create another one from the web portal.
+ You're about to perform an RMA request. Our team will process it an will reach you once it's validated. Keep in mind that:
+
+
Select the product quantity and the requested operation
+
Use the comment button to add relevant information regarding the RMA, like returned serial numbers or a description of the issue
+
If no requested operation is set, the RMA won't be correctly fulfilled
+
You can only return as much product units as you received for this order
+
The limit will decrease when the units in other RMAs are confirmed