feat: 统一 Admin 主列表分页 (#64)
This commit is contained in:
@@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -12,6 +13,42 @@ import (
|
||||
"cmautobuy/admin/repository"
|
||||
)
|
||||
|
||||
func TestListClientPageForUser_分页统计不泄露其他采购员客户端(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
admin, buyerA, _ := prepareClientAssignmentUsers(t, db)
|
||||
now := time.Now().UTC()
|
||||
for i := 0; i < 22; i++ {
|
||||
clientID := fmt.Sprintf("page-client-%02d", i)
|
||||
if err := RegisterClient(db, model.Client{ClientID: clientID, Name: clientID}, true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i < 21 {
|
||||
if _, _, err := AssignClient(db, admin, clientID, buyerA.UserID, now); err != nil {
|
||||
t.Fatalf("绑定 %s 失败: %v", clientID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buyerPage, err := ListClientPageForUser(db, buyerA, "", time.Hour, 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(buyerPage.Rows) != 1 || buyerPage.Total != 21 || buyerPage.Page != 2 || buyerPage.TotalPages != 2 {
|
||||
t.Fatalf("采购员分页不对: rows=%d total=%d page=%d/%d",
|
||||
len(buyerPage.Rows), buyerPage.Total, buyerPage.Page, buyerPage.TotalPages)
|
||||
}
|
||||
if buyerPage.Online+buyerPage.Offline != 21 {
|
||||
t.Fatalf("采购员统计泄露或漏算: online=%d offline=%d", buyerPage.Online, buyerPage.Offline)
|
||||
}
|
||||
adminPage, err := ListClientPageForUser(db, admin, "", time.Hour, 999)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if adminPage.Total != 22 || adminPage.Page != 2 || len(adminPage.Rows) != 2 {
|
||||
t.Fatalf("管理员分页不对: rows=%d total=%d page=%d", len(adminPage.Rows), adminPage.Total, adminPage.Page)
|
||||
}
|
||||
}
|
||||
|
||||
// newTestDB 建一个临时库,测试结束自动删。
|
||||
// 用真实的 migrations,这样表结构变了测试会跟着失败。
|
||||
func newTestDB(t *testing.T) *sql.DB {
|
||||
|
||||
+26
-10
@@ -238,26 +238,42 @@ type PddProductView struct {
|
||||
|
||||
// PddListResult 是列表页要的全部数据。
|
||||
type PddListResult struct {
|
||||
Rows []PddProductView
|
||||
Total int // 全部未删除记录数,不受筛选影响
|
||||
Counts map[model.CollectStatus]int
|
||||
IsFiltered bool
|
||||
Rows []PddProductView
|
||||
Total int // 全部未删除记录数,不受筛选影响
|
||||
FilteredTotal int // 当前筛选下的总数,用于页数和筛选状态
|
||||
Page int
|
||||
TotalPages int
|
||||
Counts map[model.CollectStatus]int
|
||||
IsFiltered bool
|
||||
}
|
||||
|
||||
// ListPddProducts 查列表并把每一行翻成界面文字。
|
||||
func ListPddProducts(db *sql.DB, keyword string, status model.CollectStatus) (*PddListResult, error) {
|
||||
rows, err := repository.ListPddProducts(db, keyword, status)
|
||||
func ListPddProducts(db *sql.DB, keyword string, status model.CollectStatus, requestedPage int) (*PddListResult, error) {
|
||||
page := requestedPage
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
rows, filteredTotal, err := repository.ListPddProducts(db, keyword, status, PageSize, (page-1)*PageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
totalPages := TotalPages(filteredTotal)
|
||||
clampedPage := ClampPage(page, totalPages)
|
||||
if clampedPage != page {
|
||||
page = clampedPage
|
||||
rows, _, err = repository.ListPddProducts(db, keyword, status, PageSize, (page-1)*PageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
counts, err := repository.CountPddProductsByStatus(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &PddListResult{
|
||||
Rows: make([]PddProductView, 0, len(rows)),
|
||||
Counts: counts,
|
||||
Rows: make([]PddProductView, 0, len(rows)), Counts: counts,
|
||||
FilteredTotal: filteredTotal, Page: page, TotalPages: totalPages,
|
||||
IsFiltered: strings.TrimSpace(keyword) != "" || status != "",
|
||||
}
|
||||
for _, n := range counts {
|
||||
@@ -312,9 +328,9 @@ func (r *PddListResult) StatusLine() string {
|
||||
}
|
||||
line := strings.Join(parts, " · ")
|
||||
if r.IsFiltered {
|
||||
line = fmt.Sprintf("筛选出 %d 条 / %s", len(r.Rows), line)
|
||||
line = fmt.Sprintf("筛选出 %d 条 / %s", r.FilteredTotal, line)
|
||||
}
|
||||
return line
|
||||
return fmt.Sprintf("%s · 第 %d/%d 页", line, r.Page, r.TotalPages)
|
||||
}
|
||||
|
||||
// ---------- 弹窗 ----------
|
||||
|
||||
@@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -12,6 +13,33 @@ import (
|
||||
"cmautobuy/admin/repository"
|
||||
)
|
||||
|
||||
func TestListPddProducts_统一每页20条并收敛越界页(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
for i := 0; i < 25; i++ {
|
||||
goodsID := fmt.Sprintf("73711653%04d", i)
|
||||
if _, err := CreatePddProduct(db,
|
||||
"https://mobile.yangkeduo.com/goods.html?goods_id="+goodsID); err != nil {
|
||||
t.Fatalf("创建第 %d 个商品失败: %v", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
second, err := ListPddProducts(db, "", "", 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(second.Rows) != 5 || second.FilteredTotal != 25 || second.Page != 2 || second.TotalPages != 2 {
|
||||
t.Fatalf("第二页结果不对: rows=%d total=%d page=%d/%d",
|
||||
len(second.Rows), second.FilteredTotal, second.Page, second.TotalPages)
|
||||
}
|
||||
overflow, err := ListPddProducts(db, "", "", 999)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if overflow.Page != 2 || len(overflow.Rows) != 5 {
|
||||
t.Fatalf("越界页应收敛到末页: page=%d rows=%d", overflow.Page, len(overflow.Rows))
|
||||
}
|
||||
}
|
||||
|
||||
// ── 链接解析 ───────────────────────────────────────────
|
||||
|
||||
func TestParsePddGoodsID_认得的写法(t *testing.T) {
|
||||
@@ -259,7 +287,7 @@ func TestListPddProducts_规格数(t *testing.T) {
|
||||
repository.SetCollectResult(db, "100000000002", "有规格的", "", sampleSkusJSON)
|
||||
repository.SetCollectResult(db, "100000000003", "没规格的", "", `{"skus": []}`)
|
||||
|
||||
result, err := ListPddProducts(db, "", "")
|
||||
result, err := ListPddProducts(db, "", "", 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查列表失败: %v", err)
|
||||
}
|
||||
@@ -287,7 +315,7 @@ func TestListPddProducts_坏掉的采集结果不影响列表打开(t *testing.T
|
||||
t.Fatalf("造坏数据失败: %v", err)
|
||||
}
|
||||
|
||||
result, err := ListPddProducts(db, "", "")
|
||||
result, err := ListPddProducts(db, "", "", 1)
|
||||
if err != nil {
|
||||
t.Fatalf("列表页应该照样打得开: %v", err)
|
||||
}
|
||||
@@ -302,7 +330,7 @@ func TestListPddProducts_按采集状态筛选(t *testing.T) {
|
||||
createProduct(t, db, "100000000002")
|
||||
repository.SetCollectResult(db, "100000000002", "已采的", "", sampleSkusJSON)
|
||||
|
||||
collected, err := ListPddProducts(db, "", model.CollectCollected)
|
||||
collected, err := ListPddProducts(db, "", model.CollectCollected, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("筛选失败: %v", err)
|
||||
}
|
||||
@@ -324,12 +352,12 @@ func TestListPddProducts_按商品ID和链接搜索(t *testing.T) {
|
||||
createProduct(t, db, "737116531267")
|
||||
createProduct(t, db, "999888777666")
|
||||
|
||||
byID, _ := ListPddProducts(db, "7371165", "")
|
||||
byID, _ := ListPddProducts(db, "7371165", "", 1)
|
||||
if len(byID.Rows) != 1 || byID.Rows[0].GoodsID != "737116531267" {
|
||||
t.Errorf("按 ID 片段搜索失败,命中 %d 条", len(byID.Rows))
|
||||
}
|
||||
|
||||
byURL, _ := ListPddProducts(db, "yangkeduo", "")
|
||||
byURL, _ := ListPddProducts(db, "yangkeduo", "", 1)
|
||||
if len(byURL.Rows) != 2 {
|
||||
t.Errorf("按链接搜索应命中 2 条,实际 %d 条", len(byURL.Rows))
|
||||
}
|
||||
@@ -344,7 +372,7 @@ func TestListPddProducts_搜索词里的通配符不当通配符用(t *testing.T
|
||||
createProduct(t, db, "737116531267")
|
||||
|
||||
for _, kw := range []string{"7_7", "%"} {
|
||||
result, err := ListPddProducts(db, kw, "")
|
||||
result, err := ListPddProducts(db, kw, "", 1)
|
||||
if err != nil {
|
||||
t.Fatalf("搜 %q 出错: %v", kw, err)
|
||||
}
|
||||
@@ -359,7 +387,7 @@ func TestListPddProducts_删除的查不到(t *testing.T) {
|
||||
createProduct(t, db, "737116531267")
|
||||
DeletePddProducts(db, []string{"737116531267"})
|
||||
|
||||
result, _ := ListPddProducts(db, "", "")
|
||||
result, _ := ListPddProducts(db, "", "", 1)
|
||||
if len(result.Rows) != 0 {
|
||||
t.Errorf("软删除的不该出现在列表里,实际 %d 条", len(result.Rows))
|
||||
}
|
||||
@@ -374,7 +402,7 @@ func TestStatusLine_四个状态都列出来(t *testing.T) {
|
||||
createProduct(t, db, "100000000002")
|
||||
repository.SetCollectResult(db, "100000000002", "已采的", "", sampleSkusJSON)
|
||||
|
||||
result, _ := ListPddProducts(db, "", "")
|
||||
result, _ := ListPddProducts(db, "", "", 1)
|
||||
line := result.StatusLine()
|
||||
for _, want := range []string{"共 2 条", "已采集 1", "未采集 1", "采集中 0", "采集失败 0"} {
|
||||
if !strings.Contains(line, want) {
|
||||
@@ -444,7 +472,7 @@ func TestPdd页面_显示店铺与按颜色采样标记(t *testing.T) {
|
||||
repository.SetCollectResult(
|
||||
db, "737116531267", "测试商品", "测试旗舰店", resultJSON)
|
||||
|
||||
list, err := ListPddProducts(db, "", "")
|
||||
list, err := ListPddProducts(db, "", "", 1)
|
||||
if err != nil {
|
||||
t.Fatalf("读取列表失败: %v", err)
|
||||
}
|
||||
|
||||
@@ -131,17 +131,25 @@ func ListClientViews(db *sql.DB, keyword string, threshold time.Duration) ([]Cli
|
||||
|
||||
// ListClientViewsForUser 按网页登录身份限制可见范围:管理员全量,采购员只看自己。
|
||||
func ListClientViewsForUser(db *sql.DB, actor *model.User, keyword string, threshold time.Duration) ([]ClientView, error) {
|
||||
visibleUserID, err := visibleClientUserID(actor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return listClientViews(db, keyword, visibleUserID, threshold)
|
||||
}
|
||||
|
||||
func visibleClientUserID(actor *model.User) (string, error) {
|
||||
if actor == nil {
|
||||
return nil, ErrUnauthenticated
|
||||
return "", ErrUnauthenticated
|
||||
}
|
||||
visibleUserID := ""
|
||||
if !actor.IsAdmin() {
|
||||
if actor.Role != model.RolePurchaser {
|
||||
return nil, ErrAdminRequired
|
||||
return "", ErrAdminRequired
|
||||
}
|
||||
visibleUserID = actor.UserID
|
||||
}
|
||||
return listClientViews(db, keyword, visibleUserID, threshold)
|
||||
return visibleUserID, nil
|
||||
}
|
||||
|
||||
func listClientViews(db *sql.DB, keyword, visibleUserID string, threshold time.Duration) ([]ClientView, error) {
|
||||
@@ -163,6 +171,58 @@ func listClientViews(db *sql.DB, keyword, visibleUserID string, threshold time.D
|
||||
return views, nil
|
||||
}
|
||||
|
||||
// ClientListResult 是客户端页面的一页数据和同一权限范围内的完整统计。
|
||||
type ClientListResult struct {
|
||||
Rows []ClientView
|
||||
Page int
|
||||
Total int
|
||||
TotalPages int
|
||||
Online int
|
||||
Offline int
|
||||
}
|
||||
|
||||
// ListClientPageForUser 按网页登录身份、搜索词和统一页大小返回客户端列表。
|
||||
func ListClientPageForUser(db *sql.DB, actor *model.User, keyword string, threshold time.Duration, requestedPage int) (*ClientListResult, error) {
|
||||
visibleUserID, err := visibleClientUserID(actor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
page := requestedPage
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
rows, total, err := repository.ListClientsForUserPage(db, keyword, visibleUserID, PageSize, (page-1)*PageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
totalPages := TotalPages(total)
|
||||
clampedPage := ClampPage(page, totalPages)
|
||||
if clampedPage != page {
|
||||
page = clampedPage
|
||||
rows, _, err = repository.ListClientsForUserPage(db, keyword, visibleUserID, PageSize, (page-1)*PageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
online, err := repository.CountOnlineClientsForUser(
|
||||
db, keyword, visibleUserID, now.Add(-threshold).Format(model.TimeLayout))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
views := make([]ClientView, 0, len(rows))
|
||||
for _, client := range rows {
|
||||
views = append(views, ClientView{
|
||||
Client: client.Client, Status: client.StatusText(now, threshold),
|
||||
AssignedUserID: client.AssignedUserID, AssignedUsername: client.AssignedUsername,
|
||||
})
|
||||
}
|
||||
return &ClientListResult{
|
||||
Rows: views, Page: page, Total: total, TotalPages: totalPages,
|
||||
Online: online, Offline: total - online,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListAssignableClients 返回当前用户在采购任务页面可选择的客户端。
|
||||
// 当前创建页面尚未实现,本函数固定未来入口也必须沿用相同权限边界。
|
||||
func ListAssignableClients(db *sql.DB, actor *model.User, threshold time.Duration) ([]ClientView, error) {
|
||||
|
||||
+16
-11
@@ -233,9 +233,11 @@ type TaskView struct {
|
||||
|
||||
// TaskListResult 是列表页要的全部数据。
|
||||
type TaskListResult struct {
|
||||
Rows []TaskView
|
||||
Counts map[model.TaskStatus]int
|
||||
Total int // 当前筛选下的总数(= Counts 求和),不是全库总数
|
||||
Rows []TaskView
|
||||
Counts map[model.TaskStatus]int
|
||||
Total int // 当前筛选下的总数(= Counts 求和),不是全库总数
|
||||
Page int
|
||||
TotalPages int
|
||||
|
||||
// IsFiltered 为 false 时如果 Rows 也是空的,说明库里从来没建过任务
|
||||
// (不筛选就是查全表,全表空自然等价于"从没有过");为 true 时
|
||||
@@ -247,12 +249,18 @@ type TaskListResult struct {
|
||||
//
|
||||
// `[必须]` 底部统计要跟随当前筛选,所以 Counts 和 Rows 用的是**同一个**
|
||||
// filter,见 #19。
|
||||
func ListTasksView(db *sql.DB, filter repository.TaskFilter) (*TaskListResult, error) {
|
||||
rows, err := repository.ListTasks(db, filter)
|
||||
func ListTasksView(db *sql.DB, filter repository.TaskFilter, requestedPage int) (*TaskListResult, error) {
|
||||
counts, err := repository.CountTasksByStatus(db, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
counts, err := repository.CountTasksByStatus(db, filter)
|
||||
total := 0
|
||||
for _, n := range counts {
|
||||
total += n
|
||||
}
|
||||
totalPages := TotalPages(total)
|
||||
page := ClampPage(requestedPage, totalPages)
|
||||
rows, err := repository.ListTasks(db, filter, PageSize, (page-1)*PageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -260,13 +268,10 @@ func ListTasksView(db *sql.DB, filter repository.TaskFilter) (*TaskListResult, e
|
||||
result := &TaskListResult{
|
||||
Rows: make([]TaskView, 0, len(rows)),
|
||||
Counts: counts,
|
||||
Total: total, Page: page, TotalPages: totalPages,
|
||||
IsFiltered: filter.Type != "" || filter.Status != "" ||
|
||||
strings.TrimSpace(filter.Keyword) != "",
|
||||
}
|
||||
for _, n := range counts {
|
||||
result.Total += n
|
||||
}
|
||||
|
||||
for _, r := range rows {
|
||||
result.Rows = append(result.Rows, TaskView{
|
||||
TaskID: r.TaskID,
|
||||
@@ -292,7 +297,7 @@ func (r *TaskListResult) StatusLine() string {
|
||||
for _, s := range taskStatusOrder {
|
||||
parts = append(parts, fmt.Sprintf("%s %d", taskStatusText(s), r.Counts[s]))
|
||||
}
|
||||
return strings.Join(parts, " · ")
|
||||
return fmt.Sprintf("%s · 第 %d/%d 页", strings.Join(parts, " · "), r.Page, r.TotalPages)
|
||||
}
|
||||
|
||||
// DeleteTasks 批量删除任务,返回实际删掉的条数。
|
||||
|
||||
+42
-16
@@ -2,12 +2,38 @@ package service
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"cmautobuy/admin/model"
|
||||
"cmautobuy/admin/repository"
|
||||
)
|
||||
|
||||
func TestListTasksView_统一每页20条并收敛越界页(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
for i := 0; i < 25; i++ {
|
||||
insertTestTask(t, db, testTaskParams{
|
||||
taskID: fmt.Sprintf("PAGE-%02d", i), taskType: model.TaskCollect,
|
||||
status: model.TaskPending, pddGoodsID: fmt.Sprintf("%d", i+1),
|
||||
})
|
||||
}
|
||||
second, err := ListTasksView(db, repository.TaskFilter{}, 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(second.Rows) != 5 || second.Total != 25 || second.Page != 2 || second.TotalPages != 2 {
|
||||
t.Fatalf("第二页结果不对: rows=%d total=%d page=%d/%d",
|
||||
len(second.Rows), second.Total, second.Page, second.TotalPages)
|
||||
}
|
||||
overflow, err := ListTasksView(db, repository.TaskFilter{}, 999)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if overflow.Page != 2 || len(overflow.Rows) != 5 {
|
||||
t.Fatalf("越界页应收敛到末页: page=%d rows=%d", overflow.Page, len(overflow.Rows))
|
||||
}
|
||||
}
|
||||
|
||||
// insertTestTask 插一条任务,字段按需覆盖默认值,供本文件的用例使用。
|
||||
// 跟 client_test.go 里的 insertTask 不一样:那个专为"领取"场景写死了固定值,
|
||||
// 这里需要覆盖类型、状态、options 等更多维度。
|
||||
@@ -94,7 +120,7 @@ func TestListTasksView_同时显示采集和采购(t *testing.T) {
|
||||
insertTestTask(t, db, testTaskParams{taskID: "COL-1", taskType: model.TaskCollect, status: model.TaskPending, pddGoodsID: "111"})
|
||||
insertTestTask(t, db, testTaskParams{taskID: "PUR-1", taskType: model.TaskPurchase, status: model.TaskAssigned, orderNo: "SO-1"})
|
||||
|
||||
result, err := ListTasksView(db, repository.TaskFilter{})
|
||||
result, err := ListTasksView(db, repository.TaskFilter{}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -110,7 +136,7 @@ func TestListTasksView_类型筛选生效(t *testing.T) {
|
||||
insertTestTask(t, db, testTaskParams{taskID: "COL-1", taskType: model.TaskCollect, status: model.TaskPending, pddGoodsID: "111"})
|
||||
insertTestTask(t, db, testTaskParams{taskID: "PUR-1", taskType: model.TaskPurchase, status: model.TaskAssigned, orderNo: "SO-1"})
|
||||
|
||||
result, err := ListTasksView(db, repository.TaskFilter{Type: model.TaskCollect})
|
||||
result, err := ListTasksView(db, repository.TaskFilter{Type: model.TaskCollect}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -127,7 +153,7 @@ func TestListTasksView_状态筛选生效(t *testing.T) {
|
||||
insertTestTask(t, db, testTaskParams{taskID: "COL-1", taskType: model.TaskCollect, status: model.TaskPending, pddGoodsID: "111"})
|
||||
insertTestTask(t, db, testTaskParams{taskID: "COL-2", taskType: model.TaskCollect, status: model.TaskSucceeded, pddGoodsID: "222"})
|
||||
|
||||
result, err := ListTasksView(db, repository.TaskFilter{Status: model.TaskSucceeded})
|
||||
result, err := ListTasksView(db, repository.TaskFilter{Status: model.TaskSucceeded}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -143,17 +169,17 @@ func TestListTasksView_关键词同时匹配任务编号订单号PDD商品ID(t *
|
||||
insertTestTask(t, db, testTaskParams{taskID: "PUR-2", taskType: model.TaskPurchase, status: model.TaskAssigned, orderNo: "SO-OTHER"})
|
||||
|
||||
// 按任务编号命中
|
||||
r, err := ListTasksView(db, repository.TaskFilter{Keyword: "ABC"})
|
||||
r, err := ListTasksView(db, repository.TaskFilter{Keyword: "ABC"}, 1)
|
||||
if err != nil || len(r.Rows) != 1 || r.Rows[0].TaskID != "COL-ABC" {
|
||||
t.Fatalf("按任务编号搜索失败: err=%v rows=%+v", err, r)
|
||||
}
|
||||
// 按订单号命中
|
||||
r, err = ListTasksView(db, repository.TaskFilter{Keyword: "XYZ"})
|
||||
r, err = ListTasksView(db, repository.TaskFilter{Keyword: "XYZ"}, 1)
|
||||
if err != nil || len(r.Rows) != 1 || r.Rows[0].TaskID != "PUR-1" {
|
||||
t.Fatalf("按订单号搜索失败: err=%v rows=%+v", err, r)
|
||||
}
|
||||
// 按 PDD 商品 ID 命中
|
||||
r, err = ListTasksView(db, repository.TaskFilter{Keyword: "737116531267"})
|
||||
r, err = ListTasksView(db, repository.TaskFilter{Keyword: "737116531267"}, 1)
|
||||
if err != nil || len(r.Rows) != 1 || r.Rows[0].TaskID != "COL-ABC" {
|
||||
t.Fatalf("按 PDD 商品 ID 搜索失败: err=%v rows=%+v", err, r)
|
||||
}
|
||||
@@ -165,7 +191,7 @@ func TestListTasksView_目标列_采集任务显示PDD商品ID(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
insertTestTask(t, db, testTaskParams{taskID: "COL-1", taskType: model.TaskCollect, status: model.TaskPending, pddGoodsID: "737116531267"})
|
||||
|
||||
r, err := ListTasksView(db, repository.TaskFilter{})
|
||||
r, err := ListTasksView(db, repository.TaskFilter{}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -185,7 +211,7 @@ func TestListTasksView_目标列_采集任务能join到标题时追加显示(t *
|
||||
}
|
||||
insertTestTask(t, db, testTaskParams{taskID: "COL-1", taskType: model.TaskCollect, status: model.TaskSucceeded, pddGoodsID: "737116531267"})
|
||||
|
||||
r, err := ListTasksView(db, repository.TaskFilter{})
|
||||
r, err := ListTasksView(db, repository.TaskFilter{}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -206,7 +232,7 @@ func TestListTasksView_目标列_商品已软删除时退回显示商品ID(t *te
|
||||
}
|
||||
insertTestTask(t, db, testTaskParams{taskID: "COL-1", taskType: model.TaskCollect, status: model.TaskPending, pddGoodsID: "737116531267"})
|
||||
|
||||
r, err := ListTasksView(db, repository.TaskFilter{})
|
||||
r, err := ListTasksView(db, repository.TaskFilter{}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -224,7 +250,7 @@ func TestListTasksView_目标列_采购任务显示订单号规格数量价格
|
||||
quantity: 2, maxPriceCent: 4200,
|
||||
})
|
||||
|
||||
r, err := ListTasksView(db, repository.TaskFilter{})
|
||||
r, err := ListTasksView(db, repository.TaskFilter{}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -240,7 +266,7 @@ func TestListTasksView_无主任务客户端列显示占位符(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
insertTestTask(t, db, testTaskParams{taskID: "COL-1", taskType: model.TaskCollect, status: model.TaskPending, pddGoodsID: "111"})
|
||||
|
||||
r, err := ListTasksView(db, repository.TaskFilter{})
|
||||
r, err := ListTasksView(db, repository.TaskFilter{}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -258,7 +284,7 @@ func TestListTasksView_统计跟随当前筛选(t *testing.T) {
|
||||
insertTestTask(t, db, testTaskParams{taskID: "PUR-1", taskType: model.TaskPurchase, status: model.TaskAssigned, orderNo: "SO-1"})
|
||||
insertTestTask(t, db, testTaskParams{taskID: "PUR-2", taskType: model.TaskPurchase, status: model.TaskAssigned, orderNo: "SO-2"})
|
||||
|
||||
all, err := ListTasksView(db, repository.TaskFilter{})
|
||||
all, err := ListTasksView(db, repository.TaskFilter{}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -266,7 +292,7 @@ func TestListTasksView_统计跟随当前筛选(t *testing.T) {
|
||||
t.Fatalf("不筛选时总数应该是 4,实际 %d", all.Total)
|
||||
}
|
||||
|
||||
collectOnly, err := ListTasksView(db, repository.TaskFilter{Type: model.TaskCollect})
|
||||
collectOnly, err := ListTasksView(db, repository.TaskFilter{Type: model.TaskCollect}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -285,7 +311,7 @@ func TestListTasksView_统计跟随当前筛选(t *testing.T) {
|
||||
|
||||
func TestListTasksView_从未建过任务时不算筛选无结果(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
r, err := ListTasksView(db, repository.TaskFilter{})
|
||||
r, err := ListTasksView(db, repository.TaskFilter{}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -301,7 +327,7 @@ func TestListTasksView_筛选无结果时IsFiltered为true(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
insertTestTask(t, db, testTaskParams{taskID: "COL-1", taskType: model.TaskCollect, status: model.TaskPending, pddGoodsID: "111"})
|
||||
|
||||
r, err := ListTasksView(db, repository.TaskFilter{Type: model.TaskPurchase})
|
||||
r, err := ListTasksView(db, repository.TaskFilter{Type: model.TaskPurchase}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
@@ -416,7 +442,7 @@ func TestDeleteTasks_批量删除(t *testing.T) {
|
||||
t.Fatalf("应该删除 1 条,实际 %d", n)
|
||||
}
|
||||
|
||||
r, err := ListTasksView(db, repository.TaskFilter{})
|
||||
r, err := ListTasksView(db, repository.TaskFilter{}, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user