diff --git a/addons/website_sale_delivery/__manifest__.py b/addons/website_sale_delivery/__manifest__.py index 3be003a3954..13c8309b6d4 100644 --- a/addons/website_sale_delivery/__manifest__.py +++ b/addons/website_sale_delivery/__manifest__.py @@ -12,7 +12,6 @@ Configure your own methods with a pricing grid or integrate with carriers for a 'views/website_sale_delivery_templates.xml', 'views/website_sale_delivery_views.xml', 'views/res_config_settings_views.xml', - 'views/locations_carrier_templates.xml', 'data/website_sale_delivery_data.xml' ], 'demo': [ diff --git a/addons/website_sale_delivery/controllers/main.py b/addons/website_sale_delivery/controllers/main.py index 91d841a488a..9d26aacffd1 100644 --- a/addons/website_sale_delivery/controllers/main.py +++ b/addons/website_sale_delivery/controllers/main.py @@ -28,7 +28,7 @@ class WebsiteSaleDelivery(WebsiteSale): return super(WebsiteSaleDelivery, self).shop_payment(**post) - @http.route(['/shop/update_carrier'], type='json', auth='public', methods=['POST'], website=True, csrf=False) + @http.route(['/shop/update_carrier'], type='json', auth='public', methods=['POST'], website=True) def update_eshop_carrier(self, **post): order = request.website.sale_get_order() order.access_point_address = {} @@ -203,39 +203,40 @@ class WebsiteSaleDelivery(WebsiteSale): order_sudo.currency_id, ), } for carrier in order_sudo._get_delivery_methods()], - key=lambda carrier: carrier['minorAmount']) + key=lambda carrier: carrier['minorAmount']) - @http.route('/shop/access_point/set', type='json', auth='public', methods=['POST'], csrf=False, website=True, sitemap=False) + @http.route('/shop/access_point/set', type='json', auth='public', methods=['POST'], website=True, sitemap=False) def set_access_point(self, access_point_encoded): order = request.website.sale_get_order() if hasattr(order.carrier_id, order.carrier_id.delivery_type + '_use_locations'): use_location = getattr(order.carrier_id, order.carrier_id.delivery_type + '_use_locations') - access_point = use_location and access_point_encoded or None + access_point = use_location and (json.loads(access_point_encoded) if access_point_encoded else False) or False order.write({'access_point_address': access_point}) - @http.route('/shop/access_point/get', type='json', auth='public', csrf=False, website=True, sitemap=False) + @http.route('/shop/access_point/get', type='json', auth='public', website=True, sitemap=False) def get_access_point(self): order = request.website.sale_get_order() - if not order.carrier_id.delivery_type: + if not order.carrier_id.delivery_type or not order.carrier_id.display_name: return {} - order_location = json.loads(order.access_point_address) if order.access_point_address else False + order_location = order.access_point_address if not order_location: return {} address = order_location['address'] - return {order.carrier_id.delivery_type + '_access_point': address} + name = order_location['pick_up_point_name'] + return {order.carrier_id.delivery_type + '_access_point': address, 'name': name, 'delivery_name': order.carrier_id.display_name} - @http.route('/shop/access_point/close_locations', type='json', auth='public', csrf=False, website=True, sitemap=False) + @http.route('/shop/access_point/close_locations', type='json', auth='public', website=True, sitemap=False) def get_close_locations(self): order = request.website.sale_get_order() try: - error = {'error': 'No pick-up point available for that shipping address'} + error = {'error': _('No pick-up point available for that shipping address')} if not hasattr(order.carrier_id, '_' + order.carrier_id.delivery_type + '_get_close_locations'): return error close_locations = getattr(order.carrier_id, '_' + order.carrier_id.delivery_type + '_get_close_locations')(order.partner_shipping_id) partner_address = order.partner_shipping_id inline_partner_address = ' '.join((part or '') for part in [partner_address.street, partner_address.street2, partner_address.zip, partner_address.country_id.code]) if len(close_locations) < 0: - return {'error': 'No pick-up point available for that shipping address'} + return error for location in close_locations: location['address_stringified'] = json.dumps(location) return {'close_locations': close_locations, 'partner_address': inline_partner_address} diff --git a/addons/website_sale_delivery/models/sale_order.py b/addons/website_sale_delivery/models/sale_order.py index 9b0a3ff01b8..afb429a3480 100644 --- a/addons/website_sale_delivery/models/sale_order.py +++ b/addons/website_sale_delivery/models/sale_order.py @@ -11,7 +11,7 @@ class SaleOrder(models.Model): compute='_compute_amount_delivery', string='Delivery Amount', help="The amount without tax.", store=True, tracking=True) - access_point_address = fields.Text('Delivery Point Address') + access_point_address = fields.Json('Delivery Point Address') @api.depends('order_line.price_unit', 'order_line.tax_id', 'order_line.discount', 'order_line.product_uom_qty') def _compute_amount_delivery(self): @@ -21,6 +21,51 @@ class SaleOrder(models.Model): else: order.amount_delivery = sum(order.order_line.filtered('is_delivery').mapped('price_total')) + def _action_confirm(self): + for order in self: + order_location = order.access_point_address + + if not order_location: + continue + + # retreive all the data : + # name, street, city, state, zip, country + name = order.partner_shipping_id.name + street = order_location['pick_up_point_address'] + city = order_location['pick_up_point_town'] + zip_code = order_location['pick_up_point_postal_code'] + country = order.env['res.country'].search([('code', '=', order_location['pick_up_point_country'])]).id + state = order.env['res.country.state'].search(['&', ('code', '=', order_location['pick_up_point_state']), ('country_id.id', '=', country)]).id if (order_location['pick_up_point_state'] and country) else None + parent_id = order.partner_shipping_id.id + email = order.partner_shipping_id.email + phone = order.partner_shipping_id.phone + + # we can check if the current partner has a partner of type "delivery" that has the same address + existing_partner = order.env['res.partner'].search(['&', '&', '&', '&', + ('street', '=', street), + ('city', '=', city), + ('state_id', '=', state), + ('country_id', '=', country), + ('type', '=', 'delivery')], limit=1) + + if existing_partner: + order.partner_shipping_id = existing_partner + else: + # if not, we create that res.partner + order.partner_shipping_id = order.env['res.partner'].create({ + 'parent_id': parent_id, + 'type': 'delivery', + 'name': name, + 'street': street, + 'city': city, + 'state_id': state, + 'zip': zip_code, + 'country_id': country, + 'email': email, + 'phone': phone + }) + return super()._action_confirm() + def _check_carrier_quotation(self, force_carrier_id=None, keep_carrier=False): self.ensure_one() DeliveryCarrier = self.env['delivery.carrier'] diff --git a/addons/website_sale_delivery/static/src/js/website_sale_delivery.js b/addons/website_sale_delivery/static/src/js/website_sale_delivery.js index ba5c2fc2a91..8371ae5bf31 100644 --- a/addons/website_sale_delivery/static/src/js/website_sale_delivery.js +++ b/addons/website_sale_delivery/static/src/js/website_sale_delivery.js @@ -4,10 +4,9 @@ odoo.define('website_sale_delivery.checkout', function (require) { var core = require('web.core'); var publicWidget = require('web.public.widget'); -var _t = core._t; -var qweb = core.qweb; +const _t = core._t; +const qweb = core.qweb; var concurrency = require('web.concurrency'); -var dp = new concurrency.DropPrevious(); publicWidget.registry.websiteSaleDelivery = publicWidget.Widget.extend({ selector: '.oe_website_sale', @@ -17,42 +16,36 @@ publicWidget.registry.websiteSaleDelivery = publicWidget.Widget.extend({ "click .o_address_select": "_onClickLocation", "click .o_remove_order_location": "_onClickRemoveLocation", "click .o_show_pickup_locations": "_onClickShowLocations", + "click .o_payment_option_card": "_onClickPaymentMethod" }, /** * @override */ - start: function () { - var self = this; - var $carriers = $('#delivery_carrier input[name="delivery_type"]'); - var $payButton = $('button[name="o_payment_submit_button"]'); + start: async function () { + const carriers = Array.from(document.querySelectorAll('input[name="delivery_type"]')); + this.dp = new concurrency.DropPrevious(); // Workaround to: // - update the amount/error on the label at first rendering // - prevent clicking on 'Pay Now' if the shipper rating fails - if ($carriers.length > 0) { - if ($carriers.filter(':checked').length === 0) { - $payButton.prop('disabled', true); - var disabledReasons = $payButton.data('disabled_reasons') || {}; - disabledReasons.carrier_selection = true; - $payButton.data('disabled_reasons', disabledReasons); + if (carriers.length > 0) { + const carrierChecked = carriers.filter(e =>e.checked) + if (carrierChecked.length === 0) { + const payButton = document.querySelector('button[name="o_payment_submit_button"]'); + payButton? payButton.disabled = true : null; + } else { + carrierChecked[0].click(); } - $carriers.filter(':checked').click(); } - self._getCurrentLocation(); - - _.each($carriers, async function (carrierInput, k) { - self._showLoading($(carrierInput)); - const result = await self._rpc({ - route: '/shop/carrier_rate_shipment', - params: { - 'carrier_id': carrierInput.value, - }, - }) - self._handleCarrierUpdateResult(result) + await this._getCurrentLocation(); + await _.each(carriers, async carrierInput => { + this._showLoading((carrierInput)); + await this._handleCarrierUpdateResult(carrierInput) }); - - return this._super.apply(this, arguments); + if (this._super && typeof(this._super.apply)==="function") { + return this._super.apply(this, arguments); + } }, //-------------------------------------------------------------------------- @@ -62,228 +55,112 @@ publicWidget.registry.websiteSaleDelivery = publicWidget.Widget.extend({ * @private */ _getCurrentLocation: async function () { - const self=this; - const data = await self._rpc({ + const data = await this._rpc({ route: "/shop/access_point/get", }) - const order_locations = document.getElementsByClassName("o_order_location"); - for (const order_loc of order_locations) { - const show_loc = order_loc.parentElement.nextElementSibling; - // We could end not having the property - let delivery_type="" - if(order_loc.parentElement.parentElement.parentElement.children[0].attributes[8]){ - delivery_type = order_loc.parentElement.parentElement.parentElement.children[0].attributes[8].nodeValue; - } - if (!show_loc) + const carriers = document.querySelectorAll('.o_delivery_carrier_select') + for (let carrier of carriers) { + const deliveryType = carrier.querySelector('input[type="radio"]').getAttribute("delivery_type"); + const deliveryName = carrier.querySelector('label').innerText; + const showLoc = carrier.querySelector(".o_show_pickup_locations"); + if (!showLoc) { continue; - if (data[delivery_type+'_access_point']) { - order_loc.innerText = data[delivery_type+'_access_point'] - order_loc.parentElement.classList.remove("d-none"); - show_loc.classList.add("d-none"); + } + const orderLoc = carrier.querySelector(".o_order_location"); + if (data[deliveryType + '_access_point'] && data.delivery_name == deliveryName) { + orderLoc.querySelector(".o_order_location_name").innerText = data.name + orderLoc.querySelector(".o_order_location_address").innerText = data[deliveryType + '_access_point'] + orderLoc.parentElement.classList.remove("d-none"); + showLoc.classList.add("d-none"); break; } else { - order_loc.parentElement.classList.add("d-none"); - show_loc.classList.remove("d-none"); + orderLoc.parentElement.classList.add("d-none"); + showLoc.classList.remove("d-none"); } } }, /** * @private + * @param {Element} docCarrier //carrier element from document */ - _onClickRemoveLocation: async function (ev) { - ev.stopPropagation(); - const self = this; - await this._rpc({ - route: "/shop/access_point/set", - params: { - access_point_encoded: null, - }, - }) - self._getCurrentLocation(); - }, - - /** - * @private - * @param {Event} ev - */ - _onClickShowLocations: async function (ev) { - const self = this; - const show_pickup_locations = ev.currentTarget; - let modal = show_pickup_locations.nextElementSibling; - if (!show_pickup_locations.getElementsByClassName("link-primary").length) - return; - const should_load_content = modal.firstChild ? false : true; - while (modal.firstChild) { - modal.lastChild.remove(); - } - if (!should_load_content) - return; - - var delivery_type = ev.currentTarget.closest(".o_delivery_carrier_select").childNodes[1].attributes[8].nodeValue; - - const delivery_type_id = ev.currentTarget.closest(".o_delivery_carrier_select").childNodes[1].value; - await this._checkCarrier(ev,delivery_type_id) - - $(qweb.render(delivery_type + "_pickup_location_loading")).appendTo($(modal)); - const data = await self._rpc({ - route: "/shop/access_point/close_locations", - }) - if (modal.firstChild) - modal.firstChild.remove(); - if(!data || data && data.error || (data && data.close_locations && data.close_locations.length==0)){ - const error_message = document.createElement("em"); - error_message.classList.add("text-error"); - error_message.innerText = data.error ? data.error : "No available Pick-Up Locations"; - modal.appendChild(error_message); + _specificDropperDisplay: function (docCarrier) { + if(!docCarrier?.closest("li").getElementsByTagName("input")[0].getAttribute("delivery_type")){ return; } - - var list_to_render = delivery_type + "_pickup_location_list"; - var data_to_render = {partner_address: data.partner_address}; - data_to_render[delivery_type+"_pickup_locations"] = data.close_locations; - $(qweb.render(list_to_render, data_to_render)).appendTo($(modal)); - this._displayCarrierDropper(ev); - }, - /** - * @private - * @param {Object} obj // can be either an event or an objet returned by the controller - */ - _displayCarrierDropper: async function (obj) { - let current_id = obj.carrier_id - const show_locations = document - .getElementById("delivery_carrier") - .getElementsByClassName("o_show_pickup_locations"); - - // We check if it's an event - if('currentTarget' in obj){ - const is_full_page_event = !obj.currentTarget.closest(".o_delivery_carrier_select") - if(is_full_page_event)return; - for (const show_loc of show_locations){ - this._specificDropperDisplay(show_loc); - } + while (docCarrier.firstChild) { + docCarrier.lastChild.remove(); } - else{ - for (const show_loc of show_locations){ - const current_carrier_id = show_loc.closest("li").getElementsByTagName("input")[0].value; - if (current_carrier_id == current_id) { - this._specificDropperDisplay(show_loc); - break; - } - } - } - }, - /** - * @private - * @param {Object} doc_carrier //carrier element from document - */ - _specificDropperDisplay: function (doc_carrier) { - if(!doc_carrier) - return; - if(!doc_carrier.closest("li").getElementsByTagName("input")[0].attributes[8]) - return; - const current_carrier_type = doc_carrier.closest("li").getElementsByTagName("input")[0].attributes[8].nodeValue; - const location_still_loading = document.getElementById("#"+current_carrier_type+"_addresses") - if(location_still_loading)return - while (doc_carrier.firstChild) { - doc_carrier.lastChild.remove(); - } - const current_carrier_checked = doc_carrier.closest("li").getElementsByTagName("input")[0].checked; + const currentCarrierChecked = docCarrier.closest("li").getElementsByTagName("input")[0].checked; const span = document.createElement("em"); - const is_pick_up_location_list = doc_carrier.nextElementSibling.childNodes.length > 0 - if(current_carrier_checked){ - const chevron_down = document.createElement("i"); - if(is_pick_up_location_list) - chevron_down.classList.add("fa", "fa-angle-up"); - else - chevron_down.classList.add("fa", "fa-angle-down"); - span.textContent = "Pick-Up Locations "; - span.classList.add("link-primary"); - span.appendChild(chevron_down); - } - else { + if (!currentCarrierChecked) { span.textContent = "select to see available Pick-Up Locations"; span.classList.add("text-muted"); } - doc_carrier.appendChild(span); + docCarrier.appendChild(span); }, /** * @private - * @param {Event} ev + * @param {Element} carrierInput */ - _onClickLocation: async function (ev) { - ev.preventDefault(); - const carrierId = ev.currentTarget.closest(".o_delivery_carrier_select").childNodes[1].value; - await this._checkCarrier(ev,carrierId) - const self = this; - const modal = ev.target.closest(".o_list_pickup_locations"); - const encoded_location = ev.target.previousElementSibling.innerText; - await self._rpc({ - route: "/shop/access_point/set", - params: { - access_point_encoded: encoded_location, - }, - }) - while (modal.firstChild) { - modal.lastChild.remove(); + _showLoading: function (carrierInput) { + const priceTag = carrierInput.parentNode.querySelector('.o_wsale_delivery_badge_price') + while (priceTag.firstChild) { + priceTag.removeChild(priceTag.lastChild); } - self._getCurrentLocation(); - }, - /** - * @private - * @param {jQuery} $carrierInput - */ - _showLoading: function ($carrierInput) { - $carrierInput.siblings('.o_wsale_delivery_badge_price').empty(); - $carrierInput.siblings('.o_wsale_delivery_badge_price').append(''); + const loadingCircle = priceTag.appendChild(document.createElement('span')); + loadingCircle.classList.add("fa", "fa-circle-o-notch", "fa-spin"); }, /** * Update the total cost according to the selected shipping method - * + * * @private * @param {float} amount : The new total amount of to be paid */ - _updateShippingCost: function(amount){ + _updateShippingCost: function(amount) { core.bus.trigger('update_shipping_cost', amount); }, /** * @private * @param {Object} result */ - _handleCarrierUpdateResult: function (result) { - this._handleCarrierUpdateResultBadge(result); - var $payButton = $('button[name="o_payment_submit_button"]'); - var $amountDelivery = $('#order_delivery .monetary_field'); - var $amountUntaxed = $('#order_total_untaxed .monetary_field'); - var $amountTax = $('#order_total_taxes .monetary_field'); - var $amountTotal = $('#order_total .monetary_field, #amount_total_summary.monetary_field'); - - if (result.status === true) { - $amountDelivery.html(result.new_amount_delivery); - $amountUntaxed.html(result.new_amount_untaxed); - $amountTax.html(result.new_amount_tax); - $amountTotal.html(result.new_amount_total); - var disabledReasons = $payButton.data('disabled_reasons') || {}; - disabledReasons.carrier_selection = false; - $payButton.data('disabled_reasons', disabledReasons); - $payButton.prop('disabled', _.contains($payButton.data('disabled_reasons'), true)); - } else { - $amountDelivery.html(result.new_amount_delivery); - $amountUntaxed.html(result.new_amount_untaxed); - $amountTax.html(result.new_amount_tax); - $amountTotal.html(result.new_amount_total); - } - if (result.new_amount_total_raw !== undefined) { - this._updateShippingCost(result.new_amount_total_raw); - } - - var $carriers_inputs = $('#delivery_carrier input[name="delivery_type"]'); - var carriers = []; - _.each($carriers_inputs, function (carrierInput, k) { - carriers.push(carrierInput.dataset.deliveryType); + _handleCarrierUpdateResult: async function (carrierInput) { + const result = await this._rpc({ + route: '/shop/update_carrier', + params: { + 'carrier_id': carrierInput.value, + }, }) - this._displayCarrierDropper(result); + this._handleCarrierUpdateResultBadge(result); + if (carrierInput.checked) { + var amountDelivery = document.querySelector('#order_delivery .monetary_field'); + var amountUntaxed = document.querySelector('#order_total_untaxed .monetary_field'); + var amountTax = document.querySelector('#order_total_taxes .monetary_field'); + var amountTotal = document.querySelector('#order_total .monetary_field, #amount_total_summary.monetary_field'); + + amountDelivery.innerHTML = result.new_amount_delivery; + amountUntaxed.innerHTML = result.new_amount_untaxed; + amountTax.innerHTML = result.new_amount_tax; + amountTotal.innerHTML = result.new_amount_total; + // we need to check if it's the carrier that is selected + if (result.new_amount_total_raw !== undefined) { + this._updateShippingCost(result.new_amount_total_raw); + } + this._updateShippingCost(result.new_amount_delivery); + } + this._setIsPayable(result.status); + let currentId = result.carrier_id + const showLocations = document.querySelectorAll(".o_show_pickup_locations"); + + for (const showLoc of showLocations) { + const currentCarrierId = showLoc.closest("li").getElementsByTagName("input")[0].value; + if (currentCarrierId == currentId) { + this._specificDropperDisplay(showLoc); + break; + } + } }, + /** * @private * @param {Object} result @@ -291,7 +168,7 @@ publicWidget.registry.websiteSaleDelivery = publicWidget.Widget.extend({ _handleCarrierUpdateResultBadge: function (result) { var $carrierBadge = $('#delivery_carrier input[name="delivery_type"][value=' + result.carrier_id + '] ~ .o_wsale_delivery_badge_price'); - if (result.status === true) { + if (result.status === true) { // if free delivery (`free_over` field), show 'Free', not '$0' if (result.is_free_delivery) { $carrierBadge.text(_t('Free')); @@ -305,44 +182,219 @@ publicWidget.registry.websiteSaleDelivery = publicWidget.Widget.extend({ } }, - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- + _disablePayButtonNoPickupPoint : function (ev){ + const selectedCarrierEl = ev.currentTarget.closest('.o_delivery_carrier_select'); + const address = selectedCarrierEl.querySelector('.o_order_location_address').innerText + const isPickUp = selectedCarrierEl.lastChild.previousSibling.children; - /** - * @private - * @param {Event} ev - */ - _onCarrierClick: async function (ev) { - var $radio = $(ev.currentTarget).find('input[type="radio"]'); - this._showLoading($radio); - $radio.prop("checked", true); - var $payButton = $('button[name="o_payment_submit_button"]'); - $payButton.prop('disabled', true); - var disabledReasons = $payButton.data('disabled_reasons') || {}; - disabledReasons.carrier_selection = true; - $payButton.data('disabled_reasons', disabledReasons); - const data = await dp.add(this._rpc({ - route: '/shop/update_carrier', - params: { - carrier_id: $radio.val(), - }, - })) - this._handleCarrierUpdateResult(data); + document.querySelectorAll('.error_no_pick_up_point').forEach(el => el.remove()); + + if (isPickUp.length > 1 && (address == "" || isPickUp[0].classList.contains("d-none"))) { + var payButton = document.querySelector('button[name="o_payment_submit_button"]'); + payButton? payButton.disabled = true : null; + const errorNode = document.createElement("i"); + errorNode.classList.add("small", "error_no_pick_up_point","ms-2"); + errorNode.textContent = _t("Select a pick-up point"); + errorNode.style = "color:red;"; + selectedCarrierEl.insertBefore(errorNode, selectedCarrierEl.querySelector("label").nextElementSibling); + } }, _checkCarrier: async function (ev, carrier_id) { ev.stopPropagation(); - await dp.add(this._rpc({ + await this.dp.add(this._rpc({ route: '/shop/update_carrier', params: { carrier_id: carrier_id, }, })) var closestDocElement = ev.currentTarget.closest('.o_delivery_carrier_select'); - var $radio = $(closestDocElement).find('input[type="radio"]'); - $radio.prop("checked", true); + var radio = closestDocElement.querySelector('input[type="radio"]'); + radio.checked = true; + this._disablePayButtonNoPickupPoint(ev) }, + + _onClickPaymentMethod: async function (ev) { + const carriers = Array.from(document.querySelectorAll('.o_delivery_carrier_select')) + let carrierChecked = null; + carriers.forEach((carrier) => { + if (carrier.querySelector('input').checked){ + carrierChecked = carrier; + } + }) + if (!carrierChecked) { + return; + } + const carrier_id = carrierChecked?.querySelector('input')?.value; + const result = await this._rpc({ + route: '/shop/update_carrier', + params: { + 'carrier_id': carrier_id, + }, + }) + this._setIsPayable(result.status) + }, + /** + * @private + * @param {boolean} status : the status of the rate_shipment request + */ + // FYI we don't cover the case where the payement method is not selected because it already throws an error + _setIsPayable: function(status=false){ + // abort if no paybutton + var payButton = document.querySelector('button[name="o_payment_submit_button"]'); + if (!payButton) { + return; + } + // abort if the rating failed + if (!status){ + payButton.disabled = true; + return; + } + const carriers = Array.from(document.querySelectorAll('.o_delivery_carrier_select')) + let carrierChecked = null; + carriers.forEach((carrier) => { + if (carrier.querySelector('input').checked){ + carrierChecked = carrier; + } + }) + //abort if no carrier is selected + if (!carrierChecked){ + payButton.disabled = true; + return; + } + + // if the carrier does not need a pickup point + const isPickUpPointNeeded = carrierChecked.querySelector('.o_show_pickup_locations') + if (!isPickUpPointNeeded){ + payButton.disabled = false; + return; + } + + const address = carrierChecked.querySelector('.o_order_location_address').innerText + const isPickUp = carrierChecked.lastChild.previousSibling.children; + if (isPickUp.length > 1 && (address == "" || isPickUp[0].classList.contains("d-none"))) { + payButton.disabled = true ; + return + } + payButton.disabled = false; + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + */ + _onClickRemoveLocation: async function (ev) { + ev.stopPropagation(); + await this._rpc({ + route: "/shop/access_point/set", + params: { + access_point_encoded: null, + }, + }) + const deliveryTypeInput = ev.currentTarget.closest(".o_delivery_carrier_select").querySelector('input[name="delivery_type"]'); + const deliveryTypeId = deliveryTypeInput.value; + await Promise.all([this._getCurrentLocation(),this._checkCarrier(ev,deliveryTypeId)]) + await this._onClickShowLocations(ev); + }, + + /** + * @private + * @param {Event} ev + */ + _onClickShowLocations: async function (ev) { + // This checks if there is a pick up point already select with that carrier + if (!ev.currentTarget.closest('.o_delivery_carrier_select').querySelector(".o_order_location").parentElement.classList.contains("d-none")) { + return; + } + const showPickupLocations = ev.currentTarget.closest('.o_delivery_carrier_select').querySelector('.o_show_pickup_locations'); + const modal = showPickupLocations?.nextElementSibling; + if (!modal) { + return; + } + + while (modal.firstChild) { + modal.lastChild.remove(); + } + const deliveryTypeInput = ev.currentTarget.closest(".o_delivery_carrier_select").querySelector('input[name="delivery_type"]'); + const deliveryType = deliveryTypeInput.getAttribute("delivery_type"); + const deliveryTypeId = deliveryTypeInput.value; + await this._checkCarrier(ev,deliveryTypeId) + $(qweb.render(deliveryType + "_pickup_location_loading")).appendTo($(modal)); + const data = await this._rpc({ + route: "/shop/access_point/close_locations", + }) + if (modal.firstChild){ + modal.firstChild.remove(); + } + if (data.error || (data.close_locations.length === 0)) { + const errorMessage = document.createElement("em"); + errorMessage.classList.add("text-error"); + errorMessage.innerText = data.error ? data.error : "No available Pick-Up Locations"; + modal.appendChild(errorMessage); + return; + } + + var listToRender = deliveryType + "_pickup_location_list"; + var dataToRender = {partner_address: data.partner_address}; + dataToRender[deliveryType + "_pickup_locations"] = data.close_locations; + $(qweb.render(listToRender, dataToRender)).appendTo($(modal)); + + const showLocations = document.querySelectorAll(".o_show_pickup_locations"); + if (!ev.currentTarget.closest(".o_delivery_carrier_select")) { + return; + } + for (const showLoc of showLocations) { + this._specificDropperDisplay(showLoc); + } + }, + /** + * @private + * @param {Event} ev + */ + _onCarrierClick: async function (ev) { + const radio = ev.currentTarget.closest('.o_delivery_carrier_select').querySelector('input[type="radio"]'); + if (radio.checked) { + return; + } + this._showLoading(radio); + radio.checked = true; + await this._onClickShowLocations(ev); + await this._handleCarrierUpdateResult(radio); + this._disablePayButtonNoPickupPoint(ev); + }, + + /** + * @private + * @param {Event} ev + */ + _onClickLocation: async function (ev) { + const carrierId = ev.currentTarget.closest(".o_delivery_carrier_select").childNodes[1].value; + await this._checkCarrier(ev,carrierId) + const modal = ev.target.closest(".o_list_pickup_locations"); + const encodedLocation = ev.target.previousElementSibling.innerText; + await this._rpc({ + route: "/shop/access_point/set", + params: { + access_point_encoded: encodedLocation, + }, + }) + while (modal.firstChild) { + modal.lastChild.remove(); + } + await this._getCurrentLocation(); + document.querySelectorAll('.error_no_pick_up_point').forEach(el => el.remove()); + const result = await this._rpc({ + route: '/shop/update_carrier', + params: { + 'carrier_id': carrierId, + }, + }) + this._setIsPayable(result.status) + }, + /** * @private * @param {Event} ev diff --git a/addons/website_sale_delivery/views/locations_carrier_templates.xml b/addons/website_sale_delivery/views/locations_carrier_templates.xml deleted file mode 100644 index 8b2d0991f9d..00000000000 --- a/addons/website_sale_delivery/views/locations_carrier_templates.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - diff --git a/addons/website_sale_delivery/views/website_sale_delivery_templates.xml b/addons/website_sale_delivery/views/website_sale_delivery_templates.xml index 7031f67886c..1764eb95ef1 100644 --- a/addons/website_sale_delivery/views/website_sale_delivery_templates.xml +++ b/addons/website_sale_delivery/views/website_sale_delivery_templates.xml @@ -20,17 +20,26 @@