package service import ( "errors" "testing" "time" "cmautobuy/admin/model" "cmautobuy/admin/repository" ) func TestSybAllowedShop_管理员维护与精确去重(t *testing.T) { db := newTestDB(t) now := time.Date(2026, 8, 12, 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 := CreateSybAllowedShop(db, admin, " qwg8fkb044 ", now); err != nil { t.Fatal(err) } if _, err := repository.UpsertSybOrder(db, model.SybOrder{ SybID: "SHOP-HISTORY", OrderNo: "ORDER-HISTORY", ShopName: "qwg8fkb044", Quantity: 1, SybData: `{}`, CreatedAt: model.NowISO(), UpdatedAt: model.NowISO(), }); err != nil { t.Fatal(err) } if err := repository.CreateSybSyncRun(db, model.SybSyncRun{ RunID: "SHOP-RUN-HISTORY", UserID: admin.UserID, DateFrom: "2026-08-12", DateTo: "2026-08-12", Status: model.SybSyncRunning, StartedAt: model.NowISO(), }); err != nil { t.Fatal(err) } rows, err := ListSybAllowedShops(db, admin) if err != nil || len(rows) != 1 || rows[0].ShopName != "qwg8fkb044" || !rows[0].Enabled { t.Fatalf("新增结果错误: rows=%+v err=%v", rows, err) } if err := CreateSybAllowedShop(db, admin, "qwg8fkb044", now); !IsValidationError(err) { t.Fatalf("去除首尾空白后的重名应是表单错误,实际 %v", err) } if err := SetSybAllowedShopEnabled(db, admin, rows[0].ShopID, false, now.Add(time.Minute)); err != nil { t.Fatal(err) } if count, err := CountEnabledSybAllowedShops(db); err != nil || count != 0 { t.Fatalf("停用后启用数错误: count=%d err=%v", count, err) } if err := EnsureEnabledSybAllowedShops(db); !IsValidationError(err) { t.Fatalf("空白名单应阻止同步: %v", err) } if err := DeleteDisabledSybAllowedShop(db, admin, rows[0].ShopID); err != nil { t.Fatalf("删除已停用店铺失败: %v", err) } if list, err := ListSybAllowedShops(db, admin); err != nil || len(list) != 0 { t.Fatalf("删除后仍存在: rows=%+v err=%v", list, err) } if count, err := repository.CountSybOrdersTotal(db); err != nil || count != 1 { t.Fatalf("删除配置不应影响历史货运单: count=%d err=%v", count, err) } if count, err := repository.CountSybSyncRuns(db); err != nil || count != 1 { t.Fatalf("删除配置不应影响同步记录: count=%d err=%v", count, err) } if err := CreateSybAllowedShop(db, admin, "qwg8fkb044", now.Add(2*time.Minute)); err != nil { t.Fatalf("删除后应允许重新新增同名店铺: %v", err) } newRows, _ := ListSybAllowedShops(db, admin) if err := DeleteDisabledSybAllowedShop(db, admin, newRows[0].ShopID); !IsValidationError(err) { t.Fatalf("启用店铺必须拒绝删除: %v", err) } } func TestSybAllowedShop_采购员不能管理(t *testing.T) { purchaser := &model.User{UserID: "BUYER", Role: model.RolePurchaser, Status: model.UserActive} if err := CreateSybAllowedShop(nil, purchaser, "店铺", time.Now()); !errors.Is(err, ErrAdminRequired) { t.Fatalf("采购员新增应被拒绝: %v", err) } if _, err := ListSybAllowedShops(nil, purchaser); !errors.Is(err, ErrAdminRequired) { t.Fatalf("采购员读取管理列表应被拒绝: %v", err) } if err := DeleteDisabledSybAllowedShop(nil, purchaser, "SHOP-1"); !errors.Is(err, ErrAdminRequired) { t.Fatalf("采购员删除应被拒绝: %v", err) } }