fix: add missing action_fetch_products and action_sync methods

Product mapping UI called these methods but they didn't exist on
woo.instance. action_fetch_products fetches WC products via API,
auto-matches by SKU, handles variations. action_sync runs all
enabled sync types manually.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-03-31 22:28:35 -04:00
parent 396f895ae2
commit ab16040eb4

View File

@@ -147,6 +147,146 @@ class WooInstance(models.Model):
'company_id': self.company_id.id,
})
# ------------------------------------------------------------------
# UI actions (called from OWL product mapping + dashboard)
# ------------------------------------------------------------------
def action_fetch_products(self):
"""Fetch products from WooCommerce and run auto-match."""
self.ensure_one()
if self.state != 'connected':
raise UserError("Please test the connection first.")
client = self._get_client()
ProductMap = self.env['woo.product.map']
page = 1
total_fetched = 0
auto_matched = 0
while True:
try:
products = client.get_products(page=page, per_page=100)
except Exception as e:
self._log_sync('product', 'woo_to_odoo', self.name, 'failed', str(e))
raise UserError("Failed to fetch products: %s" % str(e))
if not products:
break
for wc_prod in products:
wc_id = wc_prod.get('id')
# Skip if already mapped
existing = ProductMap.search([
('instance_id', '=', self.id),
('woo_product_id', '=', wc_id),
], limit=1)
if existing:
continue
wc_sku = wc_prod.get('sku', '') or ''
wc_name = wc_prod.get('name', '')
wc_type = wc_prod.get('type', 'simple')
# Try SKU match
odoo_product = False
match_state = 'unmapped'
if wc_sku:
odoo_product = self.env['product.product'].search([
('default_code', '=', wc_sku),
], limit=1)
if odoo_product:
match_state = 'mapped'
auto_matched += 1
ProductMap.create({
'instance_id': self.id,
'product_id': odoo_product.id if odoo_product else False,
'woo_product_id': wc_id,
'woo_product_name': wc_name,
'woo_sku': wc_sku,
'woo_product_type': wc_type if wc_type in ('simple', 'variable', 'grouped', 'external') else 'simple',
'state': match_state,
'company_id': self.company_id.id,
})
total_fetched += 1
# Fetch variations for variable products
if wc_type == 'variable':
try:
var_page = 1
while True:
variations = client.get_product_variations(wc_id, page=var_page, per_page=100)
if not variations:
break
for var in variations:
var_id = var.get('id')
var_existing = ProductMap.search([
('instance_id', '=', self.id),
('woo_product_id', '=', var_id),
], limit=1)
if var_existing:
continue
var_sku = var.get('sku', '') or ''
var_name = wc_name + ' - ' + ', '.join(
[a.get('option', '') for a in var.get('attributes', [])]
)
var_product = False
var_state = 'unmapped'
if var_sku:
var_product = self.env['product.product'].search([
('default_code', '=', var_sku),
], limit=1)
if var_product:
var_state = 'mapped'
auto_matched += 1
ProductMap.create({
'instance_id': self.id,
'product_id': var_product.id if var_product else False,
'woo_product_id': var_id,
'woo_product_name': var_name,
'woo_sku': var_sku,
'woo_product_type': 'simple',
'woo_parent_id': wc_id,
'is_variation': True,
'state': var_state,
'company_id': self.company_id.id,
})
total_fetched += 1
var_page += 1
if len(variations) < 100:
break
except Exception:
_logger.warning("Failed to fetch variations for product %s", wc_id)
page += 1
if len(products) < 100:
break
self._log_sync('product', 'woo_to_odoo', self.name, 'success',
'Fetched %d products, auto-matched %d by SKU' % (total_fetched, auto_matched))
return True
def action_sync(self):
"""Manual sync trigger from the UI."""
self.ensure_one()
if self.state != 'connected':
raise UserError("Instance is not connected.")
try:
if self.sync_products:
self._sync_products()
if self.sync_orders:
self._sync_orders()
if self.sync_inventory:
self._sync_inventory()
if self.sync_customers:
self._sync_customers()
self.last_sync = fields.Datetime.now()
except Exception as e:
_logger.error("Manual sync failed for %s: %s", self.name, str(e))
self._log_sync('product', 'odoo_to_woo', self.name, 'failed', str(e))
raise UserError("Sync failed: %s" % str(e))
return True
# ------------------------------------------------------------------
# Cron entry points
# ------------------------------------------------------------------