feat(t237): import freight orders synchronously

This commit is contained in:
QiuSW
2026-07-29 12:11:56 +08:00
parent 4bce1e162c
commit 8d5b88f4a2
18 changed files with 653 additions and 97 deletions
@@ -852,6 +852,8 @@ func writeUsecaseError(ctx *gin.Context, err error) {
status = http.StatusBadGateway
case "OCR_SERVICE_INVALID", "ERP_UNAVAILABLE":
status = http.StatusServiceUnavailable
case "FREIGHT_SYNC_TIMEOUT":
status = http.StatusGatewayTimeout
}
message := typed.Message
if preflightMessage, ok := freightPreflightPublicMessage(typed.Code); ok {
@@ -883,6 +885,10 @@ func freightPreflightPublicMessage(code string) (string, bool) {
return "OCR service is invalid", true
case "ERP_UNAVAILABLE":
return "ERP is temporarily unavailable", true
case "FREIGHT_SYNC_TIMEOUT":
return "freight order sync exceeded 55 seconds", true
case "FREIGHT_SYNC_BUSY":
return "another freight order sync is already running", true
default:
return "", false
}
@@ -405,7 +405,9 @@ func TestAdminFreightAPIImportsAllItemsWithoutPII(t *testing.T) {
),
"freight-sync-1",
)
if create.Code != http.StatusAccepted {
if create.Code != http.StatusCreated ||
create.Header().Get("Location") != "/api/v1/freight-orders" ||
!strings.Contains(create.Body.String(), `"status":"SUCCEEDED"`) {
t.Fatalf("create status/body = %d / %s", create.Code, create.Body)
}
var createBody struct {
@@ -486,8 +488,9 @@ func TestAdminFreightAPIImportsAllItemsWithoutPII(t *testing.T) {
),
"freight-sync-1",
)
if replay.Code != http.StatusAccepted ||
if replay.Code != http.StatusOK ||
!strings.Contains(replay.Body.String(), `"replayed":true`) ||
!strings.Contains(replay.Body.String(), `"status":"SUCCEEDED"`) ||
!strings.Contains(replay.Body.String(), createBody.Sync.ID) {
t.Fatalf("replay status/body = %d / %s", replay.Code, replay.Body)
}
@@ -515,6 +518,9 @@ func TestAdminFreightDateSyncAdvancesInspectableWatermark(t *testing.T) {
"freight-date-sync-1",
)
requireAdminStatus(t, create, http.StatusAccepted)
if !strings.Contains(create.Body.String(), `"status":"PENDING"`) {
t.Fatalf("date sync create response = %s", create.Body)
}
var created struct {
Sync struct {
ID string `json:"id"`
@@ -589,31 +595,9 @@ func TestAdminProcurementAPIProducesImmutablePendingTask(t *testing.T) {
),
"procurement-freight-sync",
)
var syncBody struct {
Sync struct {
ID string `json:"id"`
} `json:"sync"`
}
decodeResponse(t, createSync, &syncBody)
succeeded := false
for attempt := 0; attempt < 50; attempt++ {
status := performAdminRequest(
t,
fixture.router,
http.MethodGet,
"/api/v1/freight-syncs/"+syncBody.Sync.ID,
"",
nil,
"",
)
if strings.Contains(status.Body.String(), `"status":"SUCCEEDED"`) {
succeeded = true
break
}
time.Sleep(10 * time.Millisecond)
}
if !succeeded {
t.Fatal("freight sync did not succeed")
requireAdminStatus(t, createSync, http.StatusCreated)
if !strings.Contains(createSync.Body.String(), `"status":"SUCCEEDED"`) {
t.Fatalf("freight sync response = %s", createSync.Body)
}
orders := performAdminRequest(
t,
@@ -106,7 +106,15 @@ func (h *adminHandlers) createFreightSync(ctx *gin.Context) {
return
}
ctx.Header("Cache-Control", "no-store")
ctx.JSON(http.StatusAccepted, gin.H{
status := http.StatusAccepted
if request.Mode == domain.FreightSyncOrderNumber {
status = http.StatusCreated
if result.Replayed {
status = http.StatusOK
}
ctx.Header("Location", "/api/v1/freight-orders")
}
ctx.JSON(status, gin.H{
"sync": freightSyncResponse(result.Run),
"replayed": result.Replayed,
})
@@ -21,6 +21,7 @@ func TestWriteUsecaseErrorUsesPreflightStatusAndCode(t *testing.T) {
{"ERP_RESPONSE_INVALID", http.StatusBadGateway},
{"OCR_SERVICE_INVALID", http.StatusServiceUnavailable},
{"ERP_UNAVAILABLE", http.StatusServiceUnavailable},
{"FREIGHT_SYNC_TIMEOUT", http.StatusGatewayTimeout},
}
for _, testCase := range testCases {
t.Run(testCase.code, func(t *testing.T) {