feat: 展示蝦皮主图和店铺 (#142)
This commit is contained in:
@@ -43,13 +43,13 @@ func GetCatalogImportRun(q Execer, source, batchID string) (model.CatalogImportR
|
||||
var run model.CatalogImportRun
|
||||
var observedAt, lastConflictAt, errorSummary, responseBody, finishedAt sql.NullString
|
||||
err := q.QueryRow(`SELECT source,batch_id,request_hash,status,request_count,conflict_count,
|
||||
observed_at,update_policy,last_request_at,last_conflict_at,shopee_created,shopee_updated,sku_created,
|
||||
observed_at,update_policy,last_request_at,last_conflict_at,shopee_created,shopee_updated,shopee_fields_filled,shopee_fields_same_source_updated,shopee_fields_manual_skipped,shopee_fields_stale_skipped,sku_created,
|
||||
sku_updated,sku_filled,sku_same_source_updated,sku_skipped,sku_manual_skipped,sku_stale_skipped,
|
||||
pdd_created,pdd_updated,association_created,association_unchanged,failure_count,
|
||||
error_summary,response_body,created_at,finished_at
|
||||
FROM catalog_import_runs WHERE source=? AND batch_id=?`, source, batchID).Scan(
|
||||
&run.Source, &run.BatchID, &run.RequestHash, &run.Status, &run.RequestCount, &run.ConflictCount,
|
||||
&observedAt, &run.UpdatePolicy, &run.LastRequestAt, &lastConflictAt, &run.ShopeeCreated, &run.ShopeeUpdated,
|
||||
&observedAt, &run.UpdatePolicy, &run.LastRequestAt, &lastConflictAt, &run.ShopeeCreated, &run.ShopeeUpdated, &run.ShopeeFieldsFilled, &run.ShopeeFieldsSameSourceUpdated, &run.ShopeeFieldsManualSkipped, &run.ShopeeFieldsStaleSkipped,
|
||||
&run.SKUCreated, &run.SKUUpdated, &run.SKUFilled, &run.SKUSameSourceUpdated, &run.SKUSkipped,
|
||||
&run.SKUManualSkipped, &run.SKUStaleSkipped, &run.PddCreated, &run.PddUpdated, &run.AssociationCreated,
|
||||
&run.AssociationUnchanged, &run.FailureCount, &errorSummary, &responseBody, &run.CreatedAt, &finishedAt)
|
||||
@@ -149,37 +149,78 @@ func RecordCatalogImportConflict(q Execer, source, batchID, requestedAt string)
|
||||
|
||||
// CompleteCatalogImportRun 把处理结果摘要和安全的响应 JSON 固化,供幂等重放。
|
||||
func CompleteCatalogImportRun(q Execer, run model.CatalogImportRun) error {
|
||||
result, err := q.Exec(`UPDATE catalog_import_runs SET status=?,shopee_created=?,shopee_updated=?,
|
||||
result, err := q.Exec(`UPDATE catalog_import_runs SET status=?,shopee_created=?,shopee_updated=?,shopee_fields_filled=?,shopee_fields_same_source_updated=?,shopee_fields_manual_skipped=?,shopee_fields_stale_skipped=?,
|
||||
sku_created=?,sku_updated=?,sku_filled=?,sku_same_source_updated=?,sku_skipped=?,
|
||||
sku_manual_skipped=?,sku_stale_skipped=?,pdd_created=?,pdd_updated=?,association_created=?,
|
||||
association_unchanged=?,failure_count=?,error_summary=NULLIF(?,''),response_body=NULLIF(?,''),
|
||||
finished_at=? WHERE source=? AND batch_id=?`, run.Status, run.ShopeeCreated, run.ShopeeUpdated,
|
||||
run.SKUCreated, run.SKUUpdated, run.SKUFilled, run.SKUSameSourceUpdated, run.SKUSkipped,
|
||||
run.ShopeeFieldsFilled, run.ShopeeFieldsSameSourceUpdated, run.ShopeeFieldsManualSkipped, run.ShopeeFieldsStaleSkipped, run.SKUCreated, run.SKUUpdated, run.SKUFilled, run.SKUSameSourceUpdated, run.SKUSkipped,
|
||||
run.SKUManualSkipped, run.SKUStaleSkipped, run.PddCreated, run.PddUpdated, run.AssociationCreated,
|
||||
run.AssociationUnchanged, run.FailureCount, run.ErrorSummary, run.ResponseBody,
|
||||
run.FinishedAt, run.Source, run.BatchID)
|
||||
return catalogRunUpdateResult(result, err, "完成商品目录批次")
|
||||
}
|
||||
|
||||
// UpsertCatalogShopeeProduct 按上游观测时间更新来源字段,绝不覆盖人工 PDD 关联。
|
||||
func UpsertCatalogShopeeProduct(q Execer, goodsID, title, status, mainSKU, observedAt, now string) (created, updated bool, err error) {
|
||||
var oldObserved sql.NullString
|
||||
err = q.QueryRow(`SELECT source_observed_at FROM shopee_products WHERE goods_id=?`, goodsID).Scan(&oldObserved)
|
||||
type CatalogShopeeProductInput struct{ GoodsID, Title, Status, MainSKU, ImageURL, ShopName, Source, ObservedAt, Now, UpdatePolicy string }
|
||||
type CatalogProductOutcome struct {
|
||||
Created, Updated bool
|
||||
FieldsFilled, FieldsSameSourceUpdated, FieldsManualSkipped, FieldsStaleSkipped int
|
||||
}
|
||||
|
||||
// UpsertCatalogShopeeProduct 独立保护主图和店铺字段,绝不覆盖人工 PDD 关联。
|
||||
func UpsertCatalogShopeeProduct(q Execer, in CatalogShopeeProductInput) (out CatalogProductOutcome, err error) {
|
||||
var oldObserved, imageURL, shopName, imageSource, imageObserved, shopSource, shopObserved sql.NullString
|
||||
var imageManual, shopManual int
|
||||
err = q.QueryRow(`SELECT source_observed_at,image_url,shopee_shop_name,image_source,image_observed_at,image_is_manual,shop_name_source,shop_name_observed_at,shop_name_is_manual FROM shopee_products WHERE goods_id=?`, in.GoodsID).Scan(&oldObserved, &imageURL, &shopName, &imageSource, &imageObserved, &imageManual, &shopSource, &shopObserved, &shopManual)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
_, err = q.Exec(`INSERT INTO shopee_products(goods_id,title,shopee_status,main_sku_code,source,
|
||||
source_observed_at,created_at,updated_at) VALUES(?,?,NULLIF(?,''),NULLIF(?,''),'api',?,?,?)`,
|
||||
goodsID, title, status, mainSKU, observedAt, now, now)
|
||||
return err == nil, false, err
|
||||
_, err = q.Exec(`INSERT INTO shopee_products(goods_id,title,shopee_status,main_sku_code,image_url,shopee_shop_name,image_source,image_observed_at,image_is_manual,shop_name_source,shop_name_observed_at,shop_name_is_manual,source,source_observed_at,created_at,updated_at) VALUES(?,?,NULLIF(?,''),NULLIF(?,''),NULLIF(?,''),NULLIF(?,''),CASE WHEN TRIM(?)='' THEN NULL ELSE ? END,CASE WHEN TRIM(?)='' THEN NULL ELSE ? END,0,CASE WHEN TRIM(?)='' THEN NULL ELSE ? END,CASE WHEN TRIM(?)='' THEN NULL ELSE ? END,0,'api',?,?,?)`, in.GoodsID, in.Title, in.Status, in.MainSKU, in.ImageURL, in.ShopName, in.ImageURL, in.Source, in.ImageURL, in.ObservedAt, in.ShopName, in.Source, in.ShopName, in.ObservedAt, in.ObservedAt, in.Now, in.Now)
|
||||
out.Created = err == nil
|
||||
return out, err
|
||||
}
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
return out, err
|
||||
}
|
||||
if oldObserved.Valid && oldObserved.String > observedAt {
|
||||
return false, false, nil
|
||||
baseUpdate := !oldObserved.Valid || oldObserved.String <= in.ObservedAt
|
||||
newImage, newShop := imageURL.String, shopName.String
|
||||
imageChanged, shopChanged := false, false
|
||||
apply := func(incoming string, current *string, source, observed sql.NullString, manual int) (changed bool) {
|
||||
if strings.TrimSpace(incoming) == "" || in.UpdatePolicy == "insert_only" {
|
||||
return false
|
||||
}
|
||||
if manual != 0 {
|
||||
out.FieldsManualSkipped++
|
||||
return false
|
||||
}
|
||||
if in.UpdatePolicy == "fill_missing" {
|
||||
if *current == "" {
|
||||
*current = incoming
|
||||
out.FieldsFilled++
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
if !source.Valid || source.String != in.Source {
|
||||
return false
|
||||
}
|
||||
if observed.Valid && observed.String > in.ObservedAt {
|
||||
out.FieldsStaleSkipped++
|
||||
return false
|
||||
}
|
||||
if *current != incoming {
|
||||
*current = incoming
|
||||
out.FieldsSameSourceUpdated++
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
_, err = q.Exec(`UPDATE shopee_products SET title=?,shopee_status=NULLIF(?,''),main_sku_code=NULLIF(?,''),
|
||||
source='api',source_observed_at=?,updated_at=? WHERE goods_id=?`, title, status, mainSKU, observedAt, now, goodsID)
|
||||
return false, err == nil, err
|
||||
imageChanged = apply(in.ImageURL, &newImage, imageSource, imageObserved, imageManual)
|
||||
shopChanged = apply(in.ShopName, &newShop, shopSource, shopObserved, shopManual)
|
||||
if !baseUpdate && !imageChanged && !shopChanged {
|
||||
return out, nil
|
||||
}
|
||||
_, err = q.Exec(`UPDATE shopee_products SET title=CASE WHEN ? THEN ? ELSE title END,shopee_status=CASE WHEN ? THEN NULLIF(?,'') ELSE shopee_status END,main_sku_code=CASE WHEN ? THEN NULLIF(?,'') ELSE main_sku_code END,source=CASE WHEN ? THEN 'api' ELSE source END,source_observed_at=CASE WHEN ? THEN ? ELSE source_observed_at END,image_url=NULLIF(?,''),shopee_shop_name=NULLIF(?,''),image_source=CASE WHEN ? THEN ? ELSE image_source END,image_observed_at=CASE WHEN ? THEN ? ELSE image_observed_at END,shop_name_source=CASE WHEN ? THEN ? ELSE shop_name_source END,shop_name_observed_at=CASE WHEN ? THEN ? ELSE shop_name_observed_at END,updated_at=? WHERE goods_id=?`, baseUpdate, in.Title, baseUpdate, in.Status, baseUpdate, in.MainSKU, baseUpdate, baseUpdate, in.ObservedAt, newImage, newShop, imageChanged, in.Source, imageChanged, in.ObservedAt, shopChanged, in.Source, shopChanged, in.ObservedAt, in.Now, in.GoodsID)
|
||||
out.Updated = err == nil
|
||||
return out, err
|
||||
}
|
||||
|
||||
type CatalogSKUOutcome string
|
||||
|
||||
Reference in New Issue
Block a user