# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) import logging from odoo import http from odoo.http import request _logger = logging.getLogger(__name__) class WooProductSearchController(http.Controller): """AJAX search endpoints used by the product mapping UI.""" # ------------------------------------------------------------------------- # Endpoints # ------------------------------------------------------------------------- @http.route( '/woo/search/odoo_products', type='jsonrpc', auth='user', methods=['POST'], ) def search_odoo_products(self, query='', instance_id=None, limit=20, **kw): """ Search Odoo products by name or internal reference (SKU). Params: query (str): Search string matched against name and default_code. instance_id (int): woo.instance ID (used for future per-instance filtering). limit (int): Max results to return (default 20). Returns: list of {id, name, default_code, list_price, qty_available} """ limit = min(int(limit or 20), 100) domain = [] if query: domain = [ '|', ('name', 'ilike', query), ('default_code', 'ilike', query), ] products = request.env['product.product'].search(domain, limit=limit) return [ { 'id': p.id, 'name': p.name, 'default_code': p.default_code or '', 'list_price': p.list_price, 'qty_available': p.qty_available, } for p in products ] @http.route( '/woo/search/woo_products', type='jsonrpc', auth='user', methods=['POST'], ) def search_woo_products(self, query='', instance_id=None, limit=20, **kw): """ Search unmapped WooCommerce products from the woo.product.map model. Params: query (str): Search string matched against woo_product_name and woo_sku. instance_id (int): woo.instance ID — filters results to this instance. limit (int): Max results to return (default 20). Returns: list of {id, woo_product_id, woo_product_name, woo_sku, woo_product_type} """ limit = min(int(limit or 20), 100) domain = [('state', '=', 'unmapped')] if instance_id: domain.append(('instance_id', '=', int(instance_id))) if query: domain += [ '|', ('woo_product_name', 'ilike', query), ('woo_sku', 'ilike', query), ] maps = request.env['woo.product.map'].search(domain, limit=limit) return [ { 'id': m.id, 'woo_product_id': m.woo_product_id, 'woo_product_name': m.woo_product_name or '', 'woo_sku': m.woo_sku or '', 'woo_product_type': m.woo_product_type or '', } for m in maps ] @http.route( '/woo/search/mapped', type='jsonrpc', auth='user', methods=['POST'], ) def search_mapped(self, query='', instance_id=None, limit=20, **kw): """ Search mapped WooCommerce ↔ Odoo product pairs. Params: query (str): Matched against woo_product_name, woo_sku, and linked product name. instance_id (int): woo.instance ID — filters results to this instance. limit (int): Max results to return (default 20). Returns: list of mapped product data dicts """ limit = min(int(limit or 20), 100) domain = [('state', '=', 'mapped')] if instance_id: domain.append(('instance_id', '=', int(instance_id))) if query: domain += [ '|', '|', ('woo_product_name', 'ilike', query), ('woo_sku', 'ilike', query), ('product_id.name', 'ilike', query), ] maps = request.env['woo.product.map'].search(domain, limit=limit) return [ { 'id': m.id, 'woo_product_id': m.woo_product_id, 'woo_product_name': m.woo_product_name or '', 'woo_sku': m.woo_sku or '', 'woo_product_type': m.woo_product_type or '', 'odoo_product_id': m.product_id.id if m.product_id else False, 'odoo_product_name': m.product_id.name if m.product_id else '', 'odoo_default_code': m.product_id.default_code or '' if m.product_id else '', 'instance_id': m.instance_id.id if m.instance_id else False, 'instance_name': m.instance_id.name if m.instance_id else '', } for m in maps ]