diff --git a/rma_sale/__manifest__.py b/rma_sale/__manifest__.py index 75752cc6..fb3af4cf 100644 --- a/rma_sale/__manifest__.py +++ b/rma_sale/__manifest__.py @@ -17,6 +17,7 @@ "views/rma_views.xml", "views/sale_views.xml", "views/sale_portal_template.xml", + "views/res_config_settings_views.xml", "wizard/sale_order_rma_wizard_views.xml", ], } diff --git a/rma_sale/controllers/sale_portal.py b/rma_sale/controllers/sale_portal.py index e8eec8e6..eb5ab385 100644 --- a/rma_sale/controllers/sale_portal.py +++ b/rma_sale/controllers/sale_portal.py @@ -30,12 +30,18 @@ class CustomerPortal(CustomerPortal): } # Set wizard line vals mapped_vals = {} + custom_vals = {} partner_shipping_id = post.pop("partner_shipping_id", False) for name, value in post.items(): - row, field_name = name.split("-", 1) - if wizard_line_field_types.get(field_name) == "many2one": - value = int(value) if value else False - mapped_vals.setdefault(row, {}).update({field_name: value}) + try: + row, field_name = name.split("-", 1) + if wizard_line_field_types.get(field_name) == "many2one": + value = int(value) if value else False + mapped_vals.setdefault(row, {}).update({field_name: value}) + # Catch possible form custom fields to add them to the RMA + # description values + except ValueError: + custom_vals.update({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") @@ -43,11 +49,19 @@ class CustomerPortal(CustomerPortal): # Create wizard an generate rmas order = order_obj.browse(order_id).sudo() location_id = order.warehouse_id.rma_loc_id.id + # Add custom fields text + custom_description = "" + if custom_vals: + custom_description = r"---" + custom_description += r"".join( + ["{}: {}".format(x, y) for x, y in custom_vals.items()] + ) wizard = wizard_obj.with_context(active_id=order_id).create( { "line_ids": line_vals, "location_id": location_id, "partner_shipping_id": partner_shipping_id, + "custom_description": custom_description, } ) rma = wizard.sudo().create_rma(from_portal=True) @@ -61,3 +75,27 @@ class CustomerPortal(CustomerPortal): else: route = "/my/rmas?sale_id=%d" % order_id return request.redirect(route) + + @http.route( + ["/my/requestrma/"], type="http", auth="public", website=True + ) + def request_sale_rma(self, order_id, access_token=None, **kw): + """Request RMA on a single page""" + try: + order_sudo = self._document_check_access( + "sale.order", order_id, access_token=access_token + ) + except (AccessError, MissingError): + return request.redirect("/my") + if order_sudo.state in ("draft", "sent", "cancel"): + return request.redirect("/my") + values = { + "sale_order": order_sudo, + "page_name": "request_rma", + "default_url": order_sudo.get_portal_url(), + "token": access_token, + "partner_id": order_sudo.partner_id.id, + } + if order_sudo.company_id: + values["res_company"] = order_sudo.company_id + return request.render("rma_sale.request_rma_single_page", values) diff --git a/rma_sale/models/__init__.py b/rma_sale/models/__init__.py index 0090dd37..16972d9b 100644 --- a/rma_sale/models/__init__.py +++ b/rma_sale/models/__init__.py @@ -1,5 +1,6 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). - +from . import res_company +from . import res_config_settings from . import rma from . import sale from . import stock_move diff --git a/rma_sale/models/res_company.py b/rma_sale/models/res_company.py new file mode 100644 index 00000000..021eea2c --- /dev/null +++ b/rma_sale/models/res_company.py @@ -0,0 +1,13 @@ +# Copyright 2021 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + show_full_page_sale_rma = fields.Boolean( + string="Full page RMA creation", + help="From the frontend sale order page go to a single RMA page " + "creation instead of the usual popup", + ) diff --git a/rma_sale/models/res_config_settings.py b/rma_sale/models/res_config_settings.py new file mode 100644 index 00000000..dd42c753 --- /dev/null +++ b/rma_sale/models/res_config_settings.py @@ -0,0 +1,11 @@ +# Copyright 2021 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + show_full_page_sale_rma = fields.Boolean( + related="company_id.show_full_page_sale_rma", readonly=False, + ) diff --git a/rma_sale/views/res_config_settings_views.xml b/rma_sale/views/res_config_settings_views.xml new file mode 100644 index 00000000..61618781 --- /dev/null +++ b/rma_sale/views/res_config_settings_views.xml @@ -0,0 +1,36 @@ + + + + res.config.settings + + + + + + + + + + + + When we hit the RMA request button from the portal sale page, open in a single page instead of a popup. + + + + + + + diff --git a/rma_sale/views/sale_portal_template.xml b/rma_sale/views/sale_portal_template.xml index 78de3dc4..0150d4ab 100644 --- a/rma_sale/views/sale_portal_template.xml +++ b/rma_sale/views/sale_portal_template.xml @@ -1,4 +1,194 @@ + + + + + + Request RMAs + × + + + + + 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 + You can send a message in every RMA sent + + + + + Choose a delivery address + + + + + + + + + + + + + + + + + + + Product + Quantity + Delivery + Requested operation + + + + + + + + + + + + + + + + + + + + + + + + + + --- + + + + + + + + + + + + + + + + + + + + + + + + + + role="button" + class="btn btn-secondary btn-block mb8" + t-attf-href="/my/requestrma/#{sale_order.id}" + > Request RMAs + + + + Request RMAs + + - + - - - - Request RMAs - × - - - - - 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 - You can send a message in every RMA sent - - - - - Choose a delivery address - - - - - - - - - - - - - - - - - - - Product - Quantity - Delivery - Requested operation - - - - - - - - - - - - - - - - - - - - - - - - - - --- - - - - - - - - - - - - - - - - - - - - - - - + @@ -288,4 +279,49 @@ + + + + + + + + RMA request for order + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rma_sale/wizard/sale_order_rma_wizard.py b/rma_sale/wizard/sale_order_rma_wizard.py index 99270219..436bcc8d 100644 --- a/rma_sale/wizard/sale_order_rma_wizard.py +++ b/rma_sale/wizard/sale_order_rma_wizard.py @@ -37,6 +37,9 @@ class SaleOrderRmaWizard(models.TransientModel): string="Shipping Address", help="Will be used to return the goods when the RMA is completed", ) + custom_description = fields.Text( + help="Values coming from portal RMA request form custom fields", + ) def create_rma(self, from_portal=None): self.ensure_one() @@ -162,6 +165,9 @@ class SaleOrderLineRmaWizard(models.TransientModel): partner_shipping = ( self.wizard_id.partner_shipping_id or self.order_id.partner_shipping_id ) + description = (self.description or "") + ( + self.wizard_id.custom_description or "" + ) return { "partner_id": self.order_id.partner_id.id, "partner_invoice_id": self.order_id.partner_invoice_id.id, @@ -176,5 +182,5 @@ class SaleOrderLineRmaWizard(models.TransientModel): "product_uom_qty": self.quantity, "product_uom": self.uom_id.id, "operation_id": self.operation_id.id, - "description": self.description, + "description": description, }