feat(t239): persist freight item metadata
This commit is contained in:
@@ -472,8 +472,10 @@ func TestAdminFreightAPIImportsAllItemsWithoutPII(t *testing.T) {
|
||||
"",
|
||||
)
|
||||
if detail.Code != http.StatusOK ||
|
||||
!strings.Contains(detail.Body.String(), `"sku":"BLACK-L"`) ||
|
||||
!strings.Contains(detail.Body.String(), `"sku":"WHITE-M"`) ||
|
||||
!strings.Contains(detail.Body.String(), `"sku":"黑色,L"`) ||
|
||||
!strings.Contains(detail.Body.String(), `"sku":"白色,M"`) ||
|
||||
!strings.Contains(detail.Body.String(), `"original_unit_price_minor":12950`) ||
|
||||
!strings.Contains(detail.Body.String(), `"original_currency":"TWD"`) ||
|
||||
detail.Header().Get("Cache-Control") != "no-store" {
|
||||
t.Fatalf("freight detail status/body = %d / %s", detail.Code, detail.Body)
|
||||
}
|
||||
@@ -718,7 +720,7 @@ func TestAdminProcurementAPIProducesImmutablePendingTask(t *testing.T) {
|
||||
)
|
||||
for _, required := range []string{
|
||||
`"title":"商品一"`,
|
||||
`"sku":"BLACK-L"`,
|
||||
`"sku":"黑色,L"`,
|
||||
`"quantity":1`,
|
||||
`"image_asset_id":"` + assetBody.ID + `"`,
|
||||
`"description":"ERP 规格:黑色,L"`,
|
||||
@@ -873,6 +875,9 @@ func TestAdminOrderAuthorizationIsIdempotentAndRevisioned(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("migration.New() error = %v", err)
|
||||
}
|
||||
if err := runner.Down(context.Background()); err != nil {
|
||||
t.Fatalf("metadata migration down: %v", err)
|
||||
}
|
||||
if err := runner.Down(context.Background()); err != nil {
|
||||
t.Fatalf("date sync migration down: %v", err)
|
||||
}
|
||||
@@ -1263,6 +1268,8 @@ func (staticFreightSource) QueryOrder(
|
||||
created := "2026-07-28 08:00"
|
||||
quantityOne := 1
|
||||
quantityTwo := 2
|
||||
priceOne := int64(12950)
|
||||
priceTwo := int64(8800)
|
||||
return domain.FreightSourceBatch{
|
||||
SchemaVersion: 1,
|
||||
Query: domain.FreightSourceQuery{
|
||||
@@ -1275,18 +1282,22 @@ func (staticFreightSource) QueryOrder(
|
||||
SourceCreatedAt: &created,
|
||||
Items: []domain.FreightSourceItem{
|
||||
{
|
||||
ExternalItemID: "88",
|
||||
Title: "商品一",
|
||||
ProductSpec: "黑色,L",
|
||||
SKU: "BLACK-L",
|
||||
Quantity: &quantityOne,
|
||||
ExternalItemID: "88",
|
||||
Title: "商品一",
|
||||
ProductSpec: "黑色,L",
|
||||
SKU: "黑色,L",
|
||||
Quantity: &quantityOne,
|
||||
OriginalUnitPriceMinor: &priceOne,
|
||||
OriginalCurrency: domain.FreightCurrencyTWD,
|
||||
},
|
||||
{
|
||||
ExternalItemID: "89",
|
||||
Title: "商品二",
|
||||
ProductSpec: "白色,M",
|
||||
SKU: "WHITE-M",
|
||||
Quantity: &quantityTwo,
|
||||
ExternalItemID: "89",
|
||||
Title: "商品二",
|
||||
ProductSpec: "白色,M",
|
||||
SKU: "白色,M",
|
||||
Quantity: &quantityTwo,
|
||||
OriginalUnitPriceMinor: &priceTwo,
|
||||
OriginalCurrency: domain.FreightCurrencyTWD,
|
||||
},
|
||||
},
|
||||
}},
|
||||
|
||||
@@ -713,6 +713,9 @@ func TestDeviceExecutionResultsAreIdempotentAndAuditable(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("migration.New() after review error = %v", err)
|
||||
}
|
||||
if err := runner.Down(context.Background()); err != nil {
|
||||
t.Fatalf("metadata migration down: %v", err)
|
||||
}
|
||||
if err := runner.Down(context.Background()); err != nil {
|
||||
t.Fatalf("date sync migration down: %v", err)
|
||||
}
|
||||
@@ -736,8 +739,8 @@ func TestDeviceExecutionResultsAreIdempotentAndAuditable(t *testing.T) {
|
||||
}
|
||||
if applied, err := runner.Up(context.Background()); err != nil {
|
||||
t.Fatalf("restore device command migration: %v", err)
|
||||
} else if applied != 6 {
|
||||
t.Fatalf("restored migrations = %d, want 6", applied)
|
||||
} else if applied != 7 {
|
||||
t.Fatalf("restored migrations = %d, want 7", applied)
|
||||
}
|
||||
|
||||
completePayload := fmt.Sprintf(
|
||||
@@ -1426,6 +1429,9 @@ func TestDeviceOrderCommandDeliveryAndAcknowledgementAreRecoverable(
|
||||
if err != nil {
|
||||
t.Fatalf("migration.New() error = %v", err)
|
||||
}
|
||||
if err := runner.Down(context.Background()); err != nil {
|
||||
t.Fatalf("metadata migration down: %v", err)
|
||||
}
|
||||
if err := runner.Down(context.Background()); err != nil {
|
||||
t.Fatalf("date sync migration down: %v", err)
|
||||
}
|
||||
|
||||
@@ -206,17 +206,19 @@ func (h *adminHandlers) freightOrderDetail(ctx *gin.Context) {
|
||||
items := make([]gin.H, 0, len(detail.Items))
|
||||
for _, item := range detail.Items {
|
||||
items = append(items, gin.H{
|
||||
"id": item.ID,
|
||||
"external_item_id": item.ExternalItemID,
|
||||
"title": item.Title,
|
||||
"product_spec": item.ProductSpec,
|
||||
"sku": item.SKU,
|
||||
"quantity": item.Quantity,
|
||||
"product_thumb_ref": item.ProductThumbRef,
|
||||
"purchase_status": item.PurchaseStatus,
|
||||
"revision": item.Revision,
|
||||
"canonical_sha256": item.CanonicalSHA256,
|
||||
"updated_at": formatTime(item.UpdatedAt),
|
||||
"id": item.ID,
|
||||
"external_item_id": item.ExternalItemID,
|
||||
"title": item.Title,
|
||||
"product_spec": item.ProductSpec,
|
||||
"sku": item.SKU,
|
||||
"quantity": item.Quantity,
|
||||
"product_thumb_ref": item.ProductThumbRef,
|
||||
"original_unit_price_minor": item.OriginalUnitPriceMinor,
|
||||
"original_currency": item.OriginalCurrency,
|
||||
"purchase_status": item.PurchaseStatus,
|
||||
"revision": item.Revision,
|
||||
"canonical_sha256": item.CanonicalSHA256,
|
||||
"updated_at": formatTime(item.UpdatedAt),
|
||||
})
|
||||
}
|
||||
ctx.Header("Cache-Control", "no-store")
|
||||
|
||||
@@ -150,15 +150,17 @@ type FreightOrder struct {
|
||||
}
|
||||
|
||||
type FreightOrderItem struct {
|
||||
ID string
|
||||
ExternalItemID string
|
||||
Title string
|
||||
ProductSpec string
|
||||
SKU string
|
||||
Quantity int
|
||||
ProductThumbRef string
|
||||
PurchaseStatus string
|
||||
Revision int
|
||||
ID string
|
||||
ExternalItemID string
|
||||
Title string
|
||||
ProductSpec string
|
||||
SKU string
|
||||
Quantity int
|
||||
ProductThumbRef string
|
||||
OriginalUnitPriceMinor *int64
|
||||
OriginalCurrency string
|
||||
PurchaseStatus string
|
||||
Revision int
|
||||
}
|
||||
|
||||
type FreightOrderDetail struct {
|
||||
|
||||
@@ -160,14 +160,16 @@ func (adapter *UsecaseAdapter) GetFreightOrder(
|
||||
items := make([]FreightItemReview, 0, len(detail.Items))
|
||||
for _, item := range detail.Items {
|
||||
view := FreightOrderItem{
|
||||
ID: item.ID,
|
||||
ExternalItemID: item.ExternalItemID,
|
||||
Title: item.Title,
|
||||
ProductSpec: item.ProductSpec,
|
||||
SKU: item.SKU,
|
||||
ProductThumbRef: stringValue(item.ProductThumbRef),
|
||||
PurchaseStatus: stringValue(item.PurchaseStatus),
|
||||
Revision: item.Revision,
|
||||
ID: item.ID,
|
||||
ExternalItemID: item.ExternalItemID,
|
||||
Title: item.Title,
|
||||
ProductSpec: item.ProductSpec,
|
||||
SKU: item.SKU,
|
||||
ProductThumbRef: stringValue(item.ProductThumbRef),
|
||||
OriginalUnitPriceMinor: item.OriginalUnitPriceMinor,
|
||||
OriginalCurrency: item.OriginalCurrency,
|
||||
PurchaseStatus: stringValue(item.PurchaseStatus),
|
||||
Revision: item.Revision,
|
||||
}
|
||||
if item.Quantity != nil {
|
||||
view.Quantity = *item.Quantity
|
||||
|
||||
Reference in New Issue
Block a user