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