fix: 产品导入去重 — 批次内product_code去重 + DB层按product_code+org_id兜底查重

- 批次内seen_codes去重: 同一导入批次中相同product_code只处理第一条
- DB查重增加fallback: resource_ref_id查不到时再按product_code+org_id查
- update时同步写入resource_ref_id
This commit is contained in:
Hermes Agent 2026-06-23 18:07:30 +08:00
parent 984fc73bd6
commit 265081c43f

View File

@ -1172,13 +1172,21 @@ class ProductManager:
created_cats += 1 created_cats += 1
# Step 3: Process products — update existing, create new # Step 3: Process products — update existing, create new
# Local dedup: skip duplicate product_code within same import batch
seen_codes = set()
for prod in products: for prod in products:
target_cat_id = source_to_id.get(prod.get('source_category_id')) target_cat_id = source_to_id.get(prod.get('source_category_id'))
if not target_cat_id: if not target_cat_id:
continue continue
product_code = prod.get('product_code', '')
resource_ref_id = prod.get('resource_ref_id', '') resource_ref_id = prod.get('resource_ref_id', '')
# Skip duplicate product_code in this batch
if product_code in seen_codes:
continue
seen_codes.add(product_code)
# Check if product already exists by resource_ref_id + org_id # Check if product already exists by resource_ref_id + org_id
existing_prod = None existing_prod = None
if resource_ref_id: if resource_ref_id:
@ -1188,15 +1196,24 @@ class ProductManager:
{'ref_id': resource_ref_id, 'org_id': org_id} {'ref_id': resource_ref_id, 'org_id': org_id}
) )
# Fallback: check by product_code + org_id (unique constraint)
if not existing_prod and product_code:
existing_prod = await sor.sqlExe(
"""SELECT id FROM product
WHERE product_code = ${code}$ AND org_id = ${org_id}$""",
{'code': product_code, 'org_id': org_id}
)
if existing_prod: if existing_prod:
# Update existing product # Update existing product
await sor.U('product', { await sor.U('product', {
'id': existing_prod[0].id, 'id': existing_prod[0].id,
'product_name': prod.get('product_name', ''), 'product_name': prod.get('product_name', ''),
'product_code': prod.get('product_code', ''), 'product_code': product_code,
'product_type': prod.get('product_type', ''), 'product_type': prod.get('product_type', ''),
'brief_intro': prod.get('brief_intro', ''), 'brief_intro': prod.get('brief_intro', ''),
'category_id': target_cat_id, 'category_id': target_cat_id,
'resource_ref_id': resource_ref_id,
'sort_order': str(prod.get('sort_order', 0)), 'sort_order': str(prod.get('sort_order', 0)),
'updated_at': now 'updated_at': now
}) })