From 1a679a45c3dc49c0d91a1fc6d883f28dad2b00ae Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Wed, 1 Apr 2026 21:53:41 -0400 Subject: [PATCH] fix: serve variant images via custom endpoint instead of product URL Product image URL was serving placeholder because writing to image_1920 doesn't work for variants (computed field). New approach: 1. Store image in wizard line table (attachment=False, bytea column) 2. Serve directly via /woo/image/{line_id}/{filename} endpoint 3. WC downloads real image data from this URL 4. Also saves to image_variant_1920 for Odoo reference Co-Authored-By: Claude Opus 4.6 (1M context) --- .../fusion_woocommerce/controllers/api.py | 25 ++++++++++++++++++- .../wizard/woo_variant_push.py | 23 +++++------------ 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/fusion-woo-odoo/fusion_woocommerce/controllers/api.py b/fusion-woo-odoo/fusion_woocommerce/controllers/api.py index 175881d9..11607ece 100644 --- a/fusion-woo-odoo/fusion_woocommerce/controllers/api.py +++ b/fusion-woo-odoo/fusion_woocommerce/controllers/api.py @@ -2,11 +2,12 @@ # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) +import base64 import logging from odoo import http from odoo.exceptions import AccessDenied -from odoo.http import request +from odoo.http import request, Response _logger = logging.getLogger(__name__) @@ -14,6 +15,28 @@ _logger = logging.getLogger(__name__) class WooApiController(http.Controller): """REST endpoints consumed by the WooCommerce WordPress plugin.""" + @http.route('/woo/image//', + type='http', auth='none', csrf=False, methods=['GET']) + def serve_variant_image(self, line_id, filename, **kw): + """Serve a variant image from the transient wizard line. + Used by WC to download images during variant push.""" + try: + line = request.env['woo.variant.push.line'].sudo().browse(line_id) + if not line.exists() or not line.image: + return request.not_found() + img_data = line.image + if isinstance(img_data, str): + img_data = base64.b64decode(img_data) + elif isinstance(img_data, memoryview): + img_data = bytes(img_data) + content_type = 'image/png' + if filename.lower().endswith('.jpg') or filename.lower().endswith('.jpeg'): + content_type = 'image/jpeg' + return Response(img_data, content_type=content_type, status=200) + except Exception as e: + _logger.error("Failed to serve variant image %d: %s", line_id, e) + return request.not_found() + def _authenticate_instance(self): """ Validate Bearer token from Authorization header against woo.instance.odoo_api_key. diff --git a/fusion-woo-odoo/fusion_woocommerce/wizard/woo_variant_push.py b/fusion-woo-odoo/fusion_woocommerce/wizard/woo_variant_push.py index 8ff0b87e..861688ef 100644 --- a/fusion-woo-odoo/fusion_woocommerce/wizard/woo_variant_push.py +++ b/fusion-woo-odoo/fusion_woocommerce/wizard/woo_variant_push.py @@ -248,33 +248,22 @@ class WooVariantPushWizard(models.TransientModel): if wc_tax_class: var_data['tax_class'] = wc_tax_class - # Save wizard image to Odoo product, then pass URL to WC + # Serve image directly from wizard line via custom endpoint if line.image: - img_data = line.image - img_size = len(img_data) if img_data else 0 - _logger.info("Variant %d image data: type=%s size=%d", variant.id, type(img_data).__name__, img_size) - # Save the image from the wizard to the actual Odoo product - if img_size > 100: # Skip tiny placeholders - variant.sudo().write({'image_1920': img_data}) - self.env.cr.commit() # Force commit so the image is available for download - _logger.info("Saved image to Odoo product %d (%d bytes)", variant.id, img_size) - else: - _logger.warning("Skipping tiny image for variant %d (%d bytes)", variant.id, img_size) - - # Now build the public URL for WC to download + # Commit the line data so the image endpoint can read it + self.env.cr.commit() odoo_base = inst.env['ir.config_parameter'].sudo().get_param('web.base.url', '') if odoo_base: img_name = (line.sku or variant.default_code or 'variant') + '.png' - # Add timestamp to bust WC cache - import time - cache_bust = int(time.time()) - img_url = f"{odoo_base}/web/image/product.product/{variant.id}/image_1920/{img_name}?t={cache_bust}" + img_url = f"{odoo_base}/woo/image/{line.id}/{img_name}" var_data['image'] = { 'src': img_url, 'name': img_name, 'alt': line.variant_name or '', } _logger.info("Variant image URL: %s", img_url) + # Also save to Odoo product for future reference + variant.sudo().write({'image_variant_1920': line.image}) try: client.update_product_variation(pm.woo_product_id, wc_var_id, var_data)