feat: 完善 SYB 蝦皮主数据与软删除 (#203 #204 #205)

This commit is contained in:
chengma
2026-08-13 10:39:21 +08:00
parent 3af9bf245a
commit ad1ccc2c60
23 changed files with 864 additions and 90 deletions
+62
View File
@@ -10,6 +10,7 @@ import (
"cmautobuy/admin/config"
"cmautobuy/admin/model"
"cmautobuy/admin/spec"
)
func newSybTestDB(t *testing.T) *sql.DB {
@@ -140,6 +141,67 @@ func TestUpsertSybOrder_只更新Syb骨架标题(t *testing.T) {
}
}
func TestUpsertSybOrder_店铺图片按字段来源保护(t *testing.T) {
db := newSybTestDB(t)
order := model.SybOrder{SybID: "META-1", OrderNo: "O-META", Title: "商品", ShopeeGoodsID: "SP-META", ProductSpec: "黑色,M", ShopName: "店铺一", ImageURL: "https://example.com/1.jpg", Quantity: 1, SybData: "{}"}
if _, err := UpsertSybOrder(db, order); err != nil {
t.Fatal(err)
}
var shop, image, shopSource, imageSource string
if err := db.QueryRow(`SELECT shopee_shop_name,image_url,shop_name_source,image_source FROM shopee_products WHERE goods_id='SP-META'`).Scan(&shop, &image, &shopSource, &imageSource); err != nil {
t.Fatal(err)
}
if shop != "店铺一" || image != "https://example.com/1.jpg" || shopSource != "syb" || imageSource != "syb" {
t.Fatalf("首次补全不正确:shop=%q image=%q sources=%q/%q", shop, image, shopSource, imageSource)
}
order.ShopName, order.ImageURL = "店铺二", "https://example.com/2.jpg"
if _, err := UpsertSybOrder(db, order); err != nil {
t.Fatal(err)
}
if _, err := db.Exec(`UPDATE shopee_products SET image_url='https://example.com/api.jpg',image_source='api',shop_name_is_manual=1 WHERE goods_id='SP-META'`); err != nil {
t.Fatal(err)
}
order.ShopName, order.ImageURL = "不应覆盖的店铺", "https://example.com/3.jpg"
if _, err := UpsertSybOrder(db, order); err != nil {
t.Fatal(err)
}
if err := db.QueryRow(`SELECT shopee_shop_name,image_url FROM shopee_products WHERE goods_id='SP-META'`).Scan(&shop, &image); err != nil {
t.Fatal(err)
}
if shop != "店铺二" || image != "https://example.com/api.jpg" {
t.Fatalf("字段保护失败:shop=%q image=%q", shop, image)
}
}
func TestUpsertSybShopeeSKU_确定性解析并允许权威来源升级(t *testing.T) {
db := newSybTestDB(t)
now := model.NowISO()
if _, err := db.Exec(`INSERT INTO shopee_products(goods_id,title,source,created_at,updated_at) VALUES('SP-SKU','商品','syb',?,?)`, now, now); err != nil {
t.Fatal(err)
}
parsed, err := UpsertSybShopeeSKU(db, "SP-SKU", "白色,L【建議50-60公斤】", now)
if err != nil || !parsed {
t.Fatalf("SYB 规格应解析成功:parsed=%v err=%v", parsed, err)
}
if parsed, err := UpsertSybShopeeSKU(db, "SP-SKU", "不明确规格", now); err != nil || parsed {
t.Fatalf("不明确规格不应写入:parsed=%v err=%v", parsed, err)
}
key, _ := spec.SpecKey("白色,L【建議50-60公斤】")
outcome, err := UpsertCatalogShopeeSKU(db, CatalogShopeeSKUInput{RecordID: "API-NEW", ShopeeSKUID: "REAL-1", GoodsID: "SP-SKU", SpecRaw: "白色,L【建議50-60公斤】", SpecKey: key, Color: "象牙白", Size: "L", Advice: "建议50-60公斤", ParseOK: true, Source: "partner", ObservedAt: now, Now: now, UpdatePolicy: "fill_missing"})
if err != nil || outcome != CatalogSKUFilled {
t.Fatalf("权威来源升级失败:outcome=%s err=%v", outcome, err)
}
var count int
var external, color, sourceJSON string
if err := db.QueryRow(`SELECT COUNT(*),MAX(COALESCE(shopee_sku_id,'')),MAX(COALESCE(color,'')),MAX(COALESCE(field_sources,'')) FROM shopee_skus WHERE goods_id='SP-SKU'`).Scan(&count, &external, &color, &sourceJSON); err != nil {
t.Fatal(err)
}
if count != 1 || external != "REAL-1" || color != "象牙白" || !strings.Contains(sourceJSON, `"color":"partner"`) {
t.Fatalf("升级后数据不正确:count=%d external=%q color=%q sources=%s", count, external, color, sourceJSON)
}
}
func TestUpsertSybOrder_ShopeeGoodsID会被同步更新(t *testing.T) {
db := newSybTestDB(t)