feat: 支持顺运宝多订单号搜索 (#217)
This commit is contained in:
+34
-7
@@ -530,18 +530,21 @@ func nullableText(s string) any {
|
||||
|
||||
// SybOrderFilter 是货运单列表页支持的筛选条件。
|
||||
type SybOrderFilter struct {
|
||||
Keyword string // 匹配订单号或商品标题
|
||||
Shop string // 店铺名模糊匹配;空字符串表示全部
|
||||
Stage string // 处理阶段;空字符串表示全部
|
||||
OrderNos []string // 订单号精确匹配;多个值之间是 OR,空切片表示全部
|
||||
Shop string // 店铺名模糊匹配;空字符串表示全部
|
||||
Stage string // 处理阶段;空字符串表示全部
|
||||
}
|
||||
|
||||
func sybOrderFilterClause(filter SybOrderFilter) (string, []any) {
|
||||
var clauses []string
|
||||
var args []any
|
||||
if kw := filter.Keyword; kw != "" {
|
||||
like := "%" + escapeLike(kw) + "%"
|
||||
clauses = append(clauses, `(so.order_no LIKE ? ESCAPE '!' OR so.title LIKE ? ESCAPE '!')`)
|
||||
args = append(args, like, like)
|
||||
if len(filter.OrderNos) > 0 {
|
||||
placeholders := make([]string, len(filter.OrderNos))
|
||||
for i, orderNo := range filter.OrderNos {
|
||||
placeholders[i] = "?"
|
||||
args = append(args, orderNo)
|
||||
}
|
||||
clauses = append(clauses, `so.order_no IN (`+strings.Join(placeholders, ",")+`)`)
|
||||
}
|
||||
if shop := strings.TrimSpace(filter.Shop); shop != "" {
|
||||
clauses = append(clauses, `so.shop_name LIKE ? ESCAPE '!'`)
|
||||
@@ -752,6 +755,30 @@ func CountSybOrders(q Execer, filter SybOrderFilter) (int, error) {
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// ListMatchedSybOrderNos 返回当前可由 SQL 表达的组合筛选实际命中的订单号。
|
||||
// 页面用它区分“输入了多少订单”和“命中了多少商品明细”;查询继续复用
|
||||
// idx_syb_orders_order,所有订单号都通过占位符传入。
|
||||
func ListMatchedSybOrderNos(q Execer, filter SybOrderFilter) ([]string, error) {
|
||||
if len(filter.OrderNos) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
where, args := sybOrderFilterClause(filter)
|
||||
rows, err := q.Query(`SELECT DISTINCT so.order_no`+sybOrderContextFrom+where+` ORDER BY so.order_no`, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询顺运宝命中订单号失败: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
matched := make([]string, 0, len(filter.OrderNos))
|
||||
for rows.Next() {
|
||||
var orderNo string
|
||||
if err := rows.Scan(&orderNo); err != nil {
|
||||
return nil, fmt.Errorf("读取顺运宝命中订单号失败: %w", err)
|
||||
}
|
||||
matched = append(matched, orderNo)
|
||||
}
|
||||
return matched, rows.Err()
|
||||
}
|
||||
|
||||
// CountSybOrdersTotal 统计全部货运单明细数量(不带筛选),
|
||||
// 供列表页判断"是否已经同步过任何数据"。
|
||||
func CountSybOrdersTotal(q Execer) (int, error) {
|
||||
|
||||
@@ -408,7 +408,7 @@ func TestInterruptRunningSybSyncRuns_只中断未完成记录(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestListSybOrders_订单标题店铺组合筛选(t *testing.T) {
|
||||
func TestListSybOrders_多订单精确与店铺组合筛选(t *testing.T) {
|
||||
db := newSybTestDB(t)
|
||||
mustUpsert := func(sybID, orderNo, shop, title string) {
|
||||
if _, err := UpsertSybOrder(db, model.SybOrder{
|
||||
@@ -420,28 +420,33 @@ func TestListSybOrders_订单标题店铺组合筛选(t *testing.T) {
|
||||
mustUpsert("SYB-A", "260728AAA", "台北服饰旗舰店", "纯棉上衣")
|
||||
mustUpsert("SYB-B", "260728BBB", "台南生活馆", "牛仔裤")
|
||||
|
||||
rows, err := ListSybOrders(db, SybOrderFilter{Keyword: "AAA"}, 20, 0)
|
||||
rows, err := ListSybOrders(db, SybOrderFilter{OrderNos: []string{"260728AAA", "260728BBB"}}, 20, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
if len(rows) != 1 || rows[0].SybID != "SYB-A" {
|
||||
t.Fatalf("按订单号筛选应该只查到 SYB-A,实际 %+v", rows)
|
||||
if len(rows) != 2 {
|
||||
t.Fatalf("两个精确订单号应该查到两条,实际 %+v", rows)
|
||||
}
|
||||
|
||||
rows2, err := ListSybOrders(db, SybOrderFilter{Keyword: "牛仔"}, 20, 0)
|
||||
rows2, err := ListSybOrders(db, SybOrderFilter{OrderNos: []string{"AAA", "牛仔"}}, 20, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("查询失败: %v", err)
|
||||
}
|
||||
if len(rows2) != 1 || rows2[0].SybID != "SYB-B" {
|
||||
t.Fatalf("按标题筛选应该只查到 SYB-B,实际 %+v", rows2)
|
||||
if len(rows2) != 0 {
|
||||
t.Fatalf("订单号片段和商品标题都不应再命中,实际 %+v", rows2)
|
||||
}
|
||||
|
||||
rows3, err := ListSybOrders(db, SybOrderFilter{Shop: " 服饰 "}, 20, 0)
|
||||
if err != nil || len(rows3) != 1 || rows3[0].SybID != "SYB-A" || rows3[0].ShopName != "台北服饰旗舰店" {
|
||||
t.Fatalf("按店铺模糊筛选错误:rows=%+v err=%v", rows3, err)
|
||||
}
|
||||
count, err := CountSybOrders(db, SybOrderFilter{Keyword: "牛仔", Shop: "台南"})
|
||||
filter := SybOrderFilter{OrderNos: []string{"260728AAA", "260728BBB", "NOT-FOUND"}, Shop: "台南"}
|
||||
count, err := CountSybOrders(db, filter)
|
||||
if err != nil || count != 1 {
|
||||
t.Fatalf("标题与店铺组合 COUNT 错误:count=%d err=%v", count, err)
|
||||
t.Fatalf("订单号与店铺组合 COUNT 错误:count=%d err=%v", count, err)
|
||||
}
|
||||
matched, err := ListMatchedSybOrderNos(db, filter)
|
||||
if err != nil || len(matched) != 1 || matched[0] != "260728BBB" {
|
||||
t.Fatalf("当前筛选命中订单号错误:matched=%v err=%v", matched, err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user