diff --git a/admin/repository/mysql_db.go b/admin/repository/mysql_db.go index 2232c56..8fb3ce5 100644 --- a/admin/repository/mysql_db.go +++ b/admin/repository/mysql_db.go @@ -547,13 +547,16 @@ func MigrateMySQL(db *sql.DB) error { return CheckMySQLSchema(db) } -// migrateMySQLV10 修复曾在 v8 开发中间状态记录过版本的数据库。 -// v8 迁移本身逐项检查列和索引且回填只处理空值,因此可安全重放; +// migrateMySQLV10 修复曾在 v8/v9 开发中间状态记录过版本的数据库。 +// 两版迁移均逐项检查结构,v8 回填只处理空值,因此可安全重放; // 历史 v8/v9 版本记录保持不变,完整自检通过后再追加 v10。 func migrateMySQLV10(db *sql.DB) error { if err := migrateMySQLV8(db); err != nil { return fmt.Errorf("修复商品目录 SKU v8 结构失败: %w", err) } + if err := migrateMySQLV9(db); err != nil { + return fmt.Errorf("修复蝦皮商品 v9 结构失败: %w", err) + } return nil } diff --git a/admin/repository/mysql_db_integration_test.go b/admin/repository/mysql_db_integration_test.go index 49f7ac3..15743f9 100644 --- a/admin/repository/mysql_db_integration_test.go +++ b/admin/repository/mysql_db_integration_test.go @@ -468,7 +468,7 @@ func TestMySQLMigrate_V9形状错误不记版本(t *testing.T) { } } -func TestMySQLMigrate_已记录V9但缺少SKU来源字段时由V10修复(t *testing.T) { +func TestMySQLMigrate_已记录V9但缺少V8V9结构时由V10修复(t *testing.T) { db := openMySQLMigrationTestDB(t) defer db.Close() cleanMySQLTestSchema(t, db) @@ -486,6 +486,9 @@ func TestMySQLMigrate_已记录V9但缺少SKU来源字段时由V10修复(t *test if err := migrateMySQLV9(db); err != nil { t.Fatal(err) } + // 同时模拟 v9 已记录但两个图片/店铺人工标记约束尚未建立。 + mustExec(t, db, `ALTER TABLE shopee_products DROP CHECK chk_shopee_products_image_manual`) + mustExec(t, db, `ALTER TABLE shopee_products DROP CHECK chk_shopee_products_shop_manual`) mustExec(t, db, `INSERT INTO schema_migrations(version,applied_at) VALUES (8,'2026-08-11T00:00:00Z'),(9,'2026-08-11T00:00:00Z')`) diff --git a/docs/admin/03-data-model.md b/docs/admin/03-data-model.md index 955d404..75c35fe 100644 --- a/docs/admin/03-data-model.md +++ b/docs/admin/03-data-model.md @@ -445,9 +445,10 @@ MySQL schema v9 为 `shopee_products` 增加 `image_url` 和 `shopee_shop_name` 商品主图,与 `syb_orders.image_url` 的历史货运单观测图片是两个独立概念。 MySQL schema v10(工单 #144)是兼容修复:部分数据库曾在 v8 开发中间状态提前记录 -v8/v9,实际缺少 `field_sources` 或 `field_observed_at`。v10 幂等重放 v8 的逐项建列、 -空值回填和唯一索引逻辑,再核对 v8/v9 完整形状;只有全部通过才记录 v10。它不删除 -或改写旧迁移记录,也不清空商品、SKU 或导入记录。 +v8/v9,实际缺少 `field_sources`、`field_observed_at` 或 v9 图片/店铺人工标记约束。 +v10 幂等重放 v8、v9 的逐项建列、空值回填、约束和唯一索引逻辑,再核对两版完整 +形状;只有全部通过才记录 v10。它不删除或改写旧迁移记录,也不清空商品、SKU 或 +导入记录。 蝦皮详情把 `syb_orders` 按 `(shopee_goods_id, spec_key)` 聚合为“顺运宝观测规格”: 订单数按唯一 `syb_id` 行计数,累计数量求和,最近一行提供历史台币售价和图片。 diff --git a/docs/admin/10-商品目录接入接口.md b/docs/admin/10-商品目录接入接口.md index 5b4743c..dc7a5c2 100644 --- a/docs/admin/10-商品目录接入接口.md +++ b/docs/admin/10-商品目录接入接口.md @@ -93,9 +93,10 @@ HTTP/HTTPS URL,最长 2048 字节;店铺名最长 500 个字符。Admin 只 迁移只增加列和唯一索引,既有 `sku_id` 继续作为内部主键,因此历史引用不变;若检测 到同商品重复 `spec_key`,迁移会停止且不记录 v8,必须人工确认,不能自动合并。 -若数据库已经记录 v8 或 v9,但缺少 `field_sources`、`field_observed_at` 等后加入的 -v8 结构,v10 会自动补齐并只回填空值。不要通过删除迁移版本、清库或手工伪造字段来 -绕过自检;修复完成且 v8/v9 形状均正确后,程序才会记录 v10。 +若数据库已经记录 v8 或 v9,但缺少 `field_sources`、`field_observed_at` 等 v8 结构, +或缺少图片、店铺人工标记约束等 v9 结构,v10 会幂等重放两版迁移并只回填空值。 +不要通过删除迁移版本、清库或手工伪造结构来绕过自检;修复完成且 v8/v9 形状均 +正确后,程序才会记录 v10。 旧版 Admin 不理解无真实 SKU ID 的新记录。应用回退前应暂停目录接口并确认没有此类 记录;不要删除 v8 列或把内部主键复制成伪造的外部 SKU ID。