From 0beebad0ffa9df2295ef5104e1092dcb39f4f903 Mon Sep 17 00:00:00 2001 From: JPR Date: Thu, 4 Apr 2019 10:06:29 +0000 Subject: [PATCH] [IMP] sale, sale_management: avoid reload when add optional product added in portal porpose of the task is to avoid the reload of the web client when you add an optional product, in the customer portal this commit will fix the issue of window reload when add optional product and delete product in customer portal. removed order line from sale order, when a customer set the quantity of an option line to 0 in the portal task-1961015 Closes #32551 Signed-off-by: Yannick Tivisse (yti) Co-authored-by: mba-odoo --- addons/sale/views/sale_portal_templates.xml | 47 +---- addons/sale_management/controllers/portal.py | 71 ++++--- .../static/src/js/sale_management.js | 178 ++++++++++-------- .../views/sale_portal_templates.xml | 12 +- 4 files changed, 152 insertions(+), 156 deletions(-) diff --git a/addons/sale/views/sale_portal_templates.xml b/addons/sale/views/sale_portal_templates.xml index c8bbb314ebc..90e9d03ce4b 100644 --- a/addons/sale/views/sale_portal_templates.xml +++ b/addons/sale/views/sale_portal_templates.xml @@ -310,7 +310,7 @@ -
+
@@ -428,7 +428,7 @@ - +
@@ -519,48 +519,7 @@
- -
Products
- - - - - - - - - - - - - - - - - - - - -
Subtotal - -
- -  on  - - - - - - -
Total - -
+
diff --git a/addons/sale_management/controllers/portal.py b/addons/sale_management/controllers/portal.py index eb4e945b8d3..a2690237709 100644 --- a/addons/sale_management/controllers/portal.py +++ b/addons/sale_management/controllers/portal.py @@ -12,12 +12,27 @@ from odoo.addons.sale.controllers.portal import CustomerPortal class CustomerPortal(CustomerPortal): - @http.route(['/my/orders//update_line'], type='json', auth="public", website=True) - def update(self, line_id, remove=False, unlink=False, order_id=None, access_token=None, **post): - values = self.update_line_dict(line_id, remove, unlink, order_id, access_token, **post) - if values: - return [values['order_line_product_uom_qty'], values['order_amount_total']] - return values + def _get_portal_order_details(self, order_sudo, order_line=False): + currency = order_sudo.currency_id + format_price = partial(formatLang, request.env, digits=currency.decimal_places) + results = { + 'order_amount_total': format_price(order_sudo.amount_total), + 'order_amount_untaxed': format_price(order_sudo.amount_untaxed), + 'order_amount_tax': format_price(order_sudo.amount_tax), + 'order_amount_undiscounted': format_price(order_sudo.amount_undiscounted), + } + if order_line: + results.update({ + 'order_line_product_uom_qty': str(order_line.product_uom_qty), + 'order_line_price_total': format_price(order_line.price_total), + 'order_line_price_subtotal': format_price(order_line.price_subtotal) + }) + try: + results['order_totals_table'] = request.env['ir.ui.view'].render_template('sale.sale_order_portal_content_totals_table', {'sale_order': order_sudo}) + except ValueError: + pass + + return results @http.route(['/my/orders//update_line_dict'], type='json', auth="public", website=True) def update_line_dict(self, line_id, remove=False, unlink=False, order_id=None, access_token=None, input_quantity=False, **kwargs): @@ -31,9 +46,6 @@ class CustomerPortal(CustomerPortal): order_line = request.env['sale.order.line'].sudo().browse(int(line_id)) if order_line.order_id != order_sudo: return False - if unlink: - order_line.unlink() - return False # return False to reload the page, the line must move back to options and the JS doesn't handle it if input_quantity is not False: quantity = input_quantity @@ -41,29 +53,24 @@ class CustomerPortal(CustomerPortal): number = -1 if remove else 1 quantity = order_line.product_uom_qty + number - if quantity < 0: - quantity = 0.0 - order_line.write({'product_uom_qty': quantity}) - currency = order_sudo.currency_id - format_price = partial(formatLang, request.env, digits=currency.decimal_places) + if unlink or quantity <= 0: + order_line.unlink() + results = self._get_portal_order_details(order_sudo) + results.update({ + 'unlink': True, + 'sale_template': request.env['ir.ui.view'].render_template('sale.sale_order_portal_content', { + 'sale_order': order_sudo, + 'report_type': "html" + }), + }) + return results - results = { - 'order_line_product_uom_qty': str(quantity), - 'order_line_price_total': format_price(order_line.price_total), - 'order_line_price_subtotal': format_price(order_line.price_subtotal), - 'order_amount_total': format_price(order_sudo.amount_total), - 'order_amount_untaxed': format_price(order_sudo.amount_untaxed), - 'order_amount_tax': format_price(order_sudo.amount_tax), - 'order_amount_undiscounted': format_price(order_sudo.amount_undiscounted), - } - try: - results['order_totals_table'] = request.env['ir.ui.view'].render_template('sale.sale_order_portal_content_totals_table', {'sale_order': order_sudo}) - except ValueError: - pass + order_line.write({'product_uom_qty': quantity}) + results = self._get_portal_order_details(order_sudo, order_line) return results - @http.route(["/my/orders//add_option/"], type='http', auth="public", website=True) + @http.route(["/my/orders//add_option/"], type='json', auth="public", website=True) def add(self, order_id, option_id, access_token=None, **post): try: order_sudo = self._document_check_access('sale.order', order_id, access_token=access_token) @@ -76,5 +83,9 @@ class CustomerPortal(CustomerPortal): return request.redirect(order_sudo.get_portal_url()) option_sudo.add_option_to_order() - - return request.redirect(option_sudo.order_id.get_portal_url(anchor='details')) + results = self._get_portal_order_details(order_sudo) + results['sale_template'] = request.env['ir.ui.view'].render_template("sale.sale_order_portal_content", { + 'sale_order': option_sudo.order_id, + 'report_type': "html" + }) + return results diff --git a/addons/sale_management/static/src/js/sale_management.js b/addons/sale_management/static/src/js/sale_management.js index 7092ac06355..eaa126ccabf 100644 --- a/addons/sale_management/static/src/js/sale_management.js +++ b/addons/sale_management/static/src/js/sale_management.js @@ -4,56 +4,88 @@ odoo.define('sale_management.sale_management', function (require) { var publicWidget = require('web.public.widget'); publicWidget.registry.SaleUpdateLineButton = publicWidget.Widget.extend({ - selector: '.o_portal_sale_sidebar a.js_update_line_json', + selector: '.o_portal_sale_sidebar', events: { - 'click': '_onClick', + 'click a.js_update_line_json': '_onClick', + 'click a.js_add_optional_products': '_onClickOptionalProduct', + 'change .js_quantity': '_onChangeQuantity' }, /** * @override */ - start: function () { - var self = this; - return this._super.apply(this, arguments).then(function () { - self.elems = self._getUpdatableElements(); - self.elems.$lineQuantity.change(function (ev) { - var quantity = parseInt(this.value); - self._onChangeQuantity(quantity); - }); - }); - }, + async start() { + await this._super(...arguments); + this.orderDetail = this.$el.find('table#sales_order_table').data(); + this.elems = this._getUpdatableElements(); + }, /** * Process the change in line quantity * * @private - * @param {Int} quantity, the new quantity of the line - * If not present it will increment/decrement the existing quantity + * @param {Event} ev */ - _onChangeQuantity: function (quantity) { - var href = this.$el.attr("href"); - var orderID = href.match(/my\/orders\/([0-9]+)/); - var lineID = href.match(/update_line\/([0-9]+)/); - var params = { - 'line_id': parseInt(lineID[1]), - 'remove': this.$el.is('[href*="remove"]'), - 'unlink': this.$el.is('[href*="unlink"]'), - 'input_quantity': quantity >= 0 ? quantity : false, - }; - var token = href.match(/token=([\w\d-]*)/)[1]; - if (token) { - params['access_token'] = token; - } + _onChangeQuantity(ev) { + ev.preventDefault(); + let self = this, + $target = $(ev.currentTarget), + quantity = parseInt($target.val()); - orderID = parseInt(orderID[1]); - this._callUpdateLineRoute(orderID, params).then(this._updateOrderValues.bind(this)); + this._callUpdateLineRoute(self.orderDetail.orderId, { + 'line_id': $target.data('lineId'), + 'input_quantity': quantity >= 0 ? quantity : false, + 'access_token': self.orderDetail.token + }).then((data) => { + self._updateOrderLineValues($target.closest('tr'), data); + self._updateOrderValues(data); + }); }, /** * Reacts to the click on the -/+ buttons * * @param {Event} ev */ - _onClick: function (ev) { + _onClick(ev) { ev.preventDefault(); - return this._onChangeQuantity(); + let self = this, + $target = $(ev.currentTarget); + this._callUpdateLineRoute(self.orderDetail.orderId, { + 'line_id': $target.data('lineId'), + 'remove': $target.data('remove'), + 'unlink': $target.data('unlink'), + 'access_token': self.orderDetail.token + }).then((data) => { + var $saleTemplate = $(data['sale_template']); + if ($saleTemplate.length && data['unlink']) { + self.$('#portal_sale_content').html($saleTemplate); + self.elems = self._getUpdatableElements(); + } + self._updateOrderLineValues($target.closest('tr'), data); + self._updateOrderValues(data); + }); + }, + /** + * trigger when optional product added to order from portal. + * + * @private + * @param {Event} ev + */ + _onClickOptionalProduct(ev) { + ev.preventDefault(); + let self = this, + $target = $(ev.currentTarget); + // to avoid double click on link with href. + $target.css('pointer-events', 'none'); + + this._rpc({ + route: "/my/orders/" + self.orderDetail.orderId + "/add_option/" + $target.data('optionId'), + params: {access_token: self.orderDetail.token} + }).then((data) => { + if (data) { + self.$('#portal_sale_content').html($(data['sale_template'])); + self.elems = self._getUpdatableElements(); + self._updateOrderValues(data); + } + }); }, /** * Calls the route to get updated values of the line and order @@ -64,43 +96,48 @@ publicWidget.registry.SaleUpdateLineButton = publicWidget.Widget.extend({ * @param {Object} params * @return {Deferred} */ - _callUpdateLineRoute: function (order_id, params) { - var url = "/my/orders/" + order_id + "/update_line_dict"; + _callUpdateLineRoute(order_id, params) { return this._rpc({ - route: url, + route: "/my/orders/" + order_id + "/update_line_dict", params: params, }); }, + /** + * Processes data from the server to update the orderline UI + * + * @private + * @param {Element} $orderLine: orderline element to update + * @param {Object} data: contains order and line updated values + */ + _updateOrderLineValues($orderLine, data) { + let linePriceTotal = data.order_line_price_total, + linePriceSubTotal = data.order_line_price_subtotal, + $linePriceTotal = $orderLine.find('.oe_order_line_price_total .oe_currency_value'), + $linePriceSubTotal = $orderLine.find('.oe_order_line_price_subtotal .oe_currency_value'); + + if (!$linePriceTotal.length && !$linePriceSubTotal.length) { + $linePriceTotal = $linePriceSubTotal = $orderLine.find('.oe_currency_value').last(); + } + + $orderLine.find('.js_quantity').val(data.order_line_product_uom_qty); + if ($linePriceTotal.length && linePriceTotal !== undefined) { + $linePriceTotal.text(linePriceTotal); + } + if ($linePriceSubTotal.length && linePriceSubTotal !== undefined) { + $linePriceSubTotal.text(linePriceSubTotal); + } + }, /** * Processes data from the server to update the UI * * @private * @param {Object} data: contains order and line updated values */ - _updateOrderValues: function (data) { - if (!data) { - window.location.reload(); - } - - var orderAmountTotal = data.order_amount_total; - var orderAmountUntaxed = data.order_amount_untaxed; - var orderAmountTax = data.order_amount_tax; - var orderAmountUndiscounted = data.order_amount_undiscounted; - var orderTotalsTable = $(data.order_totals_table); - - var lineProductUomQty = data.order_line_product_uom_qty; - var linePriceTotal = data.order_line_price_total; - var linePriceSubTotal = data.order_line_price_subtotal; - - this.elems.$lineQuantity.val(lineProductUomQty); - - if (this.elems.$linePriceTotal.length && linePriceTotal !== undefined) { - this.elems.$linePriceTotal.text(linePriceTotal); - } - if (this.elems.$linePriceSubTotal.length && linePriceSubTotal !== undefined) { - this.elems.$linePriceSubTotal.text(linePriceSubTotal); - } - + _updateOrderValues(data) { + let orderAmountTotal = data.order_amount_total, + orderAmountUntaxed = data.order_amount_untaxed, + orderAmountUndiscounted = data.order_amount_undiscounted, + $orderTotalsTable = $(data.order_totals_table); if (orderAmountUntaxed !== undefined) { this.elems.$orderAmountUntaxed.text(orderAmountUntaxed); } @@ -112,8 +149,8 @@ publicWidget.registry.SaleUpdateLineButton = publicWidget.Widget.extend({ if (orderAmountUndiscounted !== undefined) { this.elems.$orderAmountUndiscounted.text(orderAmountUndiscounted); } - if (orderTotalsTable) { - this.elems.$orderTotalsTable.find('table').replaceWith(orderTotalsTable); + if ($orderTotalsTable.length) { + this.elems.$orderTotalsTable.find('table').replaceWith($orderTotalsTable); } }, /** @@ -124,18 +161,10 @@ publicWidget.registry.SaleUpdateLineButton = publicWidget.Widget.extend({ * @private * @return {Object}: Jquery elements to update */ - _getUpdatableElements: function () { - var $parentTr = this.$el.parents('tr:first'); - var $linePriceTotal = $parentTr.find('.oe_order_line_price_total .oe_currency_value'); - var $linePriceSubTotal = $parentTr.find('.oe_order_line_price_subtotal .oe_currency_value'); - - if (!$linePriceTotal.length && !$linePriceSubTotal.length) { - $linePriceTotal = $linePriceSubTotal = $parentTr.find('.oe_currency_value').last(); - } - - var $orderAmountUntaxed = $('[data-id="total_untaxed"]').find('span, b'); - var $orderAmountTotal = $('[data-id="total_amount"]').find('span, b'); - var $orderAmountUndiscounted = $('[data-id="amount_undiscounted"]').find('span, b'); + _getUpdatableElements() { + let $orderAmountUntaxed = $('[data-id="total_untaxed"]').find('span, b'), + $orderAmountTotal = $('[data-id="total_amount"]').find('span, b'), + $orderAmountUndiscounted = $('[data-id="amount_undiscounted"]').find('span, b'); if (!$orderAmountUntaxed.length) { $orderAmountUntaxed = $orderAmountTotal.eq(1); @@ -143,9 +172,6 @@ publicWidget.registry.SaleUpdateLineButton = publicWidget.Widget.extend({ } return { - $lineQuantity: this.$el.closest('.input-group').find('.js_quantity'), - $linePriceSubTotal: $linePriceSubTotal, - $linePriceTotal: $linePriceTotal, $orderAmountUntaxed: $orderAmountUntaxed, $orderAmountTotal: $orderAmountTotal, $orderTotalsTable: $('#total'), diff --git a/addons/sale_management/views/sale_portal_templates.xml b/addons/sale_management/views/sale_portal_templates.xml index 1f7fbcccf71..d248f2d2c2d 100644 --- a/addons/sale_management/views/sale_portal_templates.xml +++ b/addons/sale_management/views/sale_portal_templates.xml @@ -21,7 +21,7 @@ - + @@ -65,8 +65,8 @@ - - + + @@ -83,16 +83,16 @@ - +