feat: 统一顺运宝日期同步并记录历史 (#59)
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
@@ -119,6 +120,37 @@ func TestNewSybSyncOptions_指定日期校验(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultSybSyncRange_最近三天与缺口分段(t *testing.T) {
|
||||
now := time.Date(2026, 8, 9, 12, 0, 0, 0, time.UTC)
|
||||
t.Run("没有游标默认最近三天", func(t *testing.T) {
|
||||
db := newSyncTestDB(t)
|
||||
got, err := DefaultSybSyncRange(db, now)
|
||||
if err != nil || got.From != "2026-08-07" || got.To != "2026-08-09" || got.Warning != "" {
|
||||
t.Fatalf("默认范围错误: got=%+v err=%v", got, err)
|
||||
}
|
||||
})
|
||||
t.Run("短缺口自动扩展到今天", func(t *testing.T) {
|
||||
db := newSyncTestDB(t)
|
||||
if err := repository.SetSybLastSyncedAt(db, "2026-08-05T00:00:00Z"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := DefaultSybSyncRange(db, now)
|
||||
if err != nil || got.From != "2026-08-05" || got.To != "2026-08-09" || got.Warning == "" {
|
||||
t.Fatalf("短缺口范围错误: got=%+v err=%v", got, err)
|
||||
}
|
||||
})
|
||||
t.Run("长缺口优先选择最早三十一天", func(t *testing.T) {
|
||||
db := newSyncTestDB(t)
|
||||
if err := repository.SetSybLastSyncedAt(db, "2026-07-01T00:00:00Z"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := DefaultSybSyncRange(db, now)
|
||||
if err != nil || got.From != "2026-07-01" || got.To != "2026-07-31" || !strings.Contains(got.Warning, "继续同步下一段") {
|
||||
t.Fatalf("长缺口分段错误: got=%+v err=%v", got, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ── 金额换算 ──────────────────────────────────────────
|
||||
|
||||
func TestRoundYuanToCent_先四舍五入再转整数(t *testing.T) {
|
||||
@@ -489,8 +521,8 @@ func TestRunSybSyncWithOptions_历史补拉不推进游标(t *testing.T) {
|
||||
if report.Err != nil {
|
||||
t.Fatalf("历史补拉失败: %v", report.Err)
|
||||
}
|
||||
if !report.Specified || !strings.HasPrefix(report.Summary(), "指定日期同步完成") {
|
||||
t.Fatalf("报告没有标明指定日期同步:%+v / %s", report, report.Summary())
|
||||
if !report.Specified || !strings.HasPrefix(report.Summary(), "同步完成") {
|
||||
t.Fatalf("明确日期范围的报告不正确:%+v / %s", report, report.Summary())
|
||||
}
|
||||
at, _, err := repository.GetSybLastSyncedAt(db)
|
||||
if err != nil {
|
||||
@@ -522,8 +554,64 @@ func TestRunSybSyncWithOptions_完整覆盖自动范围才推进游标(t *testin
|
||||
if err != nil {
|
||||
t.Fatalf("读取同步游标失败: %v", err)
|
||||
}
|
||||
if at == original || at == "" {
|
||||
t.Fatalf("完整覆盖自动范围后应该推进游标,实际仍为 %q", at)
|
||||
if at != "2026-07-27T16:00:00Z" || !report.CursorAdvanced {
|
||||
t.Fatalf("连续覆盖后应该把游标推进到所选结束日,实际 %q,报告 %+v", at, report)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunSybSyncWithOptions_跳过缺口不推进游标(t *testing.T) {
|
||||
srv := fakeSybServer(t, nil, 0)
|
||||
defer srv.Close()
|
||||
db := newSyncTestDB(t)
|
||||
client, _ := syb.New(srv.URL)
|
||||
const original = "2026-07-01T00:00:00Z"
|
||||
if err := repository.SetSybLastSyncedAt(db, original); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
report := RunSybSyncWithOptions(context.Background(), db, client,
|
||||
config.SybConfig{BaseURL: srv.URL, PageSize: 20, MaxMatches: 500},
|
||||
time.Date(2026, 8, 9, 12, 0, 0, 0, time.UTC),
|
||||
SybSyncOptions{From: "2026-07-05", To: "2026-07-10"})
|
||||
if report.Err != nil {
|
||||
t.Fatalf("同步失败: %v", report.Err)
|
||||
}
|
||||
at, _, err := repository.GetSybLastSyncedAt(db)
|
||||
if err != nil || at != original || report.CursorAdvanced {
|
||||
t.Fatalf("跳过缺口不应推进游标: at=%q report=%+v err=%v", at, report, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSybSyncHistory_服务层创建失败记录并展示(t *testing.T) {
|
||||
db := newSyncTestDB(t)
|
||||
actor := model.User{
|
||||
UserID: "USR-HISTORY", Username: "buyer", PasswordHash: "test-hash",
|
||||
Role: model.RolePurchaser, Status: model.UserActive,
|
||||
PasswordChangedAt: "2026-08-09T00:00:00Z", CreatedAt: "2026-08-09T00:00:00Z",
|
||||
UpdatedAt: "2026-08-09T00:00:00Z",
|
||||
}
|
||||
if err := repository.CreateInitialAdmin(db, actor); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
runID, err := CreateSybSyncRun(db, &actor,
|
||||
SybSyncOptions{From: "2026-08-07", To: "2026-08-09"},
|
||||
time.Date(2026, 8, 9, 1, 0, 0, 0, time.UTC))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := FinishSybSyncRun(db, runID, SyncReport{
|
||||
From: "2026-08-07", To: "2026-08-09", Err: fmt.Errorf("测试失败"),
|
||||
FinishedAt: time.Date(2026, 8, 9, 1, 1, 0, 0, time.UTC),
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
history, err := ListSybSyncHistory(db, 1)
|
||||
if err != nil || history.Total != 1 || len(history.Rows) != 1 {
|
||||
t.Fatalf("读取记录失败: history=%+v err=%v", history, err)
|
||||
}
|
||||
row := history.Rows[0]
|
||||
if row.Username != "buyer" || row.StatusText != "失败" || row.ErrorMessage != "测试失败" || row.CursorText != "未推进" {
|
||||
t.Fatalf("同步记录视图不正确: %+v", row)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user