diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index a662a227b74..c4188ba3eba 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -1679,7 +1679,7 @@ class WebsiteSale(payment_portal.PaymentPortal): def _get_shop_payment_values(self, order, **kwargs): checkout_page_values = { 'website_sale_order': order, - 'errors': [], + 'errors': self._get_shop_payment_errors(order), 'partner': order.partner_invoice_id, 'order': order, 'submit_button_label': _("Pay now"), @@ -1702,13 +1702,6 @@ class WebsiteSale(payment_portal.PaymentPortal): has_storable_products = any( line.product_id.type in ['consu', 'product'] for line in order.order_line ) - if not order._get_delivery_methods() and has_storable_products: - values['errors'].append(( - _('Sorry, we are unable to ship your order'), - _('No shipping method is available for your current order and shipping address.' - ' Please contact us for more information.') - )) - if has_storable_products: if order.carrier_id and not order.delivery_rating_success: order._remove_delivery_line() @@ -1722,6 +1715,24 @@ class WebsiteSale(payment_portal.PaymentPortal): return values + def _get_shop_payment_errors(self, order): + """ Check that there is no error that should block the payment. + + :param sale.order order: The sales order to pay + :return: A list of errors (error_title, error_message) + :rtype: list[tuple] + """ + has_storable_products = any(line.product_id.type in ['consu', 'product'] for line in order.order_line) + errors = [] + + if not order._get_delivery_methods() and has_storable_products: + errors.append(( + _('Sorry, we are unable to ship your order'), + _('No shipping method is available for your current order and shipping address. ' + 'Please contact us for more information.'), + )) + return errors + @http.route('/shop/payment', type='http', auth='public', website=True, sitemap=False) def shop_payment(self, **post): """ Payment step. This page proposes several payment means based on available @@ -1780,6 +1791,12 @@ class WebsiteSale(payment_portal.PaymentPortal): order = request.env['sale.order'].sudo().browse(sale_order_id) assert order.id == request.session.get('sale_last_order_id') + errors = self._get_shop_payment_errors(order) + if errors: + first_error = errors[0] # only display first error + error_msg = f"{first_error[0]}\n{first_error[1]}" + raise ValidationError(error_msg) + tx_sudo = order.get_portal_last_transaction() if order else order.env['payment.transaction'] if not order or (order.amount_total and not tx_sudo): diff --git a/addons/website_sale/tests/test_delivery_controller.py b/addons/website_sale/tests/test_delivery_controller.py index 22191e93f8c..e1690100b03 100644 --- a/addons/website_sale/tests/test_delivery_controller.py +++ b/addons/website_sale/tests/test_delivery_controller.py @@ -2,8 +2,8 @@ from unittest.mock import patch -from odoo.exceptions import UserError from odoo.fields import Command +from odoo.exceptions import UserError, ValidationError from odoo.tests import tagged from odoo.addons.payment.tests.common import PaymentCommon @@ -110,3 +110,23 @@ class TestWebsiteSaleDeliveryController(PaymentCommon, SaleCommon): self.assertEqual( self.empty_order._get_delivery_methods().mapped('name'), ['Under 300', 'Fixed'] ) + + def test_validate_payment_with_no_available_delivery_method(self): + """ + An error should be raised if you try to validate an order with a storable + product without any delivery method available + """ + storable_product = self.env['product.product'].create({ + 'name': 'Storable Product', + 'sale_ok': True, + 'type': 'product', + 'website_published': True, + }) + carriers = self.env['delivery.carrier'].search([]) + carriers.write({'website_published': False}) + + with MockRequest(self.env, website=self.website): + self.website.sale_get_order(force_create=True) + self.Controller.cart_update_json(product_id=storable_product.id, add_qty=1) + with self.assertRaises(ValidationError): + self.Controller.shop_payment_validate() diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index da2ac600c9f..7993cbebd7c 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -1759,7 +1759,7 @@