feat(t224): add incremental freight sync

This commit is contained in:
QiuSW
2026-07-29 00:26:05 +08:00
parent 433db45100
commit c69879650e
35 changed files with 2085 additions and 156 deletions
@@ -959,6 +959,11 @@ func TestFreightPagesEscapeSourceDataAndCreateAsyncSync(t *testing.T) {
nil,
"",
)
if !strings.Contains(form.Body.String(), "同步至现在") ||
!strings.Contains(form.Body.String(), `name="created_from"`) ||
!strings.Contains(form.Body.String(), "尚无日期同步水位") {
t.Fatalf("freight import form = %s", form.Body)
}
cookie := csrfCookie(t, form)
idempotencyKey := hiddenValue(
t,
@@ -994,6 +999,102 @@ func TestFreightPagesEscapeSourceDataAndCreateAsyncSync(t *testing.T) {
}
}
func TestFreightDateFormSubmitsManualRange(t *testing.T) {
now := time.Date(2026, 7, 28, 3, 4, 5, 0, time.UTC)
service := &fakeFreightService{
fakeService: &fakeService{},
watermark: &FreightWatermark{
LastSuccessfulTo: now,
LastSuccessfulRunID: testTaskID,
UpdatedAt: now,
},
createResult: FreightSync{
ID: testTaskID,
Mode: "CREATED_RANGE",
Status: "PENDING",
CreatedAt: now,
},
}
router := newTestRouter(t, service)
form := performRequest(t, router, http.MethodGet, "/freight/import", nil, "")
if !strings.Contains(form.Body.String(), "增量同步水位") ||
!strings.Contains(form.Body.String(), testTaskID) {
t.Fatalf("watermark form = %s", form.Body)
}
cookie := csrfCookie(t, form)
key := hiddenValue(t, form.Body.String(), "idempotency_key")
values := url.Values{
"csrf_token": {cookie.Value},
"idempotency_key": {key},
"mode": {"CREATED_RANGE"},
"created_from": {"2026-07-22"},
"created_to": {"2026-07-28"},
}
request := httptest.NewRequest(
http.MethodPost,
"/freight/import",
strings.NewReader(values.Encode()),
)
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
request.AddCookie(cookie)
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
if response.Code != http.StatusSeeOther ||
service.createInput.Mode != "CREATED_RANGE" ||
service.createInput.CreatedFrom != "2026-07-22" ||
service.createInput.CreatedTo != "2026-07-28" {
t.Fatalf(
"date form response/input = %d / %+v",
response.Code,
service.createInput,
)
}
}
func TestFreightSyncToNowIgnoresPrefilledManualDates(t *testing.T) {
service := &fakeFreightService{
fakeService: &fakeService{},
createResult: FreightSync{
ID: testTaskID,
Mode: "CREATED_RANGE",
Status: "PENDING",
},
}
router := newTestRouter(t, service)
form := performRequest(t, router, http.MethodGet, "/freight/import", nil, "")
cookie := csrfCookie(t, form)
key := hiddenValue(t, form.Body.String(), "idempotency_key")
values := url.Values{
"csrf_token": {cookie.Value},
"idempotency_key": {key},
"mode": {"CREATED_RANGE"},
"created_from": {"2026-07-22"},
"created_to": {"2026-07-28"},
"sync_to_now": {"true"},
}
request := httptest.NewRequest(
http.MethodPost,
"/freight/import",
strings.NewReader(values.Encode()),
)
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
request.AddCookie(cookie)
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
if response.Code != http.StatusSeeOther ||
!service.createInput.SyncToNow ||
service.createInput.CreatedFrom != "" ||
service.createInput.CreatedTo != "" {
t.Fatalf(
"sync-to-now response/input = %d / %+v",
response.Code,
service.createInput,
)
}
}
func TestFreightDetailCreatesProcurementTaskWithCSRF(t *testing.T) {
const itemID = "00000000-0000-4000-8000-000000000002"
service := &fakeProcurementService{
@@ -1101,6 +1202,7 @@ type fakeFreightService struct {
sync FreightSync
createInput CreateFreightSyncInput
createResult FreightSync
watermark *FreightWatermark
err error
}
@@ -1159,6 +1261,12 @@ func (service *fakeFreightService) GetFreightSync(
return service.sync, service.err
}
func (service *fakeFreightService) GetFreightWatermark(
context.Context,
) (*FreightWatermark, error) {
return service.watermark, service.err
}
func (service *fakeFreightService) CreateFreightSync(
_ context.Context,
input CreateFreightSyncInput,