@ -0,0 +1,48 @@ |
|||
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg |
|||
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html |
|||
:alt: License: AGPL-3 |
|||
|
|||
Web Pay Shipping Methods |
|||
======================== |
|||
This Module allows users to assign shipping methods to payment providers, ensuring that only the specified shipping methods are available when a payment provider is selected during checkout. |
|||
|
|||
Configuration |
|||
============= |
|||
* No Additional configuration is needed. |
|||
|
|||
Company |
|||
------- |
|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
License |
|||
------- |
|||
Affero General Public License, v3.0 (AGPL v3). |
|||
(https://www.gnu.org/licenses/agpl-3.0-standalone.html) |
|||
|
|||
Credits |
|||
------- |
|||
* Developers: (V17) Mruthul Raj |
|||
(V18) Aysha Shalin |
|||
Contact: odoo@cybrosys.com |
|||
|
|||
Contacts |
|||
-------- |
|||
* Mail Contact : odoo@cybrosys.com |
|||
* Website : https://cybrosys.com |
|||
|
|||
Bug Tracker |
|||
---------- |
|||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
|||
|
|||
Maintainer |
|||
========== |
|||
.. image:: https://cybrosys.com/images/logo.png |
|||
:target: https://cybrosys.com |
|||
|
|||
This module is maintained by Cybrosys Technologies. |
|||
|
|||
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ |
|||
|
|||
Further information |
|||
=================== |
|||
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Aysha Shalin (odoo@cybrosys.com) |
|||
# |
|||
# you can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC |
|||
# LICENSE (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from . import controllers |
|||
from . import models |
@ -0,0 +1,50 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Aysha Shalin (odoo@cybrosys.com) |
|||
# |
|||
# you can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC |
|||
# LICENSE (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
{ |
|||
'name': "Web Pay Shipping Methods", |
|||
'version': '18.0.1.0.0', |
|||
'category': 'eCommerce', |
|||
'summary': """Select shipping methods based on payment provider.""", |
|||
'description': """The shipping methods assigned to a payment provider will |
|||
only be available when selecting that provider during the website sale |
|||
checkout process.""", |
|||
'author': "Cybrosys Techno Solutions", |
|||
'company': "Cybrosys Techno Solutions", |
|||
'maintainer': "Cybrosys Techno Solutions", |
|||
'website': "https://www.cybrosys.com", |
|||
'depends': ['website_sale'], |
|||
'data': [ |
|||
'views/payment_provider_views.xml', |
|||
'views/website_sale_delivery_templates.xml' |
|||
], |
|||
'assets': { |
|||
'web.assets_frontend': [ |
|||
'web_pay_shipping_methods/static/src/js/PaymentForm.js', |
|||
'web_pay_shipping_methods/static/src/js/DeliveryMethod.js' |
|||
], |
|||
}, |
|||
'images': ['static/description/banner.png'], |
|||
'license': 'AGPL-3', |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': False, |
|||
} |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Aysha Shalin (odoo@cybrosys.com) |
|||
# |
|||
# you can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC |
|||
# LICENSE (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from . import main |
@ -0,0 +1,76 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Aysha Shalin (odoo@cybrosys.com) |
|||
# |
|||
# you can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC |
|||
# LICENSE (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from odoo.addons.payment.controllers import portal as payment_portal |
|||
|
|||
from odoo.http import route, request |
|||
from odoo.tools import str2bool |
|||
|
|||
|
|||
class WebsiteSale(payment_portal.PaymentPortal): |
|||
@route('/shop/payment', type='http', auth='public', website=True, sitemap=False) |
|||
def shop_payment(self, try_skip_step=None, **post): |
|||
""" Payment step. This page proposes several payment means based on available |
|||
payment.provider. State at this point : |
|||
|
|||
- a draft sales order with lines; otherwise, clean context / session and |
|||
back to the shop |
|||
- no transaction in context / session, or only a draft one, if the customer |
|||
did go to a payment.provider website but closed the tab without |
|||
paying / canceling |
|||
""" |
|||
try_skip_step = str2bool(try_skip_step or 'false') |
|||
order_sudo = request.website.sale_get_order() |
|||
|
|||
checkout_page_values = self._prepare_checkout_page_values(order_sudo, |
|||
**post) |
|||
|
|||
if redirection := self._check_cart_and_addresses(order_sudo): |
|||
return redirection |
|||
|
|||
render_values = self._get_shop_payment_values(order_sudo, **post) |
|||
render_values['only_services'] = order_sudo and order_sudo.only_services |
|||
|
|||
can_skip_delivery = True # Delivery is only needed for deliverable products. |
|||
if order_sudo._has_deliverable_products(): |
|||
available_dms = order_sudo._get_delivery_methods() |
|||
checkout_page_values['delivery_methods'] = available_dms |
|||
if delivery_method := order_sudo._get_preferred_delivery_method( |
|||
available_dms): |
|||
rate = delivery_method.rate_shipment(order_sudo) |
|||
render_values['delivery_methods'] = checkout_page_values['delivery_methods'] |
|||
if ( |
|||
not order_sudo.carrier_id |
|||
or not rate.get('success') |
|||
or order_sudo.amount_delivery != rate['price'] |
|||
): |
|||
order_sudo._set_delivery_method(delivery_method, rate=rate) |
|||
can_skip_delivery = self.can_skip_delivery_step(order_sudo, |
|||
available_dms) |
|||
|
|||
if try_skip_step and can_skip_delivery: |
|||
return request.redirect('/shop/confirm_order') |
|||
|
|||
if render_values['errors']: |
|||
render_values.pop('payment_methods_sudo', '') |
|||
render_values.pop('tokens_sudo', '') |
|||
|
|||
return request.render("website_sale.payment", render_values) |
@ -0,0 +1,6 @@ |
|||
## Module <web_pay_shipping_methods> |
|||
|
|||
#### 02.11.2024 |
|||
#### Version 18.0.1.0.0 |
|||
##### ADD |
|||
- Initial commit for Web Pay Shipping Methods |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Aysha Shalin (odoo@cybrosys.com) |
|||
# |
|||
# you can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC |
|||
# LICENSE (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from . import payment_provider |
@ -0,0 +1,34 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Aysha Shalin (odoo@cybrosys.com) |
|||
# |
|||
# you can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC |
|||
# LICENSE (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class PaymentProvider(models.Model): |
|||
"""Inherited payment_provider to add shipping method field""" |
|||
_inherit = 'payment.provider' |
|||
|
|||
delivery_carrier_ids = fields.Many2many( |
|||
'delivery.carrier', |
|||
string="Shipping Methods", |
|||
domain="[('website_published', '=', True)]", |
|||
help="Add shipping methods which will be available while" |
|||
" choosing this payment provider") |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 628 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 542 B |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 738 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 189 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 751 KiB |
After Width: | Height: | Size: 760 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 781 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 162 KiB |
After Width: | Height: | Size: 137 KiB |
After Width: | Height: | Size: 880 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 9.2 KiB |
@ -0,0 +1,198 @@ |
|||
/** @odoo-module **/ |
|||
|
|||
import publicWidget from "@web/legacy/js/public/public_widget"; |
|||
import { rpc } from "@web/core/network/rpc"; |
|||
import { _t } from '@web/core/l10n/translation'; |
|||
|
|||
// Extend a new widget named DeliveryMethods for loading delivery methods in payment page
|
|||
publicWidget.registry.DeliveryMethods = publicWidget.Widget.extend({ |
|||
selector: '.o_website_sale_checkout', |
|||
events: { |
|||
'click [name="o_delivery_radio"]': '_selectDeliveryMethod', |
|||
}, |
|||
init() { |
|||
this._super(...arguments); |
|||
this.orm = this.bindService("orm"); |
|||
}, |
|||
/** |
|||
* @override |
|||
*/ |
|||
async start() { |
|||
this.mainButton = document.querySelector('a[name="o_payment_submit_button"]'); |
|||
await this._prepareDeliveryMethods(); |
|||
}, |
|||
/** |
|||
* Copied from checkout.js for loading delivery method template in payment template |
|||
*/ |
|||
async _selectDeliveryMethod(ev) { |
|||
const checkedRadio = ev.currentTarget; |
|||
if (checkedRadio.disabled) { // The delivery rate request failed.
|
|||
return; // Failing delivery methods cannot be selected.
|
|||
} |
|||
|
|||
// Disable the main button while fetching delivery rates.
|
|||
this._disableMainButton(); |
|||
|
|||
// Fetch delivery rates and update the cart summary and the price badge accordingly.
|
|||
await this._updateDeliveryMethod(checkedRadio); |
|||
|
|||
// Re-enable the main button after delivery rates have been fetched.
|
|||
this._enableMainButton(); |
|||
|
|||
// Show a button to open the location selector if required for the selected delivery method.
|
|||
await this._showPickupLocation(checkedRadio); |
|||
}, |
|||
|
|||
async _prepareDeliveryMethods() { |
|||
// Load the radios from the DOM here to update them if the template is re-rendered.
|
|||
this.dmRadios = Array.from(document.querySelectorAll('input[name="o_delivery_radio"]')); |
|||
if (this.dmRadios.length > 0) { |
|||
const checkedRadio = document.querySelector('input[name="o_delivery_radio"]:checked'); |
|||
this._disableMainButton(); |
|||
if (checkedRadio) { |
|||
await this._updateDeliveryMethod(checkedRadio); |
|||
this._enableMainButton(); |
|||
} |
|||
} |
|||
// Asynchronously fetch delivery rates to mitigate delays from third-party APIs
|
|||
await Promise.all(this.dmRadios.filter(radio => !radio.checked).map(async radio => { |
|||
this._showLoadingBadge((radio)); |
|||
const rateData = await this._getDeliveryRate(radio); |
|||
this._updateAmountBadge(radio, rateData); |
|||
})); |
|||
}, |
|||
|
|||
async _updateDeliveryMethod(radio) { |
|||
this._showLoadingBadge(radio); |
|||
const result = await this._setDeliveryMethod(radio.dataset.dmId); |
|||
this._updateAmountBadge(radio, result); |
|||
this._updateCartSummary(result); |
|||
}, |
|||
|
|||
async _showPickupLocation(radio) { |
|||
if (!radio.dataset.isPickupLocationRequired || radio.disabled) { |
|||
return; // Fetching the delivery rate failed.
|
|||
} |
|||
const deliveryMethodContainer = this._getDeliveryMethodContainer(radio); |
|||
const pickupLocation = deliveryMethodContainer.querySelector('[name="o_pickup_location"]'); |
|||
|
|||
const editPickupLocationButton = pickupLocation.querySelector( |
|||
'span[name="o_pickup_location_selector"]' |
|||
); |
|||
if (editPickupLocationButton.dataset.pickupLocationData) { |
|||
await this._setPickupLocation(editPickupLocationButton.dataset.pickupLocationData); |
|||
} |
|||
|
|||
pickupLocation.classList.remove('d-none'); // Show the whole div.
|
|||
}, |
|||
|
|||
async _setPickupLocation(pickupLocationData) { |
|||
await rpc('/website_sale/set_pickup_location', {pickup_location_data: pickupLocationData}); |
|||
}, |
|||
_updateAmountBadge(radio, rateData) { |
|||
const deliveryPriceBadge = this._getDeliveryPriceBadge(radio); |
|||
if (rateData.success) { |
|||
// If it's a free delivery (`free_over` field), show 'Free', not '$ 0'.
|
|||
if (rateData.is_free_delivery) { |
|||
deliveryPriceBadge.textContent = _t("Free"); |
|||
} else { |
|||
deliveryPriceBadge.innerHTML = rateData.amount_delivery; |
|||
} |
|||
this._toggleDeliveryMethodRadio(radio); |
|||
} else { |
|||
deliveryPriceBadge.textContent = rateData.error_message; |
|||
this._toggleDeliveryMethodRadio(radio, true); |
|||
} |
|||
}, |
|||
|
|||
_toggleDeliveryMethodRadio(radio, disable=false) { |
|||
const deliveryMethodContainer = this._getDeliveryMethodContainer(radio); |
|||
radio.disabled = disable; |
|||
if (disable) { |
|||
deliveryMethodContainer.classList.add('text-muted'); |
|||
} |
|||
else { |
|||
deliveryMethodContainer.classList.remove('text-muted'); |
|||
} |
|||
}, |
|||
|
|||
_updateCartSummary(result) { |
|||
const amountDelivery = document.querySelector('#order_delivery .monetary_field'); |
|||
const amountUntaxed = document.querySelector('#order_total_untaxed .monetary_field'); |
|||
const amountTax = document.querySelector('#order_total_taxes .monetary_field'); |
|||
const amountTotal = document.querySelectorAll( |
|||
'#order_total .monetary_field, #amount_total_summary.monetary_field' |
|||
); |
|||
amountDelivery.innerHTML = result.amount_delivery; |
|||
amountUntaxed.innerHTML = result.amount_untaxed; |
|||
amountTax.innerHTML = result.amount_tax; |
|||
amountTotal.forEach(total => total.innerHTML = result.amount_total); |
|||
}, |
|||
|
|||
async _setDeliveryMethod(dmId) { |
|||
return await rpc('/shop/set_delivery_method', {'dm_id': dmId}); |
|||
}, |
|||
|
|||
async _getDeliveryRate(radio) { |
|||
return await rpc('/shop/get_delivery_rate', {'dm_id': radio.dataset.dmId}); |
|||
}, |
|||
|
|||
_disableMainButton() { |
|||
this.mainButton?.classList.add('disabled'); |
|||
}, |
|||
|
|||
_enableMainButton() { |
|||
if (this._isDeliveryMethodReady()) { |
|||
this.mainButton?.classList.remove('disabled'); |
|||
} |
|||
}, |
|||
|
|||
_showLoadingBadge(radio) { |
|||
const deliveryPriceBadge = this._getDeliveryPriceBadge(radio); |
|||
this._clearElement(deliveryPriceBadge); |
|||
deliveryPriceBadge.appendChild(this._createLoadingElement()); |
|||
}, |
|||
|
|||
_clearElement(el) { |
|||
while (el.firstChild) { |
|||
el.removeChild(el.lastChild); |
|||
} |
|||
}, |
|||
|
|||
_createLoadingElement() { |
|||
const loadingElement = document.createElement('i'); |
|||
loadingElement.classList.add('fa', 'fa-circle-o-notch', 'fa-spin', 'center'); |
|||
return loadingElement; |
|||
}, |
|||
|
|||
_isDeliveryMethodReady() { |
|||
if (this.dmRadios.length === 0) { // No delivery method is available.
|
|||
return true; // Ignore the check.
|
|||
} |
|||
const checkedRadio = document.querySelector('input[name="o_delivery_radio"]:checked'); |
|||
return checkedRadio |
|||
&& !checkedRadio.disabled |
|||
&& !this._isPickupLocationMissing(checkedRadio); |
|||
}, |
|||
|
|||
_getDeliveryPriceBadge(radio) { |
|||
const deliveryMethodContainer = this._getDeliveryMethodContainer(radio); |
|||
return deliveryMethodContainer.querySelector('.o_wsale_delivery_price_badge'); |
|||
}, |
|||
|
|||
_isPickupLocationMissing(radio) { |
|||
const deliveryMethodContainer = this._getDeliveryMethodContainer(radio); |
|||
if (!this._isPickupLocationRequired(radio)) return false; |
|||
return !deliveryMethodContainer.querySelector( |
|||
'span[name="o_pickup_location_selector"]' |
|||
).dataset.locationId; |
|||
}, |
|||
|
|||
_getDeliveryMethodContainer(el) { |
|||
return el.closest('[name="o_delivery_method"]'); |
|||
}, |
|||
|
|||
_isPickupLocationRequired(radio) { |
|||
return Boolean(radio.dataset.isPickupLocationRequired); |
|||
}, |
|||
}); |
@ -0,0 +1,40 @@ |
|||
/** @odoo-module **/ |
|||
import { patch } from "@web/core/utils/patch"; |
|||
import PaymentForm from '@payment/js/payment_form'; |
|||
import { _t } from '@web/core/l10n/translation'; |
|||
import { rpc } from '@web/core/network/rpc'; |
|||
/** |
|||
* Handles the selection of a payment option in the payment form. |
|||
* |
|||
* This method overrides the default behavior to hide all delivery methods initially |
|||
* and then show the delivery methods associated with the selected payment provider. |
|||
*/ |
|||
PaymentForm.include({ |
|||
async _selectPaymentOption(ev) { |
|||
this._super(...arguments); |
|||
$('.delivery_method_list').each(function(key,carrier) { |
|||
$(this).find('input[type="radio"]').prop('checked', false); |
|||
$(this).addClass('d-none'); |
|||
}); |
|||
let providerId = ev.target.dataset['providerId'] |
|||
let carriers = await this.orm.read("payment.provider",[parseInt(providerId)],['delivery_carrier_ids']) |
|||
if(carriers[0].delivery_carrier_ids.length > 0){ |
|||
carriers[0].delivery_carrier_ids.forEach((id)=>{ |
|||
if(id){ |
|||
let deliveryMethod = '#delivery_method_'+id |
|||
let deliveryElement = $(deliveryMethod)[0]; |
|||
// Only attempt to remove the class if the element exists
|
|||
if (deliveryElement) { |
|||
deliveryElement.classList.remove('d-none'); |
|||
} |
|||
} |
|||
}); |
|||
}else{ |
|||
let noShippingMethodElement = $('#NoShippingMethod')[0]; |
|||
// Only attempt to remove the class if the element exists
|
|||
if (noShippingMethodElement) { |
|||
noShippingMethodElement.classList.remove('d-none'); |
|||
} |
|||
} |
|||
}, |
|||
}); |
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- New field Shipping method is added in Payment provider form view.--> |
|||
<record id="payment_provider_form" model="ir.ui.view"> |
|||
<field name="name">payment.provider.view.form.inherit.web.pay.shipping.methods</field> |
|||
<field name="model">payment.provider</field> |
|||
<field name="inherit_id" ref="payment.payment_provider_form"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//field[@name='so_reference_type']" position="after"> |
|||
<field name="delivery_carrier_ids" widget="many2many_tags"/> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,49 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!--Xpath expression specified to replace or remove the original shipping |
|||
method template in website payment page.--> |
|||
<template id="delivery_form" name="Shipping Methods" |
|||
inherit_id="website_sale.delivery_form"> |
|||
<xpath expr="//ul[@id='o_delivery_methods']" position="replace"> |
|||
<div class="alert alert-danger d-none" role="alert" id="NoShippingMethod"> |
|||
<h4> |
|||
Sorry, we are unable to ship your order |
|||
</h4> |
|||
No shipping method is available for the selected payment |
|||
method, kindly choose any other, or please contact us for more |
|||
information. |
|||
</div> |
|||
<ul t-if="delivery_methods" id="o_delivery_methods" class="list-group"> |
|||
<t t-foreach="delivery_methods" t-as="dm"> |
|||
<li name="o_delivery_method" class="list-group-item delivery_method_list text-muted o_outline d-none" |
|||
t-att-id="'delivery_method_%i' % dm.id"> |
|||
<t t-log="dm.id"/> |
|||
<t t-call="website_sale.delivery_method"> |
|||
<t t-set="is_selected" t-value="dm.id == selected_dm_id"/> |
|||
</t> |
|||
</li> |
|||
</t> |
|||
</ul> |
|||
</xpath> |
|||
</template> |
|||
|
|||
<!-- Xpath expression specified to remove the original delivery methods template |
|||
in Delivery page. --> |
|||
<template id="checkout" inherit_id="website_sale.checkout"> |
|||
<xpath expr="//t[@t-call='website_sale.delivery_form']" position="replace"> |
|||
<t/> |
|||
</xpath> |
|||
</template> |
|||
|
|||
<!-- Xpath expression specified to replace the delivery methods template |
|||
in Payment page. --> |
|||
<template id="payment" inherit_id="website_sale.payment"> |
|||
<xpath expr="//div[@id='oe_structure_website_sale_payment_1']" position="after"> |
|||
<div class="oe_structure clearfix mt-3 mb-4"> |
|||
<t t-call="website_sale.delivery_form"> |
|||
<t t-set="selected_dm_id" t-value="order.carrier_id.id"/> |
|||
</t> |
|||
</div> |
|||
</xpath> |
|||
</template> |
|||
</odoo> |