fix: 增强顺运宝同步完整性保护 (#58)

This commit is contained in:
chengma
2026-08-09 17:17:42 +08:00
parent 17b8f53113
commit 4b5cd13807
8 changed files with 448 additions and 77 deletions
+11 -6
View File
@@ -504,30 +504,35 @@ type StockRow struct {
}
// ListPage 按日期范围翻一页货运单列表:POST /am/stock/list。
func (c *Client) ListPage(ctx context.Context, dateFrom, dateTo string, start, pageIndex, pageSize int) ([]StockRow, error) {
// 返回响应内的 total,供上层核对分页期间总数有没有漂移。
func (c *Client) ListPage(ctx context.Context, dateFrom, dateTo string, start, pageIndex, pageSize int) ([]StockRow, int, error) {
data, err := c.do(ctx, http.MethodPost, "/am/stock/list", nil,
listPayload(dateFrom, dateTo, start, pageIndex, pageSize))
if err != nil {
return nil, err
return nil, 0, err
}
var wrap struct {
List []map[string]any `json:"list"`
List []map[string]any `json:"list"`
Total *int `json:"total"`
}
if err := json.Unmarshal(data, &wrap); err != nil {
return nil, fmt.Errorf("货运单列表响应格式错误: %w", err)
return nil, 0, fmt.Errorf("货运单列表响应格式错误: %w", err)
}
if wrap.Total == nil || *wrap.Total < 0 {
return nil, 0, fmt.Errorf("货运单列表响应缺少合法的 total")
}
rows := make([]StockRow, 0, len(wrap.List))
for _, raw := range wrap.List {
id, ok := toInt64(raw["id"])
if !ok {
return nil, fmt.Errorf("货运单列表里有一行缺少合法的 id: %v", raw)
return nil, 0, fmt.Errorf("货运单列表里有一行缺少合法的 id: %v", raw)
}
code, _ := raw["code"].(string)
rows = append(rows, StockRow{ID: id, Code: code, Raw: raw})
}
return rows, nil
return rows, *wrap.Total, nil
}
// ---------- 货运单明细 ----------
+27 -1
View File
@@ -304,6 +304,7 @@ func TestClient_ListTotal和ListPage(t *testing.T) {
w.Write(envelopeBody(t, true, "ok", 1, nil))
case "/am/stock/list":
w.Write(envelopeBody(t, true, "ok", map[string]any{
"total": 1,
"list": []map[string]any{
{"id": 75104587, "code": "260728TB95MJTQ", "amtOrder": 61200},
},
@@ -321,15 +322,40 @@ func TestClient_ListTotal和ListPage(t *testing.T) {
t.Fatalf("总数应该是 1,实际 %d", total)
}
rows, err := c.ListPage(context.Background(), "2026-07-25", "2026-07-28", 0, 1, 20)
rows, pageTotal, err := c.ListPage(context.Background(), "2026-07-25", "2026-07-28", 0, 1, 20)
if err != nil {
t.Fatalf("list 失败: %v", err)
}
if pageTotal != 1 {
t.Fatalf("list 响应内 total 应该是 1,实际 %d", pageTotal)
}
if len(rows) != 1 || rows[0].ID != 75104587 || rows[0].Code != "260728TB95MJTQ" {
t.Fatalf("列表结果不对: %+v", rows)
}
}
func TestClient_ListPage要求合法Total(t *testing.T) {
for _, test := range []struct {
name string
data map[string]any
}{
{"缺少total", map[string]any{"list": []any{}}},
{"total类型错误", map[string]any{"list": []any{}, "total": "1"}},
{"total为负数", map[string]any{"list": []any{}, "total": -1}},
} {
t.Run(test.name, func(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write(envelopeBody(t, true, "ok", test.data, nil))
}))
defer srv.Close()
client, _ := New(srv.URL)
if _, _, err := client.ListPage(context.Background(), "2026-08-09", "2026-08-09", 0, 1, 20); err == nil {
t.Fatal("非法 total 应返回错误")
}
})
}
}
func TestClient_DetailListByStock_一单多商品(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Query().Get("hist") != "0" {