Expected behaviour When buying something on the website, the amount to be paid for the client should take into account the choice of the shipping method. Observed behaviour When choosing a different shipping method than the default one, and only if this method is a third party acquire, the total amount is updated on the website, but the amount the client will be asked to pay doesn't take into account this change, being computed according to the default shipping method. Steps to Reproduce this Issue 1. Select a product on the website and add it to the cart 2. View and validate the cart 3. Change the shipping method 4. Click on the "Pay now" button Problem Root Cause This issue comes from the fact that the amount was written in the view when creating the cart view and wasn't updated by a change of shipping method. Related issue opw-2686369 closes odoo/odoo#81587 X-original-commit: 617ed0ef47d1496b912d5b85a494e3cda897da4d Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com> Signed-off-by: Hendrickx Anthony (anhe) <anhe@odoo.com>
123 lines
5.8 KiB
Python
123 lines
5.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import http, _
|
|
from odoo.http import request
|
|
from odoo.addons.website_sale.controllers.main import WebsiteSale
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
class WebsiteSaleDelivery(WebsiteSale):
|
|
|
|
@http.route()
|
|
def shop_payment(self, **post):
|
|
order = request.website.sale_get_order()
|
|
carrier_id = post.get('carrier_id')
|
|
if carrier_id:
|
|
carrier_id = int(carrier_id)
|
|
if order:
|
|
order._check_carrier_quotation(force_carrier_id=carrier_id)
|
|
if carrier_id:
|
|
return request.redirect("/shop/payment")
|
|
|
|
return super(WebsiteSaleDelivery, self).shop_payment(**post)
|
|
|
|
@http.route(['/shop/update_carrier'], type='json', auth='public', methods=['POST'], website=True, csrf=False)
|
|
def update_eshop_carrier(self, **post):
|
|
order = request.website.sale_get_order()
|
|
carrier_id = int(post['carrier_id'])
|
|
if order:
|
|
order._check_carrier_quotation(force_carrier_id=carrier_id)
|
|
return self._update_website_sale_delivery_return(order, **post)
|
|
|
|
@http.route(['/shop/carrier_rate_shipment'], type='json', auth='public', methods=['POST'], website=True)
|
|
def cart_carrier_rate_shipment(self, carrier_id, **kw):
|
|
order = request.website.sale_get_order(force_create=True)
|
|
|
|
if not int(carrier_id) in order._get_delivery_methods().ids:
|
|
raise UserError(_('It seems that a delivery method is not compatible with your address. Please refresh the page and try again.'))
|
|
|
|
Monetary = request.env['ir.qweb.field.monetary']
|
|
|
|
res = {'carrier_id': carrier_id}
|
|
carrier = request.env['delivery.carrier'].sudo().browse(int(carrier_id))
|
|
rate = carrier.rate_shipment(order)
|
|
if rate.get('success'):
|
|
tax_ids = carrier.product_id.taxes_id.filtered(lambda t: t.company_id == order.company_id)
|
|
if tax_ids:
|
|
fpos = order.fiscal_position_id
|
|
tax_ids = fpos.map_tax(tax_ids)
|
|
taxes = tax_ids.compute_all(
|
|
rate['price'],
|
|
currency=order.currency_id,
|
|
quantity=1.0,
|
|
product=carrier.product_id,
|
|
partner=order.partner_shipping_id,
|
|
)
|
|
if request.env.user.has_group('account.group_show_line_subtotals_tax_excluded'):
|
|
rate['price'] = taxes['total_excluded']
|
|
else:
|
|
rate['price'] = taxes['total_included']
|
|
|
|
res['status'] = True
|
|
res['new_amount_delivery'] = Monetary.value_to_html(rate['price'], {'display_currency': order.currency_id})
|
|
res['is_free_delivery'] = not bool(rate['price'])
|
|
res['error_message'] = rate['warning_message']
|
|
else:
|
|
res['status'] = False
|
|
res['new_amount_delivery'] = Monetary.value_to_html(0.0, {'display_currency': order.currency_id})
|
|
res['error_message'] = rate['error_message']
|
|
return res
|
|
|
|
def order_lines_2_google_api(self, order_lines):
|
|
""" Transforms a list of order lines into a dict for google analytics """
|
|
order_lines_not_delivery = order_lines.filtered(lambda line: not line.is_delivery)
|
|
return super(WebsiteSaleDelivery, self).order_lines_2_google_api(order_lines_not_delivery)
|
|
|
|
def order_2_return_dict(self, order):
|
|
""" Returns the tracking_cart dict of the order for Google analytics """
|
|
ret = super(WebsiteSaleDelivery, self).order_2_return_dict(order)
|
|
delivery_line = order.order_line.filtered('is_delivery')
|
|
if delivery_line:
|
|
ret['shipping'] = delivery_line.price_unit
|
|
return ret
|
|
|
|
def _get_shop_payment_values(self, order, **kwargs):
|
|
values = super(WebsiteSaleDelivery, self)._get_shop_payment_values(order, **kwargs)
|
|
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()
|
|
|
|
delivery_carriers = order._get_delivery_methods()
|
|
values['deliveries'] = delivery_carriers.sudo()
|
|
|
|
values['delivery_has_storable'] = has_storable_products
|
|
values['delivery_action_id'] = request.env.ref('delivery.action_delivery_carrier_form').id
|
|
return values
|
|
|
|
def _update_website_sale_delivery_return(self, order, **post):
|
|
Monetary = request.env['ir.qweb.field.monetary']
|
|
carrier_id = int(post['carrier_id'])
|
|
currency = order.currency_id
|
|
if order:
|
|
return {
|
|
'status': order.delivery_rating_success,
|
|
'error_message': order.delivery_message,
|
|
'carrier_id': carrier_id,
|
|
'is_free_delivery': not bool(order.amount_delivery),
|
|
'new_amount_delivery': Monetary.value_to_html(order.amount_delivery, {'display_currency': currency}),
|
|
'new_amount_untaxed': Monetary.value_to_html(order.amount_untaxed, {'display_currency': currency}),
|
|
'new_amount_tax': Monetary.value_to_html(order.amount_tax, {'display_currency': currency}),
|
|
'new_amount_total': Monetary.value_to_html(order.amount_total, {'display_currency': currency}),
|
|
'new_amount_total_raw': order.amount_total,
|
|
}
|
|
return {}
|