# -*- coding: utf-8 -*- """ Uber Delivery Tracking Page – standalone HTML, no API key required. Uses OpenStreetMap (free, no key) + Leaflet.js for live route map. """ from odoo import http from odoo.http import request, Response import urllib.parse import logging _logger = logging.getLogger(__name__) class UberTrackingController(http.Controller): @http.route([ '/uber/track/sale/', '/uber/track/pos/', ], type='http', auth='user', website=False) def track_delivery(self, order_id, **kwargs): path = request.httprequest.path # ── Load order ───────────────────────────────────────────── if '/sale/' in path: order = request.env['sale.order'].sudo().browse(order_id) model_type = 'sale' partner = order.partner_shipping_id or order.partner_id order_ref = order.name or f'SO{order_id}' customer_name = partner.name if partner else 'Customer' customer_phone = (partner.phone or partner.mobile or '') if partner else '' dropoff_street = (partner.street or '') if partner else '' dropoff_city = (partner.city or '') if partner else '' dropoff_state = (partner.state_id.name if partner and partner.state_id else '') dropoff_zip = (partner.zip or '') if partner else '' dropoff_country = (partner.country_id.name if partner and partner.country_id else '') uber_status = order.uber_status or '' uber_tracking_url = order.uber_tracking_url or '' uber_delivery_id = order.uber_delivery_id or '' uber_eta = str(order.uber_eta)[:16] if order.uber_eta else '' else: order = request.env['pos.order'].sudo().browse(order_id) model_type = 'pos' partner = order.partner_id order_ref = order.pos_reference or order.name or f'PO{order_id}' customer_name = partner.name if partner else 'Customer' customer_phone = (partner.phone or partner.mobile or '') if partner else '' dropoff_street = getattr(order, 'delivery_street', '') or ((partner.street or '') if partner else '') dropoff_city = getattr(order, 'delivery_city', '') or ((partner.city or '') if partner else '') dropoff_state = (partner.state_id.name if partner and partner.state_id else '') if partner else '' dropoff_zip = getattr(order, 'delivery_zip', '') or ((partner.zip or '') if partner else '') dropoff_country = (partner.country_id.name if partner and partner.country_id else '') if partner else '' uber_status = order.uber_status or '' uber_tracking_url = order.uber_tracking_url or '' uber_delivery_id = order.uber_delivery_id or '' uber_eta = str(order.uber_eta)[:16] if getattr(order, 'uber_eta', False) else '' # ── Restaurant pickup ─────────────────────────────────────── company = request.env.company pickup_name = company.name or 'Restaurant' pickup_street = company.street or '' pickup_city = company.city or '' pickup_state = company.state_id.name if company.state_id else '' pickup_zip = company.zip or '' pickup_country = company.country_id.name if company.country_id else '' pickup_phone = company.phone or '' def _addr(*parts): return ', '.join(p for p in parts if p) pickup_addr = _addr(pickup_street, pickup_city, pickup_state, pickup_zip, pickup_country) dropoff_addr = _addr(dropoff_street, dropoff_city, dropoff_state, dropoff_zip, dropoff_country) # Google Maps directions URL (opens in browser, no key needed) gmaps_url = ( 'https://www.google.com/maps/dir/?api=1' f'&origin={urllib.parse.quote(pickup_addr)}' f'&destination={urllib.parse.quote(dropoff_addr)}' '&travelmode=driving' ) # OpenStreetMap static route embed (no API key) osm_embed = ( 'https://www.openstreetmap.org/export/embed.html' f'?bbox={self._bbox(pickup_addr, dropoff_addr)}' '&layer=mapnik' '&marker=yes' ) # Status info status_map = { 'pending': ('#f59e0b', '⏳ Waiting for Driver', '⚠️'), 'pickup': ('#3b82f6', '🚗 Driver at Restaurant', 'ℹ️'), 'delivering': ('#06b6d4', '🛵 On the Way to You', '🔵'), 'delivered': ('#10b981', '✅ Order Delivered!', '✅'), 'cancelled': ('#ef4444', '❌ Delivery Cancelled', '❌'), } st_color, st_label, st_icon = status_map.get(uber_status, ('#64748b', '❓ Unknown', '❓')) back_url = f'/odoo/{model_type}-orders/{order_id}' if model_type == 'sale' else f'/odoo/point-of-sale/orders/{order_id}' html = self._render_page( order_ref=order_ref, model_type=model_type, order_id=order_id, pickup_name=pickup_name, pickup_street=pickup_street, pickup_city=pickup_city, pickup_state=pickup_state, pickup_zip=pickup_zip, pickup_country=pickup_country, pickup_phone=pickup_phone, pickup_addr=pickup_addr, customer_name=customer_name, customer_phone=customer_phone, dropoff_street=dropoff_street, dropoff_city=dropoff_city, dropoff_state=dropoff_state, dropoff_zip=dropoff_zip, dropoff_country=dropoff_country, dropoff_addr=dropoff_addr, uber_status=uber_status, st_color=st_color, st_label=st_label, uber_delivery_id=uber_delivery_id, uber_eta=uber_eta, uber_tracking_url=uber_tracking_url, gmaps_url=gmaps_url, ) return Response(html, content_type='text/html; charset=utf-8') def _bbox(self, addr1, addr2): """Placeholder bbox — Leaflet geocodes addresses on client side.""" return '-180,-90,180,90' def _render_page(self, **v): # Safe helper def esc(s): return str(s or '').replace('&', '&').replace('<', '<').replace('"', '"') show_uber_btn = v['uber_tracking_url'] and 'sandbox' not in v['uber_tracking_url'] # Pre-build strings that contain backslashes (not allowed inside f-string expressions) pickup_icon_html = '
🏪
' dropoff_icon_html = '
🏠
' eta_chip = ('
⏱ Estimated Delivery
' + esc(v['uber_eta']) + '
') if v['uber_eta'] else '' id_chip = ('
🔖 Uber Delivery ID
' + esc(v['uber_delivery_id']) + '
') if v['uber_delivery_id'] else '' pickup_phone_html = ('
📞 ' + esc(v['pickup_phone']) + '
') if v['pickup_phone'] else '' dropoff_phone_html = ('
📞 ' + esc(v['customer_phone']) + '
') if v['customer_phone'] else '' pickup_br = '
' if v['pickup_street'] else '' dropoff_br = '
' if v['dropoff_street'] else '' pickup_state_part = (', ' + esc(v['pickup_state'])) if v['pickup_state'] else '' pickup_zip_part = (' – ' + esc(v['pickup_zip'])) if v['pickup_zip'] else '' pickup_country_part = ('
' + esc(v['pickup_country'])) if v['pickup_country'] else '' dropoff_state_part = (', ' + esc(v['dropoff_state'])) if v['dropoff_state'] else '' dropoff_zip_part = (' – ' + esc(v['dropoff_zip'])) if v['dropoff_zip'] else '' dropoff_country_part = ('
' + esc(v['dropoff_country'])) if v['dropoff_country'] else '' uber_fab = ('⚡ Uber Live') if show_uber_btn else '' uber_btn = ('⚡ Live Track on Uber') if show_uber_btn else '' st_color = esc(v['st_color']) return f''' Uber Delivery Tracking – {esc(v["order_ref"])}
Delivery Tracking
Live Order Status
# {esc(v["order_ref"])}
{esc(v["st_label"])} 🔄 Auto-refreshes every 30s
{eta_chip} {id_chip}
📍 Pickup Location
{esc(v["pickup_name"])}
{esc(v['pickup_street'])}{pickup_br} {esc(v['pickup_city'])}{pickup_state_part}{pickup_zip_part} {pickup_country_part}
{pickup_phone_html}
🎯 Delivering To
{esc(v['customer_name'])}
{esc(v['dropoff_street'])}{dropoff_br} {esc(v['dropoff_city'])}{dropoff_state_part}{dropoff_zip_part} {dropoff_country_part}
{dropoff_phone_html}
🗺️ Google Maps {uber_fab}
Status auto-refreshes every 30 seconds
'''