from odoo import models, fields, api, _ import logging _logger = logging.getLogger(__name__) class SaleOrder(models.Model): _inherit = 'sale.order' def _get_available_carriers(self, **kwargs): """Force Include the Uber carrier in the available list to bypass Odoo's address/website filters""" carriers = super()._get_available_carriers(**kwargs) if self.carrier_id and 'Uber' in (self.carrier_id.name or ''): if self.carrier_id not in carriers: carriers |= self.carrier_id return carriers def _remove_delivery_line(self): """Prevent Odoo from automatically removing the Uber delivery fee during checkout transitions""" if self.carrier_id and 'Uber' in (self.carrier_id.name or ''): return return super()._remove_delivery_line() def _check_carrier_quotation(self, force_carrier_id=None, **kwargs): """Skip delivery re-validation for Uber orders to prevent the fee from being cleared""" if self.carrier_id and 'Uber' in (self.carrier_id.name or ''): return True return super()._check_carrier_quotation(force_carrier_id=force_carrier_id, **kwargs) def _add_uber_delivery_fee(self, amount): """Add the delivery fee using Odoo's standard delivery system to satisfy checkout validation""" _logger.info("Uber: Syncing delivery fee %s to order %s", amount, self.name) # 1. Ensure fulfillment type is set if hasattr(self, 'fulfilment_type'): self.write({ 'fulfilment_type': 'delivery', 'partner_shipping_id': self.partner_id.id }) else: self.write({'partner_shipping_id': self.partner_id.id}) # 2. Find or Create the Uber Delivery carrier Carrier = self.env['delivery.carrier'].sudo() config = self.env['uber.config'].sudo().search([('active', '=', True)], limit=1) # Search for any carrier linked to the Uber product or with Uber in the name carrier = Carrier.search(['|', ('name', 'ilike', 'Uber'), ('product_id', '=', config.delivery_product_id.id if config.delivery_product_id else 0)], limit=1) if not carrier and config: # Fallback product if one isn't set in config product = config.delivery_product_id if not product: product = self.env['product.product'].sudo().search([('name', 'ilike', 'Delivery')], limit=1) if not product: product = self.env['product.product'].sudo().search([], limit=1) # Last resort _logger.info("Uber: Creating new Uber Delivery carrier using product %s", product.name) carrier = Carrier.create({ 'name': 'Uber Direct Delivery', 'delivery_type': 'fixed', 'product_id': product.id, 'website_published': True, 'fixed_price': 0.0, 'active': True, }) if carrier: # Force carrier to be published and global to avoid "No shipping method" error carrier.sudo().write({ 'website_published': True, 'active': True, 'country_ids': [(6, 0, [])], 'state_ids': [(6, 0, [])], 'zip_prefix_ids': [(6, 0, [])] if hasattr(Carrier, 'zip_prefix_ids') else False }) # 3. Use Odoo's standard method to set delivery _logger.info("Uber: Setting carrier %s with fee %s", carrier.name, amount) # Lock the price on the carrier record itself temporarily (SUDO) to satisfy Odoo's check_carrier carrier.sudo().write({'fixed_price': amount}) # Apply to order self.sudo().set_delivery_line(carrier, amount) self.sudo().write({'carrier_id': carrier.id}) # Force the line name and price one more time to be sure delivery_line = self.order_line.filtered(lambda l: l.is_delivery) if delivery_line: delivery_line.sudo().write({ 'price_unit': amount, 'name': f"Uber Direct Delivery ({self.partner_id.city or 'Local'})" }) else: _logger.warning("Uber: No delivery carrier found to apply fee") # Save everything to DB immediately self.env.cr.commit() return True