package service import ( "errors" "testing" "time" "cmautobuy/admin/model" "cmautobuy/admin/repository" ) func TestShop_管理员维护单一店铺名称并精确关联历史数据(t *testing.T) { db := newTestDB(t) now := time.Date(2026, 8, 13, 10, 0, 0, 0, time.UTC) admin := &model.User{UserID: "SHOP-ADMIN", Username: "shop-admin", PasswordHash: "x", Role: model.RoleAdmin, Status: model.UserActive, PasswordChangedAt: model.NowISO(), CreatedAt: model.NowISO(), UpdatedAt: model.NowISO()} if err := repository.CreateUser(db, *admin); err != nil { t.Fatal(err) } if _, err := db.Exec(`INSERT INTO shopee_products(goods_id,title,shopee_shop_name,source,created_at,updated_at) VALUES('S-HISTORY','历史商品','统一店铺','api',?,?)`, model.NowISO(), model.NowISO()); err != nil { t.Fatal(err) } if err := CreateShop(db, admin, "统一店铺", now); err != nil { t.Fatal(err) } result, err := ListShops(db, admin) if err != nil || len(result.Items) != 1 { t.Fatalf("店铺列表错误: %+v %v", result, err) } shop := result.Items[0] if !shop.Enabled || shop.ShopeeProductCount != 1 { t.Fatalf("店铺状态或回填错误: %+v", shop) } product, err := repository.GetShopeeProductByGoodsID(db, "S-HISTORY") if err != nil || product.ShopID != shop.ShopID { t.Fatalf("蝦皮商品未精确关联: %+v %v", product, err) } var aliases int if err := db.QueryRow(`SELECT COUNT(*) FROM shop_channel_aliases WHERE shop_id=? AND alias_name='统一店铺' AND enabled=1`, shop.ShopID).Scan(&aliases); err != nil || aliases != 2 { t.Fatalf("两个兼容渠道记录必须由同一名称派生: count=%d err=%v", aliases, err) } if err := SetShopEnabled(db, admin, shop.ShopID, false, now.Add(time.Minute)); err != nil { t.Fatal(err) } if err := db.QueryRow(`SELECT COUNT(*) FROM shop_channel_aliases WHERE shop_id=? AND enabled=0`, shop.ShopID).Scan(&aliases); err != nil || aliases != 2 { t.Fatalf("停用状态必须同步到兼容数据: count=%d err=%v", aliases, err) } if count, err := CountEnabledSybAllowedShops(db); err != nil || count != 0 { t.Fatalf("SYB 停用没有生效: %d %v", count, err) } if err := EnsureEnabledSybAllowedShops(db); !IsValidationError(err) { t.Fatalf("没有启用 SYB 店铺应阻止同步: %v", err) } if err := DeleteShop(db, admin, shop.ShopID); !IsValidationError(err) { t.Fatalf("有关联商品的店铺不能删除: %v", err) } } func TestShop_店铺名称不可重复且采购员不能管理(t *testing.T) { db := newTestDB(t) now := time.Now() admin := &model.User{UserID: "SHOP-ADMIN-2", Username: "shop-admin-2", PasswordHash: "x", Role: model.RoleAdmin, Status: model.UserActive, PasswordChangedAt: model.NowISO(), CreatedAt: model.NowISO(), UpdatedAt: model.NowISO()} if err := repository.CreateUser(db, *admin); err != nil { t.Fatal(err) } if err := CreateShop(db, admin, "店铺一", now); err != nil { t.Fatal(err) } if err := CreateShop(db, admin, "店铺一", now); !IsValidationError(err) { t.Fatalf("重复店铺名称必须拒绝: %v", err) } purchaser := &model.User{UserID: "BUYER", Role: model.RolePurchaser, Status: model.UserActive} if err := CreateShop(nil, purchaser, "店铺", now); !errors.Is(err, ErrAdminRequired) { t.Fatalf("采购员新增应被拒绝: %v", err) } if _, err := ListShops(nil, purchaser); !errors.Is(err, ErrAdminRequired) { t.Fatalf("采购员读取管理页应被拒绝: %v", err) } }