implement unified checkout address layout with delivery/pickup selection and custom order total display
This commit is contained in:
parent
c730b5c95d
commit
c33f40a809
@ -61,9 +61,9 @@ class SaleOrderOnline(models.Model):
|
|||||||
|
|
||||||
def _is_shippable_order(self):
|
def _is_shippable_order(self):
|
||||||
"""
|
"""
|
||||||
Treat all online orders as non-shippable for Odoo's standard validation.
|
Treat pickup, delivery and other types as non-shippable for Odoo's standard validation.
|
||||||
This enables 'Billing-only' checkout even for delivery orders,
|
This enables 'Billing-only' checkout which is more reliable for payment providers.
|
||||||
as we handle shipping manually via Uber fee lines.
|
The Uber delivery line is protected by our _remove_delivery_line override.
|
||||||
"""
|
"""
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
if self.fulfilment_type in ['pickup', 'delivery', 'dine_in', 'walk_in']:
|
if self.fulfilment_type in ['pickup', 'delivery', 'dine_in', 'walk_in']:
|
||||||
@ -73,6 +73,7 @@ class SaleOrderOnline(models.Model):
|
|||||||
def _check_carrier_quotation(self, force_carrier_id=None, **kwargs):
|
def _check_carrier_quotation(self, force_carrier_id=None, **kwargs):
|
||||||
"""Allow proceeding to payment if we already have a carrier (Uber) or don't need one"""
|
"""Allow proceeding to payment if we already have a carrier (Uber) or don't need one"""
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
|
_logger.info("Checking carrier quotation for order %s (fulfilment: %s, carrier: %s)", self.name, self.fulfilment_type, self.carrier_id.name if self.carrier_id else 'None')
|
||||||
if self.fulfilment_type in ['pickup', 'delivery', 'dine_in', 'walk_in']:
|
if self.fulfilment_type in ['pickup', 'delivery', 'dine_in', 'walk_in']:
|
||||||
return True
|
return True
|
||||||
# If we have a carrier set by our Uber integration, trust it and skip standard re-validation
|
# If we have a carrier set by our Uber integration, trust it and skip standard re-validation
|
||||||
@ -80,6 +81,18 @@ class SaleOrderOnline(models.Model):
|
|||||||
return True
|
return True
|
||||||
return super()._check_carrier_quotation(force_carrier_id=force_carrier_id, **kwargs)
|
return super()._check_carrier_quotation(force_carrier_id=force_carrier_id, **kwargs)
|
||||||
|
|
||||||
|
def _remove_delivery_line(self):
|
||||||
|
"""
|
||||||
|
Prevent Odoo from removing the delivery line if its an Uber order.
|
||||||
|
Odoo often tries to clean up delivery lines on page transitions if it
|
||||||
|
thinks the shipping method is no longer valid.
|
||||||
|
"""
|
||||||
|
self.ensure_one()
|
||||||
|
if self.carrier_id and 'Uber' in (self.carrier_id.name or ''):
|
||||||
|
_logger.info("Protecting Uber delivery line from removal on order %s", self.name)
|
||||||
|
return True
|
||||||
|
return super()._remove_delivery_line()
|
||||||
|
|
||||||
def _create_pos_order_for_kds(self, sale_order):
|
def _create_pos_order_for_kds(self, sale_order):
|
||||||
"""
|
"""
|
||||||
Override from dine360_kds to also mark the POS order as an online order.
|
Override from dine360_kds to also mark the POS order as an online order.
|
||||||
|
|||||||
@ -2,17 +2,53 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<!-- 1. Global Order Total Display -->
|
<!-- 1. Global Order Total Display -->
|
||||||
<template id="chennora_total_uber_display" inherit_id="website_sale.total" name="Chennora Total Uber Display">
|
<template id="chennora_total_uber_display" inherit_id="website_sale.total" name="Chennora Total Uber Display">
|
||||||
|
<!-- Hide the original Odoo delivery row that appears ABOVE subtotal safely -->
|
||||||
|
<xpath expr="//tr[@id='order_delivery']" position="attributes">
|
||||||
|
<attribute name="style">display: none !important;</attribute>
|
||||||
|
<attribute name="class" add="d-none" separator=" "/>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<!-- Use a unified filter for all delivery-related lines -->
|
||||||
|
<xpath expr="//tr[@id='order_total_untaxed']" position="before">
|
||||||
|
<t t-set="all_delivery_lines" t-value="website_sale_order.order_line.filtered(lambda l: l.is_delivery or 'Uber' in (l.product_id.name or '') or 'Delivery' in (l.product_id.name or ''))"/>
|
||||||
|
<t t-set="all_delivery_amount" t-value="sum(all_delivery_lines.mapped('price_subtotal'))"/>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<!-- Fix Subtotal value safely to exclude delivery fee, while keeping classes for JS -->
|
||||||
|
<xpath expr="//tr[@id='order_total_untaxed']//td[not(hasclass('text-start'))]//span" position="replace">
|
||||||
|
<span class="monetary_field" style="white-space: nowrap;"
|
||||||
|
t-esc="website_sale_order.amount_untaxed - all_delivery_amount"
|
||||||
|
t-options='{"widget": "monetary", "display_currency": website_sale_order.currency_id}'/>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
<xpath expr="//tr[@id='order_total_untaxed']" position="after">
|
<xpath expr="//tr[@id='order_total_untaxed']" position="after">
|
||||||
<t t-set="uber_line" t-value="website_sale_order.order_line.filtered(lambda l: l.product_id.name == 'Uber Delivery Fee')"/>
|
<tr t-if="all_delivery_lines" id="uber_delivery_row">
|
||||||
<tr t-if="uber_line" id="uber_delivery_row">
|
<td class="border-0 pb-2 ps-0 pt-0 text-start text-muted" colspan="2">Delivery Fee</td>
|
||||||
<td class="border-0 pb-2 ps-0 pt-0 text-start text-muted" colspan="2">Uber Delivery Fee</td>
|
|
||||||
<td class="text-end border-0 pb-2 pe-0 pt-0">
|
<td class="text-end border-0 pb-2 pe-0 pt-0">
|
||||||
<span t-field="uber_line[0].price_subtotal" t-options='{"widget": "monetary", "display_currency": website_sale_order.currency_id}' class="monetary_field"/>
|
<span t-esc="all_delivery_amount" t-options='{"widget": "monetary", "display_currency": website_sale_order.currency_id}' class="monetary_field"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- Force enable Pay Now button on payment page if it's disabled by Odoo's shipping logic -->
|
||||||
|
<template id="chennora_force_pay_button" inherit_id="website_sale.payment" name="Chennora Force Pay Button">
|
||||||
|
<xpath expr="//div[@id='payment_method']" position="inside">
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function() {
|
||||||
|
function enablePayButton() {
|
||||||
|
const payBtn = document.querySelector('#o_payment_form_button, .btn-primary[type="submit"]');
|
||||||
|
if (payBtn && payBtn.disabled) {
|
||||||
|
console.log("Chennora: Force enabling payment button");
|
||||||
|
payBtn.disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setInterval(enablePayButton, 1000); // Check every second as Odoo JS might toggle it
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- 2. Hide Uber fee from cart summary -->
|
<!-- 2. Hide Uber fee from cart summary -->
|
||||||
<template id="chennora_cart_summary_uber_hide" inherit_id="website_sale.checkout_layout" name="Chennora Cart Summary Uber Hide">
|
<template id="chennora_cart_summary_uber_hide" inherit_id="website_sale.checkout_layout" name="Chennora Cart Summary Uber Hide">
|
||||||
<xpath expr="//table[@id='cart_products']//tr" position="attributes">
|
<xpath expr="//table[@id='cart_products']//tr" position="attributes">
|
||||||
@ -153,7 +189,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 3. Custom Validation on Submit
|
// 3. Custom Validation on Submit
|
||||||
if (submitBtn && document.querySelector('form.checkout_autoformat')) {
|
if (submitBtn) {
|
||||||
submitBtn.addEventListener('click', function(e) {
|
submitBtn.addEventListener('click', function(e) {
|
||||||
const form = document.querySelector('form.checkout_autoformat');
|
const form = document.querySelector('form.checkout_autoformat');
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
@ -239,8 +275,6 @@
|
|||||||
containers.forEach(c => {
|
containers.forEach(c => {
|
||||||
c.querySelectorAll('input, select').forEach(i => i.removeAttribute('required'));
|
c.querySelectorAll('input, select').forEach(i => i.removeAttribute('required'));
|
||||||
});
|
});
|
||||||
// Safety: Always enable button for pickup
|
|
||||||
if (submitBtn) submitBtn.disabled = false;
|
|
||||||
} else {
|
} else {
|
||||||
containers.forEach(c => c.style.display = '');
|
containers.forEach(c => c.style.display = '');
|
||||||
if (addrHeader) addrHeader.style.display = '';
|
if (addrHeader) addrHeader.style.display = '';
|
||||||
@ -252,6 +286,12 @@
|
|||||||
});
|
});
|
||||||
checkUber();
|
checkUber();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SYNC with server immediately
|
||||||
|
fetch('/shop/update_service_mode', {
|
||||||
|
method: 'POST', headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify({ params: { service_mode: type } })
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function checkUber() {
|
function checkUber() {
|
||||||
@ -297,7 +337,7 @@
|
|||||||
Uber Delivery Fee: $${data.result.fee} (Distance Based)
|
Uber Delivery Fee: $${data.result.fee} (Distance Based)
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
if (submitBtn && document.querySelector('input[name="street"]')) submitBtn.disabled = false;
|
if (submitBtn) submitBtn.disabled = false;
|
||||||
} else {
|
} else {
|
||||||
msgDiv.className = 'alert alert-danger my-3 animated fadeIn';
|
msgDiv.className = 'alert alert-danger my-3 animated fadeIn';
|
||||||
msgDiv.style.display = '';
|
msgDiv.style.display = '';
|
||||||
@ -308,7 +348,7 @@
|
|||||||
${data.result?.error || "This specific address is outside the Uber delivery radius."}
|
${data.result?.error || "This specific address is outside the Uber delivery radius."}
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
if (submitBtn && document.querySelector('input[name="street"]')) submitBtn.disabled = true;
|
if (submitBtn) submitBtn.disabled = true;
|
||||||
}
|
}
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error("Uber API Error:", err);
|
console.error("Uber API Error:", err);
|
||||||
@ -411,7 +451,7 @@
|
|||||||
} else {
|
} else {
|
||||||
msgBox.className = 'alert alert-danger my-3';
|
msgBox.className = 'alert alert-danger my-3';
|
||||||
msgBox.innerHTML = `<strong>✕ Uber Direct: Invalid Operation</strong><br/>${data.result?.error || "Outside delivery radius."}`;
|
msgBox.innerHTML = `<strong>✕ Uber Direct: Invalid Operation</strong><br/>${data.result?.error || "Outside delivery radius."}`;
|
||||||
if (billingGrid) document.querySelector('button[type="submit"]')?.setAttribute('disabled', 'disabled');
|
document.querySelector('button[type="submit"]')?.setAttribute('disabled', 'disabled');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user