from odoo import http from odoo.http import request from odoo.addons.website_sale.controllers.main import WebsiteSale class Dine360OnlineOrders(http.Controller): @http.route('/shop/update_service_mode', type='json', auth="public", website=True) def update_service_mode(self, service_mode, **post): order = request.website.sale_get_order() if order and service_mode in ['pickup', 'delivery', 'dine_in']: order.sudo().write({ 'fulfilment_type': service_mode, 'order_source': 'online' }) return True class Dine360WebsiteSaleOnline(WebsiteSale): @http.route(['/shop/cart'], type='http', auth="public", website=True, sitemap=False) def cart(self, **post): """When user visits cart, remove any delivery fee so cart shows ONLY food items subtotal and tax""" request.session.pop('address_confirmed_for_order', None) order = request.website.sale_get_order() if order and order.state == 'draft': delivery_lines = order.order_line.filtered(lambda l: l.is_delivery) if delivery_lines: delivery_lines.sudo().unlink() order.sudo().write({ 'carrier_id': False, 'uber_delivery_fee': 0.0 }) return super(Dine360WebsiteSaleOnline, self).cart(**post) @http.route(['/shop/cart/update_json'], type='json', auth="public", methods=['POST'], website=True, csrf=False) def cart_update_json(self, *args, **kwargs): """Ensure delivery fee is not shown when modifying cart quantities""" res = super(Dine360WebsiteSaleOnline, self).cart_update_json(*args, **kwargs) order = request.website.sale_get_order() if order and order.state == 'draft': delivery_lines = order.order_line.filtered(lambda l: l.is_delivery) if delivery_lines: delivery_lines.sudo().unlink() order.sudo().write({ 'carrier_id': False, 'uber_delivery_fee': 0.0 }) return res @http.route(['/shop/checkout'], type='http', auth="public", website=True, sitemap=False) def checkout(self, **post): """Enforce redirect to address & fulfillment selection page every single time from cart""" order = request.website.sale_get_order() if not order or order.state != 'draft': return request.redirect('/shop') if not order.order_line: return request.redirect('/shop/cart') # If user has already selected & submitted the address in this flow, proceed to standard checkout/payment if post.get('express') or request.session.get('address_confirmed_for_order') == order.id: return super(Dine360WebsiteSaleOnline, self).checkout(**post) # Otherwise, always direct to the unified delivery/pickup address page partner_id = order.partner_id.id if order.partner_id else 0 return request.redirect(f'/shop/address?mode=billing&partner_id={partner_id}') @http.route(['/shop/address'], type='http', methods=['GET', 'POST'], auth="public", website=True, sitemap=False) def address(self, **post): """Process address form submission, record fulfillment type, and mark address as confirmed""" order = request.website.sale_get_order() if post.get('submitted'): if order: request.session['address_confirmed_for_order'] = order.id fulfilment_type = post.get('fulfilment_type', 'delivery') order.sudo().write({ 'fulfilment_type': fulfilment_type, 'order_source': 'online' }) # For store pickup orders, auto-populate dummy fields so Odoo's backend validation succeeds if post.get('fulfilment_type') == 'pickup': if not post.get('street'): post['street'] = 'Store Pickup' if not post.get('city'): post['city'] = 'Local' if not post.get('zip'): post['zip'] = '00000' if not post.get('country_id'): country = request.env['res.country'].sudo().search([], limit=1) post['country_id'] = str(country.id) if country else '' for k, v in post.items(): if k in ['street', 'city', 'zip', 'country_id']: if hasattr(request.params, 'update'): try: request.params[k] = v except TypeError: pass return super(Dine360WebsiteSaleOnline, self).address(**post) @http.route(['/shop/payment'], type='http', auth="public", website=True, sitemap=False) def shop_payment(self, **post): """Ensure customer came from address selection, and bypass missing delivery carrier validation""" order = request.website.sale_get_order() if not order or order.state != 'draft' or not order.order_line: return request.redirect('/shop/cart') # If user directly visits /shop/payment without passing the address & fulfillment page, redirect them if request.session.get('address_confirmed_for_order') != order.id: partner_id = order.partner_id.id if order.partner_id else 0 return request.redirect(f'/shop/address?mode=billing&partner_id={partner_id}') # For delivery orders, ensure the delivery line is active and reflects the stored fee if order.fulfilment_type == 'delivery': delivery_line = order.order_line.filtered(lambda l: l.is_delivery) fee = getattr(order, 'uber_delivery_fee', 0.0) if not delivery_line and fee > 0 and hasattr(order, '_add_uber_delivery_fee'): order.sudo()._add_uber_delivery_fee(fee) elif order.fulfilment_type in ['pickup', 'dine_in']: # Ensure no leftover delivery line for pickup order.order_line.filtered(lambda l: l.is_delivery).sudo().unlink() return super(Dine360WebsiteSaleOnline, self).shop_payment(**post) @http.route('/shop/payment/transaction/', type='json', auth="public", website=True) def shop_payment_transaction(self, order_id, access_token=None, **kwargs): """Preserve delivery fee during payment transaction initiation""" order = request.env['sale.order'].sudo().browse(order_id) if order and order.fulfilment_type == 'delivery': delivery_line = order.order_line.filtered(lambda l: l.is_delivery) fee = getattr(order, 'uber_delivery_fee', 0.0) if not delivery_line and fee > 0 and hasattr(order, '_add_uber_delivery_fee'): order._add_uber_delivery_fee(fee) return super(Dine360WebsiteSaleOnline, self).shop_payment_transaction(order_id, access_token=access_token, **kwargs)