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:
@@ -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
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user