# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) import logging from odoo import http from odoo.exceptions import AccessDenied from odoo.http import request _logger = logging.getLogger(__name__) class WooApiController(http.Controller): """REST endpoints consumed by the WooCommerce WordPress plugin.""" def _authenticate_instance(self): """ Validate Bearer token from Authorization header against woo.instance.odoo_api_key. Returns the matching woo.instance or raises AccessDenied. """ auth_header = request.httprequest.headers.get('Authorization', '') if not auth_header.startswith('Bearer '): raise AccessDenied() api_key = auth_header[len('Bearer '):] if not api_key: raise AccessDenied() instance = request.env['woo.instance'].sudo().search([ ('odoo_api_key', '=', api_key), ], limit=1) if not instance: raise AccessDenied() return instance # ------------------------------------------------------------------------- # Endpoints # ------------------------------------------------------------------------- @http.route( '/woo/api/order/documents', type='jsonrpc', auth='none', csrf=False, methods=['POST'], ) def order_documents(self, order_id=None, **kw): """ Fetch invoice and delivery PDF URLs for a WooCommerce order. Expected payload: {"order_id": } Returns: {"invoices": [...], "deliveries": [...]} """ try: instance = self._authenticate_instance() except AccessDenied: return {'error': 'Unauthorized', 'code': 401} if not order_id: return {'error': 'order_id is required', 'code': 400} _logger.info( "WooCommerce API: order/documents requested. Instance: %s, Order: %s", instance.name, order_id, ) # Placeholder — data fetching will be implemented in later tasks return { 'order_id': order_id, 'invoices': [], 'deliveries': [], } @http.route( '/woo/api/order/status', type='jsonrpc', auth='none', csrf=False, methods=['POST'], ) def order_status(self, order_id=None, **kw): """ Fetch order status and timeline data for a WooCommerce order. Expected payload: {"order_id": } Returns: {"status": ..., "timeline": [...]} """ try: instance = self._authenticate_instance() except AccessDenied: return {'error': 'Unauthorized', 'code': 401} if not order_id: return {'error': 'order_id is required', 'code': 400} _logger.info( "WooCommerce API: order/status requested. Instance: %s, Order: %s", instance.name, order_id, ) # Placeholder — data fetching will be implemented in later tasks return { 'order_id': order_id, 'status': None, 'odoo_state': None, 'timeline': [], } @http.route( '/woo/api/order/messages', type='jsonrpc', auth='none', csrf=False, methods=['POST'], ) def order_messages(self, order_id=None, **kw): """ Fetch customer-visible messages for a WooCommerce order. Expected payload: {"order_id": } Returns: {"messages": [...]} """ try: instance = self._authenticate_instance() except AccessDenied: return {'error': 'Unauthorized', 'code': 401} if not order_id: return {'error': 'order_id is required', 'code': 400} _logger.info( "WooCommerce API: order/messages requested. Instance: %s, Order: %s", instance.name, order_id, ) # Placeholder — data fetching will be implemented in later tasks return { 'order_id': order_id, 'messages': [], } @http.route( '/woo/api/return/create', type='jsonrpc', auth='none', csrf=False, methods=['POST'], ) def return_create(self, order_id=None, reason=None, items=None, **kw): """ Submit a return request from the WooCommerce plugin. Expected payload: { "order_id": , "reason": "", "items": [{"product_id": ..., "quantity": ...}, ...] } Returns: {"success": True, "return_id": } or {"error": ...} """ try: instance = self._authenticate_instance() except AccessDenied: return {'error': 'Unauthorized', 'code': 401} if not order_id: return {'error': 'order_id is required', 'code': 400} _logger.info( "WooCommerce API: return/create requested. Instance: %s, Order: %s", instance.name, order_id, ) # Placeholder — return creation logic will be implemented in later tasks return { 'success': True, 'return_id': None, 'message': 'Return request received.', }