implement unified checkout address layout with delivery/pickup selection and custom order total display

This commit is contained in:
Alaguraj0361 2026-04-10 19:51:27 +05:30
parent c730b5c95d
commit c33f40a809
2 changed files with 66 additions and 13 deletions

View File

@ -61,9 +61,9 @@ class SaleOrderOnline(models.Model):
def _is_shippable_order(self):
"""
Treat all online orders as non-shippable for Odoo's standard validation.
This enables 'Billing-only' checkout even for delivery orders,
as we handle shipping manually via Uber fee lines.
Treat pickup, delivery and other types as non-shippable for Odoo's standard validation.
This enables 'Billing-only' checkout which is more reliable for payment providers.
The Uber delivery line is protected by our _remove_delivery_line override.
"""
self.ensure_one()
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):
"""Allow proceeding to payment if we already have a carrier (Uber) or don't need 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']:
return True
# 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 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):
"""
Override from dine360_kds to also mark the POS order as an online order.

View File

@ -2,17 +2,53 @@
<odoo>
<!-- 1. Global Order Total 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">
<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="uber_line" id="uber_delivery_row">
<td class="border-0 pb-2 ps-0 pt-0 text-start text-muted" colspan="2">Uber Delivery Fee</td>
<tr t-if="all_delivery_lines" 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="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>
</tr>
</xpath>
</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 &amp;&amp; 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 -->
<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">
@ -153,7 +189,7 @@
});
// 3. Custom Validation on Submit
if (submitBtn &amp;&amp; document.querySelector('form.checkout_autoformat')) {
if (submitBtn) {
submitBtn.addEventListener('click', function(e) {
const form = document.querySelector('form.checkout_autoformat');
if (!form) return;
@ -239,8 +275,6 @@
containers.forEach(c => {
c.querySelectorAll('input, select').forEach(i => i.removeAttribute('required'));
});
// Safety: Always enable button for pickup
if (submitBtn) submitBtn.disabled = false;
} else {
containers.forEach(c => c.style.display = '');
if (addrHeader) addrHeader.style.display = '';
@ -252,6 +286,12 @@
});
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() {
@ -297,7 +337,7 @@
Uber Delivery Fee: $${data.result.fee} (Distance Based)
</div>
</div>`;
if (submitBtn &amp;&amp; document.querySelector('input[name="street"]')) submitBtn.disabled = false;
if (submitBtn) submitBtn.disabled = false;
} else {
msgDiv.className = 'alert alert-danger my-3 animated fadeIn';
msgDiv.style.display = '';
@ -308,7 +348,7 @@
${data.result?.error || "This specific address is outside the Uber delivery radius."}
</div>
</div>`;
if (submitBtn &amp;&amp; document.querySelector('input[name="street"]')) submitBtn.disabled = true;
if (submitBtn) submitBtn.disabled = true;
}
}).catch(err => {
console.error("Uber API Error:", err);
@ -411,7 +451,7 @@
} else {
msgBox.className = 'alert alert-danger my-3';
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');
}
});
}