Merge PR #178 into 13.0

Signed-off-by pedrobaeza
This commit is contained in:
OCA-git-bot
2020-11-05 15:20:47 +00:00
32 changed files with 2721 additions and 0 deletions

126
rma_sale/README.rst Normal file
View File

@@ -0,0 +1,126 @@
=============================================================
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/13.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-13-0/rma-13-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/13.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.
Known issues / Roadmap
======================
* 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.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/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 <https://github.com/OCA/rma/issues/new?body=module:%20rma_sale%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Tecnativa
Contributors
~~~~~~~~~~~~
* `Tecnativa <https://www.tecnativa.com>`_:
* 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 <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-ernestotejeda|
This module is part of the `OCA/rma <https://github.com/OCA/rma/tree/13.0/rma_sale>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

5
rma_sale/__init__.py Normal file
View File

@@ -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

22
rma_sale/__manifest__.py Normal file
View File

@@ -0,0 +1,22 @@
# 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": "13.0.1.0.0",
"development_status": "Production/Stable",
"category": "RMA",
"website": "https://github.com/OCA/rma",
"author": "Tecnativa, Odoo Community Association (OCA)",
"maintainers": ["ernestotejeda"],
"license": "AGPL-3",
"depends": ["rma", "sale_stock"],
"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",
],
}

View File

@@ -0,0 +1,4 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import rma_portal
from . import sale_portal

View File

@@ -0,0 +1,12 @@
# 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

View File

@@ -0,0 +1,53 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
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/<int:order_id>/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})
# If no operation is filled, no RMA will be created
line_vals = [
(0, 0, vals) for vals in mapped_vals.values() if vals.get("operation_id")
]
# Create wizard an generate rmas
order = order_obj.browse(order_id).sudo()
location_id = order.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.sudo().create_rma()
for rec in rma:
rec.origin += _(" (Portal)")
# Add the user as follower of the created RMAs so they can
# later view them.
rma.message_subscribe([request.env.user.partner_id.id])
if len(rma) == 0:
route = order_sudo.get_portal_url()
else:
route = "/my/rmas?sale_id=%d" % order_id
return request.redirect(route)

402
rma_sale/i18n/es.po Normal file
View File

@@ -0,0 +1,402 @@
# 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-10-06 14:16+0000\n"
"Last-Translator: David Vidal <david.vidal@tecnativa.com>\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: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 3.10\n"
#. module: rma_sale
#: code:addons/rma_sale/controllers/sale_portal.py:39
#, python-format
msgid " (Portal)"
msgstr " (Portal)"
#. module: rma_sale
#: code:addons/rma_sale/wizard/sale_order_rma_wizard.py:42
#, python-format
msgid " has been created."
msgstr " ha sido creado."
#. module: rma_sale
#: code:addons/rma_sale/wizard/sale_order_rma_wizard.py:44
#, 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 "&amp;times;"
msgstr "&amp;times;"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "<i class=\"fa fa-check\"/> Request RMAs"
msgstr "<i class=\"fa fa-check\"/> Solicitar RMAs"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "<i class=\"fa fa-reply\"/> Request RMAs"
msgstr "<i class=\"fa fa-reply\"/> Solicitar RMAs"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "<i class=\"fa fa-times\"/> Cancel"
msgstr "<i class=\"fa fa-times\"/> Cancelar"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_content
msgid ""
"<span class=\"fa fa-reply\" role=\"img\" aria-label=\"RMA\" title=\"RMA\"/>"
msgstr ""
"<span class=\"fa fa-reply\" role=\"img\" aria-label=\"RMA\" title=\"RMA\"/>"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_content
msgid "<span>RMA</span>"
msgstr "<span>RMA</span>"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.report_rma_document
msgid "<strong>Requested operation:</strong>"
msgstr "<strong>Operación solicitada:</strong>"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.portal_rma_page
msgid "<strong>Requested operation</strong>"
msgstr "<strong>Operación solicitada:</strong>"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.report_rma_document
msgid "<strong>Sale order:</strong>"
msgstr "<strong>Orden de venta:</strong>"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.portal_rma_page
msgid "<strong>Sale order</strong>"
msgstr "<strong>Orden de venta</strong>"
#. 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:ir.model.fields,field_description:rma_sale.field_rma__allowed_move_ids
msgid "Allowed Move"
msgstr "Movimientos permitido"
#. 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 "Albaranes permitidos"
#. 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 "Producto Permitido"
#. 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_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid ""
"Comment anything relevant to the return, like serial numbers, a description "
"of the issue, etc"
msgstr ""
"Comente cualquier asunto relevante relacionado con la devolución, como "
"números de serie, descripción del problema, etc"
#. 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 RMAs"
#. 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__description
msgid "Description"
msgstr "Descripción"
#. 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_sale_order_line_rma_wizard__id
#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__id
msgid "ID"
msgstr "ID"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "If no requested operation is set, the RMA won't be correctly fulfilled"
msgstr ""
"Si no se establece operación solicitada, el RMA no se procesará correctamente"
#. 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_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 "RMA"
#. 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 "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: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_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "Select the product quantity and the requested operation"
msgstr "Selecciones la cantidad de producto y la operación solicitada"
#. module: rma_sale
#: model:ir.model,name:rma_sale.model_stock_move
msgid "Stock Move"
msgstr "Movimiento de existencias"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "The limit will decrease when the units in other RMAs are confirmed"
msgstr "El límite disminuirá cuando las unidades de otros RMAs sean confirmadas"
#. 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_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid ""
"Use the comment button to add relevant information regarding the RMA, like "
"returned serial numbers or a description of the issue"
msgstr ""
"Utilice el botón de comentarios para añadir información relevante "
"relacionada con el RMA, como números de serie devueltos o una descripción "
"del problema"
#. 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
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid ""
"You can only return as much product units as you received for this order"
msgstr ""
"Solo puede devolver tanta cantidad de producto como usted recibió en el "
"pedido original"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "You can send a message in every RMA sent"
msgstr "Puede mandar un mensaje en cada RMA enviado"
#. 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."
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid ""
"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:"
msgstr ""
"Va a realizar una petición de RMA. Nuestro equipo la procesará y se pondrá "
"en contacto con usted una vez validad. Tenga en cuenta que:"
#~ msgid ""
#~ "<span>\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"
#~ " </span>"
#~ msgstr ""
#~ "<span>\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"
#~ " </span>"
#~ msgid "Domain Move"
#~ msgstr "Dominio de movimientos"
#~ msgid "Domain Picking"
#~ msgstr "Dominio de entregas"
#~ msgid "Domain Product"
#~ msgstr "Dominio de productos"
#, fuzzy
#~| msgid "Delivery"
#~ msgid "Is Sale Delivery"
#~ msgstr "Es entrega de orden de venta"

379
rma_sale/i18n/pt_BR.po Normal file
View File

@@ -0,0 +1,379 @@
# 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"
"PO-Revision-Date: 2020-07-22 18:19+0000\n"
"Last-Translator: Fernando Colus <fcolus1@gmail.com>\n"
"Language-Team: none\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 3.10\n"
#. module: rma_sale
#: code:addons/rma_sale/controllers/sale_portal.py:39
#, python-format
msgid " (Portal)"
msgstr " (Portal)"
#. module: rma_sale
#: code:addons/rma_sale/wizard/sale_order_rma_wizard.py:42
#, python-format
msgid " has been created."
msgstr " foi criado(a)."
#. module: rma_sale
#: code:addons/rma_sale/wizard/sale_order_rma_wizard.py:44
#, python-format
msgid " have been created."
msgstr " foi criado(a)."
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "&amp;times;"
msgstr "&amp;tempos;"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "<i class=\"fa fa-check\"/> Request RMAs"
msgstr "<i class=\"fa fa-check\"/> Requerer RMAs"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "<i class=\"fa fa-reply\"/> Request RMAs"
msgstr "<i class=\"fa fa-reply\"/> Requerer RMAs"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "<i class=\"fa fa-times\"/> Cancel"
msgstr "<i class=\"fa fa-times\"/> Cancelar"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_content
msgid ""
"<span class=\"fa fa-reply\" role=\"img\" aria-label=\"RMA\" title=\"RMA\"/>"
msgstr ""
"<span class=\"fa fa-reply\" role=\"img\" aria-label=\"RMA\" title=\"RMA\"/>"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_content
msgid "<span>RMA</span>"
msgstr "<span>RMA</span>"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.report_rma_document
msgid "<strong>Requested operation:</strong>"
msgstr "<strong>Operação Requerida:</strong>"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.portal_rma_page
msgid "<strong>Requested operation</strong>"
msgstr "<strong>Operação Requerida</strong>"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.report_rma_document
msgid "<strong>Sale order:</strong>"
msgstr "<strong>Pedido de Venda:</strong>"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.portal_rma_page
msgid "<strong>Sale order</strong>"
msgstr "<strong>Pedido de Venda</strong>"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.=sale_order_rma_wizard_form_view
msgid "Accept"
msgstr "Aceitar"
#. module: rma_sale
#: model:ir.model.fields,field_description:rma_sale.field_rma__allowed_move_ids
msgid "Allowed Move"
msgstr "Movimentação Autorizada"
#. 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 "Coleta Autorizada"
#. 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 "Produto Autorizado"
#. 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 "Categoria"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "Close"
msgstr "Encerrar"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid ""
"Comment anything relevant to the return, like serial numbers, a description "
"of the issue, etc"
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 ""
"Uma conversão entre unidades de medida só poderá ocorrer se pertencer à "
"mesma categoria. A conversão será feita com base nas proporções."
#. 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 "Criar RMA"
#. module: rma_sale
#: model:ir.actions.act_window,name:rma_sale.sale_order_create_rma_action
msgid "Create RMAs"
msgstr "Criar RMAs"
#. 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 "Criado 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 "Criado em"
#. 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 "Ordem de Entrega"
#. module: rma_sale
#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__description
msgid "Description"
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 "Exibir Nome"
#. 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 "ID"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "If no requested operation is set, the RMA won't be correctly fulfilled"
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 "Última modificação Feita em"
#. 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 Atualização Feita 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 Atualização Feita em"
#. module: rma_sale
#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__line_ids
msgid "Lines"
msgstr "Linhas"
#. module: rma_sale
#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__move_id
msgid "Move"
msgstr "Movimentação"
#. 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 "Pedido"
#. module: rma_sale
#: model:ir.model.fields,field_description:rma_sale.field_rma__picking_id
msgid "Origin Delivery"
msgstr "Origem da Entrega"
#. module: rma_sale
#: model:ir.model.fields,field_description:rma_sale.field_rma__move_id
msgid "Origin move"
msgstr "Origem da Movimentação"
#. 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 "Produto"
#. 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 "Quantidade"
#. 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 "RMA"
#. module: rma_sale
#: model:ir.model.fields,field_description:rma_sale.field_sale_order__rma_count
msgid "RMA count"
msgstr "Contagem de RMA"
#. module: rma_sale
#: model:ir.model.fields,field_description:rma_sale.field_sale_order_rma_wizard__location_id
msgid "RMA location"
msgstr "Localização do RMA"
#. module: rma_sale
#: model:ir.model.fields,field_description:rma_sale.field_sale_order__rma_ids
msgid "RMAs"
msgstr "RMAs"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "Request RMAs"
msgstr "Requisição de 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 "Operação Requisitada"
#. 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 Venda"
#. module: rma_sale
#: model:ir.model,name:rma_sale.model_sale_order_line_rma_wizard
msgid "Sale Order Line Rma Wizard"
msgstr "Assistente da Linha do Pedido de Venda RMA"
#. module: rma_sale
#: model:ir.model,name:rma_sale.model_sale_order_rma_wizard
msgid "Sale Order Rma Wizard"
msgstr "Assistente do Pedido de Venda RMA"
#. module: rma_sale
#: model:ir.model,name:rma_sale.model_sale_order_line
msgid "Sales Order Line"
msgstr "Linha do Pedido de Venda"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "Select the product quantity and the requested operation"
msgstr ""
#. module: rma_sale
#: model:ir.model,name:rma_sale.model_stock_move
msgid "Stock Move"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "The limit will decrease when the units in other RMAs are confirmed"
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 "Unidade de Medida"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid ""
"Use the comment button to add relevant information regarding the RMA, like "
"returned serial numbers or a description of the issue"
msgstr ""
#. module: rma_sale
#: model:ir.model.fields,field_description:rma_sale.field_sale_order_line_rma_wizard__wizard_id
msgid "Wizard"
msgstr "Assistente"
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid ""
"You can only return as much product units as you received for this order"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "You can send a message in every RMA sent"
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 ""
"Você só pode criar RMAs a partir de um pedido de venda confirmado ou "
"concluído."
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid ""
"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:"
msgstr ""
#~ msgid ""
#~ "<span>\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"
#~ " </span>"
#~ msgstr ""
#~ "<span>\n"
#~ " Se um RMA já houver sido criado para um "
#~ "produto no pedido de venda,\n"
#~ " não será possível criar outro através do "
#~ "portal web.\n"
#~ " </span>"

347
rma_sale/i18n/rma_sale.pot Normal file
View File

@@ -0,0 +1,347 @@
# 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:39
#, python-format
msgid " (Portal)"
msgstr ""
#. module: rma_sale
#: code:addons/rma_sale/wizard/sale_order_rma_wizard.py:42
#, python-format
msgid " has been created."
msgstr ""
#. module: rma_sale
#: code:addons/rma_sale/wizard/sale_order_rma_wizard.py:44
#, python-format
msgid " have been created."
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "&amp;times;"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "<i class=\"fa fa-check\"/> Request RMAs"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "<i class=\"fa fa-reply\"/> Request RMAs"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "<i class=\"fa fa-times\"/> Cancel"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_content
msgid "<span class=\"fa fa-reply\" role=\"img\" aria-label=\"RMA\" title=\"RMA\"/>"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_content
msgid "<span>RMA</span>"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.report_rma_document
msgid "<strong>Requested operation:</strong>"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.portal_rma_page
msgid "<strong>Requested operation</strong>"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.report_rma_document
msgid "<strong>Sale order:</strong>"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.portal_rma_page
msgid "<strong>Sale order</strong>"
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_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "Comment anything relevant to the return, like serial numbers, a description of the issue, etc"
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__description
msgid "Description"
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_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "If no requested operation is set, the RMA won't be correctly fulfilled"
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_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "Select the product quantity and the requested operation"
msgstr ""
#. module: rma_sale
#: model:ir.model,name:rma_sale.model_stock_move
msgid "Stock Move"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "The limit will decrease when the units in other RMAs are confirmed"
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_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "Use the comment button to add relevant information regarding the RMA, like returned serial numbers or a description of the issue"
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
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "You can only return as much product units as you received for this order"
msgstr ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "You can send a message in every RMA sent"
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 ""
#. module: rma_sale
#: model_terms:ir.ui.view,arch_db:rma_sale.sale_order_portal_template
msgid "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:"
msgstr ""

View File

@@ -0,0 +1,5 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import rma
from . import sale
from . import stock_move

85
rma_sale/models/rma.py Normal file
View File

@@ -0,0 +1,85 @@
# 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
def _prepare_refund(self, invoice_form, origin):
"""Inject salesman from sales order (if any)"""
res = super()._prepare_refund(invoice_form, origin)
if self.order_id:
invoice_form.invoice_user_id = self.order_id.user_id
return res

128
rma_sale/models/sale.py Normal file
View File

@@ -0,0 +1,128 @@
# 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 = {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_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", views=[],
)
else:
action["domain"] = [("id", "in", rma.ids)]
# reset context to show all related rma without default filters
action["context"] = {}
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
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

View File

@@ -0,0 +1,13 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import models
class StockMove(models.Model):
_inherit = "stock.move"
def _prepare_return_rma_vals(self, original_picking):
res = super()._prepare_return_rma_vals(original_picking)
res.update(order_id=original_picking.sale_id.id)
return res

View File

@@ -0,0 +1,5 @@
* `Tecnativa <https://www.tecnativa.com>`_:
* Ernesto Tejeda
* Pedro M. Baeza
* David Vidal

View File

@@ -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.

View File

@@ -0,0 +1,5 @@
* 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.

25
rma_sale/readme/USAGE.rst Normal file
View File

@@ -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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,470 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
<title>Return Merchandise Authorization Management - Link with Sales</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="return-merchandise-authorization-management-link-with-sales">
<h1 class="title">Return Merchandise Authorization Management - Link with Sales</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/rma/tree/13.0/rma_sale"><img alt="OCA/rma" src="https://img.shields.io/badge/github-OCA%2Frma-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/rma-13-0/rma-13-0-rma_sale"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/145/13.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>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.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="id1">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="id2">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#id1">Usage</a></h1>
<p>To use this module, you need to:</p>
<ol class="arabic simple">
<li>Go to <em>RMA &gt; Orders</em> and create a new RMA.</li>
<li>Select a sales order to be linked to the RMA if you want.</li>
<li>Now you can do the rest of the instructions described in the
<em>readme</em> of the rma module.</li>
</ol>
<p>If you want to create one or more RMAs from a sale order:</p>
<ol class="arabic simple">
<li>Go to <em>Sales &gt; Orders &gt; Orders</em>.</li>
<li>Create a new sales order or select an existing one.</li>
<li>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.</li>
<li>Modify the data at your convenience and click on Accept button.</li>
<li>As many RMAs as lines with quantity greater than zero will be created.
Those RMAs will be linked to the sales order.</li>
</ol>
<p>The customer can also create RMAs from a sales order portal page:</p>
<ol class="arabic simple">
<li>Go to a confirmed sales order portal page.</li>
<li>In the left sidebar you can see a button named Request RMAs.</li>
<li>By clicking on this button a popup will appear to allow you to define
the quantity per product and delivery order line.</li>
<li>Click on the Request RMAs button and RMAs will be created linked to
the sales order.</li>
</ol>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#id2">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>When you try to request an RMA from a Sales Order in the portal,
a popup appears and the inputs for the quantity doesnt 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.</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/rma/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/rma/issues/new?body=module:%20rma_sale%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id4">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id5">Authors</a></h2>
<ul class="simple">
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id6">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Ernesto Tejeda</li>
<li>Pedro M. Baeza</li>
<li>David Vidal</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id7">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external" href="https://github.com/ernestotejeda"><img alt="ernestotejeda" src="https://github.com/ernestotejeda.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/rma/tree/13.0/rma_sale">OCA/rma</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,5 @@
.request-rma-tbody {
td {
vertical-align: middle;
}
}

View File

@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import test_rma_sale

View File

@@ -0,0 +1,80 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo.tests import Form, SavepointCase
class TestRmaSale(SavepointCase):
@classmethod
def setUpClass(cls):
super(TestRmaSale, cls).setUpClass()
cls.res_partner = cls.env["res.partner"]
cls.product_product = cls.env["product.product"]
cls.sale_order = cls.env["sale.order"]
cls.product_1 = cls.product_product.create(
{"name": "Product test 1", "type": "product"}
)
cls.product_2 = cls.product_product.create(
{"name": "Product test 2", "type": "product"}
)
cls.partner = cls.res_partner.create({"name": "Partner test"})
order_form = Form(cls.sale_order)
order_form.partner_id = cls.partner
with order_form.order_line.new() as line_form:
line_form.product_id = cls.product_1
line_form.product_uom_qty = 5
cls.sale_order = order_form.save()
cls.sale_order.action_confirm()
# Maybe other modules create additional lines in the create
# method in sale.order model, so let's find the correct line.
cls.order_line = cls.sale_order.order_line.filtered(
lambda r: r.product_id == cls.product_1
)
cls.order_out_picking = cls.sale_order.picking_ids
cls.order_out_picking.move_lines.quantity_done = 5
cls.order_out_picking.button_validate()
def test_create_rma_with_so(self):
rma_form = Form(self.env["rma"])
rma_form.partner_id = self.partner
rma_form.order_id = self.sale_order
rma_form.product_id = self.product_1
rma_form.product_uom_qty = 5
rma_form.location_id = self.sale_order.warehouse_id.rma_loc_id
rma = rma_form.save()
rma.action_confirm()
self.assertTrue(rma.reception_move_id)
self.assertFalse(rma.reception_move_id.origin_returned_move_id)
def test_create_rma_from_so(self):
order = self.sale_order
wizard_id = order.action_create_rma()["res_id"]
wizard = self.env["sale.order.rma.wizard"].browse(wizard_id)
rma = self.env["rma"].browse(wizard.create_and_open_rma()["res_id"])
self.assertEqual(rma.partner_id, order.partner_id)
self.assertEqual(rma.order_id, order)
self.assertEqual(rma.picking_id, self.order_out_picking)
self.assertEqual(rma.move_id, self.order_out_picking.move_lines)
self.assertEqual(rma.product_id, self.product_1)
self.assertEqual(rma.product_uom_qty, self.order_line.product_uom_qty)
self.assertEqual(rma.product_uom, self.order_line.product_uom)
self.assertEqual(rma.state, "confirmed")
self.assertEqual(
rma.reception_move_id.origin_returned_move_id,
self.order_out_picking.move_lines,
)
self.assertEqual(
rma.reception_move_id.picking_id + self.order_out_picking,
order.picking_ids,
)
# Refund the RMA
user = self.env["res.users"].create(
{"login": "test_refund_with_so", "name": "Test"}
)
order.user_id = user.id
rma.action_confirm()
rma.reception_move_id.quantity_done = rma.product_uom_qty
rma.reception_move_id.picking_id.action_done()
rma.action_refund()
self.assertEqual(rma.refund_id.user_id, user)

12
rma_sale/views/assets.xml Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<template id="assets_frontend" inherit_id="web.assets_frontend" name="Request RMA">
<xpath expr="//link[last()]" position="after">
<link
rel="stylesheet"
type="text/scss"
href="/rma_sale/static/src/scss/rma_sale.scss"
/>
</xpath>
</template>
</odoo>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<template id="report_rma_document" inherit_id="rma.report_rma_document">
<xpath expr="//div[@t-if='doc.picking_id']" position="before">
<div t-if="doc.order_id" class="col-auto mw-100 mb-2">
<strong>Sale order:</strong>
<p class="m-0" t-field="doc.order_id" />
</div>
</xpath>
<xpath expr="//div[@t-if='doc.user_id']" position="before">
<div t-if="doc.operation_id" class="col-auto mw-100 mb-2">
<strong>Requested operation:</strong>
<p class="m-0" t-field="doc.operation_id" />
</div>
</xpath>
</template>
</odoo>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Tecnativa - Ernesto Tejeda
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="rma_view_form" model="ir.ui.view">
<field name="name">rma.view.form</field>
<field name="model">rma</field>
<field name="inherit_id" ref="rma.rma_view_form" />
<field name="arch" type="xml">
<field name="partner_invoice_id" position="after">
<field name="order_id" options="{'no_create': True}" />
</field>
<sheet>
<field name="allowed_picking_ids" invisible="1" />
<field name="allowed_move_ids" invisible="1" />
<field name="allowed_product_ids" invisible="1" />
</sheet>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,242 @@
<odoo>
<template
id="sale_order_portal_template"
name="Request RMA"
inherit_id="sale.sale_order_portal_template"
>
<xpath
expr="//div[hasclass('o_portal_sale_sidebar')]//div[hasclass('o_download_pdf')]/.."
position="after"
>
<li
t-if="sale_order.state in ['sale', 'done']"
class="list-group-item flex-grow-1"
id="li-request-rma"
>
<a
role="button"
class="btn btn-secondary btn-block mb8"
data-toggle="modal"
data-target="#modal-request-rma"
href="#"
>
<i class="fa fa-reply" /> Request RMAs
</a>
</li>
</xpath>
<xpath expr="//div[@id='modaldecline']" position="after">
<div role="dialog" class="modal fade" id="modal-request-rma">
<div class="modal-dialog" style="max-width: 1000px;">
<form
id="form-request-rma"
method="POST"
t-attf-action="/my/orders/#{sale_order.id}/requestrma?access_token=#{sale_order.access_token}"
class="modal-content"
>
<input
type="hidden"
name="csrf_token"
t-att-value="request.csrf_token()"
/>
<header class="modal-header">
<h4 class="modal-title">Request RMAs</h4>
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>&amp;times;</button>
</header>
<main class="modal-body" id="modal-body-request-rma">
<div class="alert alert-info mb-2 mb-sm-1" role="alert">
<span>
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:
<ul>
<li
>Select the product quantity and the requested operation</li>
<li
>Use the comment button to add relevant information regarding the RMA, like returned serial numbers or a description of the issue</li>
<li
>If no requested operation is set, the RMA won't be correctly fulfilled</li>
<li
>You can only return as much product units as you received for this order</li>
<li
>The limit will decrease when the units in other RMAs are confirmed</li>
<li
>You can send a message in every RMA sent</li>
</ul>
</span>
</div>
<t
t-set="data_list"
t-value="sale_order.get_delivery_rma_data()"
/>
<t
t-set="operations"
t-value="sale_order.env['rma.operation'].search([])"
/>
<table class="table table-sm" id="request-rma-table">
<thead class="bg-100">
<tr>
<th class="text-left">Product</th>
<th class="text-right">Quantity</th>
<th class="text-left">Delivery</th>
<th class="text-left">Requested operation</th>
<th name="portal_rma_button_desc" />
</tr>
</thead>
<tbody class="request-rma-tbody">
<t t-foreach="data_list" t-as="data">
<t t-if="data['quantity'] > 0">
<tr>
<td class="text-left">
<span
t-esc="data['product'].display_name"
/>
<input
type="hidden"
t-attf-name="#{data_index}-product_id"
t-att-value="data['product'].id"
/>
</td>
<td class="text-right">
<div id="delivery-rma-qty">
<input
type="number"
t-attf-name="#{data_index}-quantity"
class="o_input text-right"
placeholder="0"
min="0"
t-att-max="data['quantity']"
t-att-value="0"
style="max-width: 60px;"
/>
<span
t-esc="data['uom'].name"
groups="uom.group_uom"
/>
<input
type="hidden"
t-attf-name="#{data_index}-uom_id"
t-att-value="data['uom'].id"
/>
</div>
</td>
<td class="text-left">
<span
t-if="data['picking']"
t-esc="data['picking'].name"
/>
<input
type="hidden"
t-attf-name="#{data_index}-picking_id"
t-att-value="data['picking'].id"
/>
</td>
<td class="text-left">
<select
t-attf-name="#{data_index}-operation_id"
class="form-control"
>
<option value="">---</option>
<t
t-foreach="operations"
t-as="operation"
>
<option
t-att-value="operation.id"
>
<t
t-esc="operation.name"
/>
</option>
</t>
</select>
</td>
<td>
<button
class="btn btn-primary fa fa-comments"
type="button"
data-toggle="collapse"
t-attf-data-target="#comment-#{data_index}"
aria-expanded="false"
t-attf-aria-controls="comment-#{data_index}"
/>
</td>
</tr>
<tr
class="collapse"
t-attf-id="comment-#{data_index}"
>
<td colspan="5">
<textarea
class="form-control o_website_form_input"
t-attf-name="#{data_index}-description"
placeholder="Comment anything relevant to the return, like serial numbers, a description of the issue, etc"
/>
</td>
</tr>
</t>
</t>
</tbody>
</table>
</main>
<footer class="modal-footer">
<button
type="submit"
t-att-id="sale_order.id"
class="btn btn-primary"
><i class="fa fa-check" /> Request RMAs</button>
<button
type="button"
class="btn btn-danger"
data-dismiss="modal"
><i class="fa fa-times" /> Cancel</button>
</footer>
</form>
</div>
</div>
</xpath>
</template>
<template
id="sale_order_portal_content"
name="Show RMAs"
inherit_id="sale.sale_order_portal_content"
>
<xpath expr="//div[@id='introduction']/h2[hasclass('my-0')]" position="inside">
<span t-if="sale_order.rma_count" class="float-right">
<a
role="button"
t-attf-href="/my/rmas?sale_id=#{sale_order.id}"
class="btn btn-sm btn-secondary"
>
<span class="fa fa-reply" role="img" aria-label="RMA" title="RMA" />
<span t-esc="sale_order.rma_count" />
<span>RMA</span>
</a>
</span>
</xpath>
</template>
<template id="portal_rma_page" name="Show RMAs" inherit_id="rma.portal_rma_page">
<xpath expr="//div[@t-if='rma.picking_id']" position="before">
<div t-if="rma.order_id" class="row mb-2 mb-sm-1">
<div class="col-12 col-sm-4">
<strong>Sale order</strong>
</div>
<div class="col-12 col-sm-8">
<span t-field="rma.order_id" />
</div>
</div>
</xpath>
<xpath expr="//div[@t-if='rma.origin']" position="after">
<div t-if="rma.operation_id" class="row mb-2 mb-sm-1">
<div class="col-12 col-sm-4">
<strong>Requested operation</strong>
</div>
<div class="col-12 col-sm-8">
<span t-field="rma.operation_id" />
</div>
</div>
</xpath>
</template>
</odoo>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_order_form" model="ir.ui.view">
<field name="name">sale.order.form.inherit</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form" />
<field name="groups_id" eval="[(4, ref('rma.rma_group_user_own'))]" />
<field name="arch" type="xml">
<button name="action_draft" position="after">
<button
name="action_create_rma"
type="object"
string="Create RMA"
states="sale,done"
/>
</button>
<div name="button_box">
<button
name="action_view_rma"
type="object"
class="oe_stat_button"
icon="fa-reply"
attrs="{'invisible': [('rma_count', '=', 0)]}"
>
<field name="rma_count" widget="statinfo" string="RMA" />
</button>
</div>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import sale_order_rma_wizard

View File

@@ -0,0 +1,159 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
class SaleOrderRmaWizard(models.TransientModel):
_name = "sale.order.rma.wizard"
_description = "Sale Order Rma Wizard"
def _domain_location_id(self):
rma_loc = self.env["stock.warehouse"].search([]).mapped("rma_loc_id")
return [("id", "child_of", rma_loc.ids)]
order_id = fields.Many2one(
comodel_name="sale.order",
default=lambda self: self.env.context.get("active_id", False),
)
line_ids = fields.One2many(
comodel_name="sale.order.line.rma.wizard",
inverse_name="wizard_id",
string="Lines",
)
location_id = fields.Many2one(
comodel_name="stock.location",
string="RMA location",
domain=_domain_location_id,
default=lambda r: r.order_id.warehouse_id.rma_loc_id.id,
)
def create_rma(self, from_portal=None):
self.ensure_one()
lines = self.line_ids.filtered(lambda r: r.quantity > 0.0)
val_list = [line._prepare_rma_values() for line in lines]
rma = self.env["rma"].create(val_list)
# post messages
msg_list = [
'<a href="#" data-oe-model="rma" data-oe-id="%d">%s</a>' % (r.id, r.name)
for r in rma
]
msg = ", ".join(msg_list)
if len(msg_list) == 1:
self.order_id.message_post(body=_(msg + " has been created."))
elif len(msg_list) > 1:
self.order_id.message_post(body=_(msg + " have been created."))
rma.message_post_with_view(
"mail.message_origin_link",
values={"self": rma, "origin": self.order_id},
subtype_id=self.env.ref("mail.mt_note").id,
)
return rma
def create_and_open_rma(self):
self.ensure_one()
rma = self.create_rma()
for rec in rma:
rec.action_confirm()
action = self.env.ref("rma.rma_action").read()[0]
if len(rma) > 1:
action["domain"] = [("id", "in", rma.ids)]
elif rma:
action.update(
res_id=rma.id, view_mode="form", view_id=False, views=False,
)
return action
class SaleOrderLineRmaWizard(models.TransientModel):
_name = "sale.order.line.rma.wizard"
_description = "Sale Order Line Rma Wizard"
wizard_id = fields.Many2one(comodel_name="sale.order.rma.wizard", string="Wizard")
order_id = fields.Many2one(
comodel_name="sale.order",
default=lambda self: self.env["sale.order"].browse(
self.env.context.get("active_id", False)
),
)
allowed_product_ids = fields.Many2many(
comodel_name="product.product", compute="_compute_allowed_product_ids"
)
product_id = fields.Many2one(
comodel_name="product.product",
string="Product",
required=True,
domain="[('id', 'in', allowed_product_ids)]",
)
uom_category_id = fields.Many2one(
comodel_name="uom.category", related="product_id.uom_id.category_id",
)
quantity = fields.Float(
string="Quantity", digits="Product Unit of Measure", required=True,
)
uom_id = fields.Many2one(
comodel_name="uom.uom",
string="Unit of Measure",
domain="[('category_id', '=', uom_category_id)]",
required=True,
)
allowed_picking_ids = fields.Many2many(
comodel_name="stock.picking", compute="_compute_allowed_picking_ids"
)
picking_id = fields.Many2one(
comodel_name="stock.picking",
string="Delivery order",
domain="[('id', 'in', allowed_picking_ids)]",
)
move_id = fields.Many2one(comodel_name="stock.move", compute="_compute_move_id")
operation_id = fields.Many2one(
comodel_name="rma.operation", string="Requested operation",
)
description = fields.Text()
@api.onchange("product_id")
def onchange_product_id(self):
self.picking_id = False
@api.depends("picking_id")
def _compute_move_id(self):
for record in self:
if record.picking_id:
record.move_id = record.picking_id.move_lines.filtered(
lambda r: (
r.sale_line_id.product_id == record.product_id
and r.sale_line_id.order_id == record.order_id
)
)
@api.depends("order_id")
def _compute_allowed_product_ids(self):
for record in self:
product_ids = record.order_id.order_line.mapped("product_id.id")
record.allowed_product_ids = product_ids
@api.depends("product_id")
def _compute_allowed_picking_ids(self):
for record in self:
line = record.order_id.order_line.filtered(
lambda r: r.product_id == record.product_id
)
record.allowed_picking_ids = line.mapped("move_ids.picking_id")
def _prepare_rma_values(self):
self.ensure_one()
return {
"partner_id": self.order_id.partner_id.id,
"partner_invoice_id": self.order_id.partner_invoice_id.id,
"origin": self.order_id.name,
"company_id": self.order_id.company_id.id,
"location_id": self.wizard_id.location_id.id,
"order_id": self.order_id.id,
"picking_id": self.picking_id.id,
"move_id": self.move_id.id,
"product_id": self.product_id.id,
"product_uom_qty": self.quantity,
"product_uom": self.uom_id.id,
"operation_id": self.operation_id.id,
"description": self.description,
}

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="sale_order_create_rma_action" model="ir.actions.act_window">
<field name="name">Create RMAs</field>
<field name="res_model">sale.order.rma.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<record id="=sale_order_rma_wizard_form_view" model="ir.ui.view">
<field name="name">sale.order.rma.wizard.form</field>
<field name="model">sale.order.rma.wizard</field>
<field name="arch" type="xml">
<form>
<group>
<field name="line_ids" nolabel="1">
<tree editable="bottom">
<field name="order_id" invisible="1" />
<field name="allowed_product_ids" invisible="1" />
<field name="product_id" options="{'no_create': True}" />
<field name="quantity" />
<field name="uom_category_id" invisible="1" />
<field
name="uom_id"
groups="uom.group_uom"
options="{'no_create': True}"
/>
<field name="allowed_picking_ids" invisible="1" />
<field name="picking_id" options="{'no_create': True}" />
<field name="operation_id" />
</tree>
</field>
</group>
<group>
<field
name="location_id"
options="{'no_create': True, 'no_open': True}"
groups="stock.group_stock_multi_locations"
required="1"
/>
</group>
<footer>
<button
name="create_and_open_rma"
string="Accept"
type="object"
class="btn-primary"
/>
<button string="Cancel" class="btn-secondary" special="cancel" />
</footer>
</form>
</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
../../../../rma_sale

6
setup/rma_sale/setup.py Normal file
View File

@@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)