mirror of
https://github.com/OCA/rma.git
synced 2025-02-16 17:11:47 +02:00
[IMP] rma_sale: portal rma request single page view
Now it's possible to configure if the portal RMA request form is loaded in a popup or in a single page. In that page, we can add custom blocks (if the website is installed) a customize the form text. In this commit, we also add the possibility to extend the form view to allow custom fields that will show up in the RMA description. TT29670
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
"views/rma_views.xml",
|
"views/rma_views.xml",
|
||||||
"views/sale_views.xml",
|
"views/sale_views.xml",
|
||||||
"views/sale_portal_template.xml",
|
"views/sale_portal_template.xml",
|
||||||
|
"views/res_config_settings_views.xml",
|
||||||
"wizard/sale_order_rma_wizard_views.xml",
|
"wizard/sale_order_rma_wizard_views.xml",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,12 +30,18 @@ class CustomerPortal(CustomerPortal):
|
|||||||
}
|
}
|
||||||
# Set wizard line vals
|
# Set wizard line vals
|
||||||
mapped_vals = {}
|
mapped_vals = {}
|
||||||
|
custom_vals = {}
|
||||||
partner_shipping_id = post.pop("partner_shipping_id", False)
|
partner_shipping_id = post.pop("partner_shipping_id", False)
|
||||||
for name, value in post.items():
|
for name, value in post.items():
|
||||||
row, field_name = name.split("-", 1)
|
try:
|
||||||
if wizard_line_field_types.get(field_name) == "many2one":
|
row, field_name = name.split("-", 1)
|
||||||
value = int(value) if value else False
|
if wizard_line_field_types.get(field_name) == "many2one":
|
||||||
mapped_vals.setdefault(row, {}).update({field_name: value})
|
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
|
# If no operation is filled, no RMA will be created
|
||||||
line_vals = [
|
line_vals = [
|
||||||
(0, 0, vals) for vals in mapped_vals.values() if vals.get("operation_id")
|
(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
|
# Create wizard an generate rmas
|
||||||
order = order_obj.browse(order_id).sudo()
|
order = order_obj.browse(order_id).sudo()
|
||||||
location_id = order.warehouse_id.rma_loc_id.id
|
location_id = order.warehouse_id.rma_loc_id.id
|
||||||
|
# Add custom fields text
|
||||||
|
custom_description = ""
|
||||||
|
if custom_vals:
|
||||||
|
custom_description = r"<br \>---<br \>"
|
||||||
|
custom_description += r"<br \>".join(
|
||||||
|
["{}: {}".format(x, y) for x, y in custom_vals.items()]
|
||||||
|
)
|
||||||
wizard = wizard_obj.with_context(active_id=order_id).create(
|
wizard = wizard_obj.with_context(active_id=order_id).create(
|
||||||
{
|
{
|
||||||
"line_ids": line_vals,
|
"line_ids": line_vals,
|
||||||
"location_id": location_id,
|
"location_id": location_id,
|
||||||
"partner_shipping_id": partner_shipping_id,
|
"partner_shipping_id": partner_shipping_id,
|
||||||
|
"custom_description": custom_description,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
rma = wizard.sudo().create_rma(from_portal=True)
|
rma = wizard.sudo().create_rma(from_portal=True)
|
||||||
@@ -61,3 +75,27 @@ class CustomerPortal(CustomerPortal):
|
|||||||
else:
|
else:
|
||||||
route = "/my/rmas?sale_id=%d" % order_id
|
route = "/my/rmas?sale_id=%d" % order_id
|
||||||
return request.redirect(route)
|
return request.redirect(route)
|
||||||
|
|
||||||
|
@http.route(
|
||||||
|
["/my/requestrma/<int:order_id>"], 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)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
# 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 rma
|
||||||
from . import sale
|
from . import sale
|
||||||
from . import stock_move
|
from . import stock_move
|
||||||
|
|||||||
13
rma_sale/models/res_company.py
Normal file
13
rma_sale/models/res_company.py
Normal file
@@ -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",
|
||||||
|
)
|
||||||
11
rma_sale/models/res_config_settings.py
Normal file
11
rma_sale/models/res_config_settings.py
Normal file
@@ -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,
|
||||||
|
)
|
||||||
36
rma_sale/views/res_config_settings_views.xml
Normal file
36
rma_sale/views/res_config_settings_views.xml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||||
|
<field name="model">res.config.settings</field>
|
||||||
|
<field name="inherit_id" ref="sale.res_config_settings_view_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath
|
||||||
|
expr="//div[@data-key='sale_management']/div[hasclass('o_settings_container')]"
|
||||||
|
position="inside"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12 col-lg-6 o_setting_box"
|
||||||
|
title="Show portal RMA request in a single page"
|
||||||
|
>
|
||||||
|
<div class="o_setting_left_pane">
|
||||||
|
<field name="show_full_page_sale_rma" />
|
||||||
|
</div>
|
||||||
|
<div class="o_setting_right_pane">
|
||||||
|
<label
|
||||||
|
for="show_full_page_sale_rma"
|
||||||
|
string="Single page RMA request"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="fa fa-lg fa-building-o"
|
||||||
|
title="Values set here are company-specific."
|
||||||
|
groups="base.group_multi_company"
|
||||||
|
/>
|
||||||
|
<div class="text-muted">
|
||||||
|
When we hit the RMA request button from the portal sale page, open in a single page instead of a popup.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
@@ -1,4 +1,194 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
|
<!-- Call this form via controller to add it to an independent page -->
|
||||||
|
<template id="sale_rma_request_form" name="RMA Request Form">
|
||||||
|
<form
|
||||||
|
id="form-request-rma"
|
||||||
|
method="POST"
|
||||||
|
t-attf-action="/my/orders/#{sale_order.id}/requestrma?access_token=#{sale_order.access_token}"
|
||||||
|
t-att-class="not single_page_mode and 'modal-content' or 'col-12'"
|
||||||
|
>
|
||||||
|
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
|
||||||
|
<header class="modal-header" t-if="not single_page_mode">
|
||||||
|
<h4 class="modal-title">Request RMAs</h4>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="close"
|
||||||
|
data-dismiss="modal"
|
||||||
|
aria-label="Close"
|
||||||
|
>&times;</button>
|
||||||
|
</header>
|
||||||
|
<main
|
||||||
|
t-att-class="not single_page_mode and 'modal-body'"
|
||||||
|
id="modal-body-request-rma"
|
||||||
|
>
|
||||||
|
<div class="alert alert-info mb-2 mb-sm-1 oe_structure" 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="delivery_addresses"
|
||||||
|
t-value="sale_order.partner_shipping_id | sale_order.partner_id.commercial_partner_id.mapped('child_ids').filtered(lambda x: x.type in ['contact', 'delivery'])"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="btn btn-primary btn-block mb8"
|
||||||
|
type="button"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-target="#delivery_address_picker"
|
||||||
|
aria-expanded="false"
|
||||||
|
><i class="fa fa-truck" /> Choose a delivery address</button>
|
||||||
|
<div class="col-lg-12 collapse mt8" id="delivery_address_picker">
|
||||||
|
<div data-toggle="buttons" class="row">
|
||||||
|
<label
|
||||||
|
t-attf-class="card mr4 btn btn-light #{address == sale_order.partner_shipping_id and 'active' or ''}"
|
||||||
|
t-foreach="delivery_addresses"
|
||||||
|
t-as="address"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="d-none"
|
||||||
|
type="radio"
|
||||||
|
name="partner_shipping_id"
|
||||||
|
t-att-value="address.id"
|
||||||
|
>
|
||||||
|
<strong>
|
||||||
|
<i
|
||||||
|
t-attf-class="text-secondary fa #{address.type == 'delivery' and 'fa-truck' or 'fa-user'}"
|
||||||
|
/>
|
||||||
|
<t t-esc="address.name" />
|
||||||
|
</strong>
|
||||||
|
<pre><h6 t-esc="address.contact_address" /></pre>
|
||||||
|
</input>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</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 and data['picking']">
|
||||||
|
<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"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
t-if="data.get('sale_line_id')"
|
||||||
|
t-attf-name="#{data_index}-sale_line_id"
|
||||||
|
t-att-value="data['sale_line_id'].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-esc="data['picking'] and data['picking'].name"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
t-attf-name="#{data_index}-picking_id"
|
||||||
|
t-att-value="data['picking'] and data['picking'].id"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td class="text-left">
|
||||||
|
<select
|
||||||
|
t-attf-name="#{data_index}-operation_id"
|
||||||
|
class="form-control rma-operation"
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
</template>
|
||||||
<template
|
<template
|
||||||
id="sale_order_portal_template"
|
id="sale_order_portal_template"
|
||||||
name="Request RMA"
|
name="Request RMA"
|
||||||
@@ -13,236 +203,37 @@
|
|||||||
class="list-group-item flex-grow-1"
|
class="list-group-item flex-grow-1"
|
||||||
id="li-request-rma"
|
id="li-request-rma"
|
||||||
>
|
>
|
||||||
|
<t t-if="sale_order.company_id.show_full_page_sale_rma">
|
||||||
<a
|
<a
|
||||||
role="button"
|
role="button"
|
||||||
class="btn btn-secondary btn-block mb8"
|
class="btn btn-secondary btn-block mb8"
|
||||||
data-toggle="modal"
|
t-attf-href="/my/requestrma/#{sale_order.id}"
|
||||||
data-target="#modal-request-rma"
|
>
|
||||||
href="#"
|
|
||||||
>
|
|
||||||
<i class="fa fa-reply" /> Request RMAs
|
<i class="fa fa-reply" /> Request RMAs
|
||||||
</a>
|
</a>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<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>
|
||||||
|
</t>
|
||||||
</li>
|
</li>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//div[@id='modaldecline']" position="after">
|
<xpath expr="//div[@id='modaldecline']" position="after">
|
||||||
<div role="dialog" class="modal fade" id="modal-request-rma">
|
<div
|
||||||
|
role="dialog"
|
||||||
|
class="modal fade"
|
||||||
|
id="modal-request-rma"
|
||||||
|
t-if="not sale_order.company_id.show_full_page_sale_rma"
|
||||||
|
>
|
||||||
<div class="modal-dialog" style="max-width: 1000px;">
|
<div class="modal-dialog" style="max-width: 1000px;">
|
||||||
<form
|
<t t-call="rma_sale.sale_rma_request_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"
|
|
||||||
>&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="delivery_addresses"
|
|
||||||
t-value="sale_order.partner_id.commercial_partner_id.mapped('child_ids').filtered(lambda x: x.type in ['contact', 'delivery'])"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
class="btn btn-primary btn-block mb8"
|
|
||||||
type="button"
|
|
||||||
data-toggle="collapse"
|
|
||||||
data-target="#delivery_address_picker"
|
|
||||||
aria-expanded="false"
|
|
||||||
><i
|
|
||||||
class="fa fa-truck"
|
|
||||||
/> Choose a delivery address</button>
|
|
||||||
<div
|
|
||||||
class="col-lg-12 collapse mt8"
|
|
||||||
id="delivery_address_picker"
|
|
||||||
>
|
|
||||||
<div data-toggle="buttons" class="row">
|
|
||||||
<label
|
|
||||||
t-attf-class="card mr4 btn btn-light"
|
|
||||||
t-foreach="delivery_addresses"
|
|
||||||
t-as="address"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
class="d-none"
|
|
||||||
type="radio"
|
|
||||||
name="partner_shipping_id"
|
|
||||||
t-att-value="address.id"
|
|
||||||
>
|
|
||||||
<strong>
|
|
||||||
<i
|
|
||||||
t-attf-class="text-secondary fa #{address.type == 'delivery' and 'fa-truck' or 'fa-user'}"
|
|
||||||
/>
|
|
||||||
<t t-esc="address.name" />
|
|
||||||
</strong>
|
|
||||||
<pre><h6
|
|
||||||
t-esc="address.contact_address"
|
|
||||||
/></pre>
|
|
||||||
</input>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</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 and data['picking']"
|
|
||||||
>
|
|
||||||
<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"
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
t-if="data.get('sale_line_id')"
|
|
||||||
t-attf-name="#{data_index}-sale_line_id"
|
|
||||||
t-att-value="data['sale_line_id'].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-esc="data['picking'] and data['picking'].name"
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
t-attf-name="#{data_index}-picking_id"
|
|
||||||
t-att-value="data['picking'] and data['picking'].id"
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
<td class="text-left">
|
|
||||||
<select
|
|
||||||
t-attf-name="#{data_index}-operation_id"
|
|
||||||
class="form-control rma-operation"
|
|
||||||
>
|
|
||||||
<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>
|
||||||
</div>
|
</div>
|
||||||
</xpath>
|
</xpath>
|
||||||
@@ -288,4 +279,49 @@
|
|||||||
</div>
|
</div>
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
|
<!-- Request RMA single view. When the website is installed, we can customize it adding blocks -->
|
||||||
|
<template id="request_rma_single_page" name="Request RMA (single page)">
|
||||||
|
<t t-call="portal.portal_layout">
|
||||||
|
<t t-call="portal.portal_record_layout">
|
||||||
|
<t t-set="card_header">
|
||||||
|
<h5 class="mb-0">
|
||||||
|
<span>
|
||||||
|
RMA request for order <t t-esc="sale_order.name" />
|
||||||
|
</span>
|
||||||
|
</h5>
|
||||||
|
</t>
|
||||||
|
<t t-set="card_body">
|
||||||
|
<div class="oe_structure" id="sale_rma_request_top_hook" />
|
||||||
|
<div id="request_form">
|
||||||
|
<div class="row">
|
||||||
|
<t t-call="rma_sale.sale_rma_request_form">
|
||||||
|
<t t-set="single_page_mode" t-value="True" />
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="oe_structure" id="sale_rma_request_bottom_hook" />
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
<!-- This way we can go back to the origin sale order easily -->
|
||||||
|
<template
|
||||||
|
id="portal_my_home_menu_sale"
|
||||||
|
inherit_id="sale.portal_my_home_menu_sale"
|
||||||
|
priority="99"
|
||||||
|
>
|
||||||
|
<xpath expr="//li[@t-if='sale_order']" position="before">
|
||||||
|
<t t-if="page_name != 'request_rma'" name="sale_breadcrumb" />
|
||||||
|
<t t-else="">
|
||||||
|
<li class="breadcrumb-item active">
|
||||||
|
<a t-if="sale_order" t-att-href="default_url"><t
|
||||||
|
t-esc="sale_order.name"
|
||||||
|
/></a>
|
||||||
|
</li>
|
||||||
|
</t>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//t[@name='sale_breadcrumb']" position="inside">
|
||||||
|
<xpath expr="//li[@t-if='sale_order']" position="move" />
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ class SaleOrderRmaWizard(models.TransientModel):
|
|||||||
string="Shipping Address",
|
string="Shipping Address",
|
||||||
help="Will be used to return the goods when the RMA is completed",
|
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):
|
def create_rma(self, from_portal=None):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
@@ -162,6 +165,9 @@ class SaleOrderLineRmaWizard(models.TransientModel):
|
|||||||
partner_shipping = (
|
partner_shipping = (
|
||||||
self.wizard_id.partner_shipping_id or self.order_id.partner_shipping_id
|
self.wizard_id.partner_shipping_id or self.order_id.partner_shipping_id
|
||||||
)
|
)
|
||||||
|
description = (self.description or "") + (
|
||||||
|
self.wizard_id.custom_description or ""
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
"partner_id": self.order_id.partner_id.id,
|
"partner_id": self.order_id.partner_id.id,
|
||||||
"partner_invoice_id": self.order_id.partner_invoice_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_qty": self.quantity,
|
||||||
"product_uom": self.uom_id.id,
|
"product_uom": self.uom_id.id,
|
||||||
"operation_id": self.operation_id.id,
|
"operation_id": self.operation_id.id,
|
||||||
"description": self.description,
|
"description": description,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user