feat(t239): persist freight item metadata
This commit is contained in:
@@ -383,6 +383,9 @@ func TestAuthMigrationCanRollbackWithoutRebuildingPurchaseTasks(
|
||||
if err != nil {
|
||||
t.Fatalf("migration.New() error = %v", err)
|
||||
}
|
||||
if err := runner.Down(context.Background()); err != nil {
|
||||
t.Fatalf("Down(v15) error = %v", err)
|
||||
}
|
||||
if err := runner.Down(context.Background()); err != nil {
|
||||
t.Fatalf("Down(v14) error = %v", err)
|
||||
}
|
||||
@@ -432,9 +435,9 @@ func TestAuthMigrationCanRollbackWithoutRebuildingPurchaseTasks(
|
||||
t.Fatal("purchase_tasks was lost during auth migration rollback")
|
||||
}
|
||||
if applied, err := runner.Up(context.Background()); err != nil {
|
||||
t.Fatalf("Up(v3-v14) error = %v", err)
|
||||
} else if applied != 12 {
|
||||
t.Fatalf("Up(v3-v14) applied = %d, want 12", applied)
|
||||
t.Fatalf("Up(v3-v15) error = %v", err)
|
||||
} else if applied != 13 {
|
||||
t.Fatalf("Up(v3-v15) applied = %d, want 13", applied)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -318,10 +318,11 @@ func upsertFreightOrderItem(
|
||||
ctx,
|
||||
`INSERT INTO freight_order_items (
|
||||
id, freight_order_id, external_item_id, title, product_spec,
|
||||
sku, quantity, product_thumb_ref, purchase_status,
|
||||
sku, quantity, product_thumb_ref, original_unit_price_minor,
|
||||
original_currency, purchase_status,
|
||||
canonical_sha256, revision, is_present, first_sync_run_id,
|
||||
last_sync_run_id, created_at, updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 1, ?, ?, ?, ?)
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 1, ?, ?, ?, ?)
|
||||
ON CONFLICT (freight_order_id, external_item_id)
|
||||
DO UPDATE SET
|
||||
title = excluded.title,
|
||||
@@ -329,6 +330,8 @@ func upsertFreightOrderItem(
|
||||
sku = excluded.sku,
|
||||
quantity = excluded.quantity,
|
||||
product_thumb_ref = excluded.product_thumb_ref,
|
||||
original_unit_price_minor = excluded.original_unit_price_minor,
|
||||
original_currency = excluded.original_currency,
|
||||
purchase_status = excluded.purchase_status,
|
||||
revision = CASE
|
||||
WHEN freight_order_items.canonical_sha256 != excluded.canonical_sha256
|
||||
@@ -347,6 +350,8 @@ func upsertFreightOrderItem(
|
||||
item.SKU,
|
||||
nullableFreightQuantity(item.Quantity),
|
||||
nullableString(item.ProductThumbRef),
|
||||
nullableInt64(item.OriginalUnitPriceMinor),
|
||||
item.OriginalCurrency,
|
||||
nullableString(item.PurchaseStatus),
|
||||
item.CanonicalSHA256,
|
||||
runID,
|
||||
@@ -519,7 +524,8 @@ func (store *Store) GetFreightOrder(
|
||||
ctx,
|
||||
`SELECT
|
||||
id, freight_order_id, external_item_id, title, product_spec,
|
||||
sku, quantity, product_thumb_ref, purchase_status,
|
||||
sku, quantity, product_thumb_ref, original_unit_price_minor,
|
||||
original_currency, purchase_status,
|
||||
canonical_sha256, revision, is_present, first_sync_run_id,
|
||||
last_sync_run_id, created_at, updated_at
|
||||
FROM freight_order_items
|
||||
@@ -678,6 +684,7 @@ func scanFreightOrder(scanner rowScanner) (domain.FreightOrder, error) {
|
||||
func scanFreightOrderItem(scanner rowScanner) (domain.FreightOrderItem, error) {
|
||||
var item domain.FreightOrderItem
|
||||
var quantity sql.NullInt64
|
||||
var originalUnitPriceMinor sql.NullInt64
|
||||
var thumb, purchaseStatus sql.NullString
|
||||
var createdAt, updatedAt string
|
||||
err := scanner.Scan(
|
||||
@@ -689,6 +696,8 @@ func scanFreightOrderItem(scanner rowScanner) (domain.FreightOrderItem, error) {
|
||||
&item.SKU,
|
||||
&quantity,
|
||||
&thumb,
|
||||
&originalUnitPriceMinor,
|
||||
&item.OriginalCurrency,
|
||||
&purchaseStatus,
|
||||
&item.CanonicalSHA256,
|
||||
&item.Revision,
|
||||
@@ -706,6 +715,9 @@ func scanFreightOrderItem(scanner rowScanner) (domain.FreightOrderItem, error) {
|
||||
item.Quantity = &value
|
||||
}
|
||||
item.ProductThumbRef = optionalString(thumb)
|
||||
if originalUnitPriceMinor.Valid {
|
||||
item.OriginalUnitPriceMinor = &originalUnitPriceMinor.Int64
|
||||
}
|
||||
item.PurchaseStatus = optionalString(purchaseStatus)
|
||||
item.CreatedAt, err = parseTimestamp(createdAt)
|
||||
if err != nil {
|
||||
|
||||
@@ -57,6 +57,8 @@ func TestFreightImportIsAtomicIdempotentAndRevisioned(t *testing.T) {
|
||||
t.Fatalf("StartFreightSync() error = %v", err)
|
||||
}
|
||||
batch := freightBatch(910, "a", "b")
|
||||
price := int64(12950)
|
||||
batch.Orders[0].Items[0].OriginalUnitPriceMinor = &price
|
||||
if err := store.CompleteFreightSync(
|
||||
ctx,
|
||||
first,
|
||||
@@ -74,10 +76,16 @@ func TestFreightImportIsAtomicIdempotentAndRevisioned(t *testing.T) {
|
||||
if err != nil || len(detail.Items) != 2 {
|
||||
t.Fatalf("detail = %+v, error = %v", detail, err)
|
||||
}
|
||||
if detail.Items[0].OriginalUnitPriceMinor == nil ||
|
||||
*detail.Items[0].OriginalUnitPriceMinor != price ||
|
||||
detail.Items[0].OriginalCurrency != domain.FreightCurrencyTWD {
|
||||
t.Fatalf("item price metadata = %+v", detail.Items[0])
|
||||
}
|
||||
|
||||
second := freightRun(904, userID, now.Add(time.Minute))
|
||||
createAndStartFreightRun(t, store, second, "freight-key-2", "3")
|
||||
unchanged := freightBatch(920, "a", "b")
|
||||
unchanged.Orders[0].Items[0].OriginalUnitPriceMinor = &price
|
||||
if err := store.CompleteFreightSync(
|
||||
ctx,
|
||||
second,
|
||||
@@ -96,6 +104,7 @@ func TestFreightImportIsAtomicIdempotentAndRevisioned(t *testing.T) {
|
||||
third := freightRun(905, userID, now.Add(2*time.Minute))
|
||||
createAndStartFreightRun(t, store, third, "freight-key-3", "4")
|
||||
changed := freightBatch(930, "a", "c")
|
||||
changed.Orders[0].Items[0].OriginalUnitPriceMinor = &price
|
||||
changed.Orders[0].CanonicalSHA256 = repeatHex("d")
|
||||
changed.Orders[0].Items[1].Title = "变化后的商品"
|
||||
changed.Orders[0].Items[1].CanonicalSHA256 = repeatHex("e")
|
||||
@@ -113,10 +122,18 @@ func TestFreightImportIsAtomicIdempotentAndRevisioned(t *testing.T) {
|
||||
detail.Items[1].Revision != 2 {
|
||||
t.Fatalf("changed revisions = %+v", detail)
|
||||
}
|
||||
if _, err := db.Exec(
|
||||
`UPDATE freight_order_items SET original_unit_price_minor = NULL`,
|
||||
); err != nil {
|
||||
t.Fatalf("clear metadata before rollback guard test: %v", err)
|
||||
}
|
||||
runner, err := migration.New(db)
|
||||
if err != nil {
|
||||
t.Fatalf("migration.New() error = %v", err)
|
||||
}
|
||||
if err := runner.Down(ctx); err != nil {
|
||||
t.Fatalf("metadata migration down: %v", err)
|
||||
}
|
||||
if err := runner.Down(ctx); err != nil {
|
||||
t.Fatalf("date sync migration down: %v", err)
|
||||
}
|
||||
@@ -251,6 +268,9 @@ func TestFreightDateSyncAdvancesWatermarkOnlyOnWholeBatchSuccess(
|
||||
}
|
||||
|
||||
runner, _ := migration.New(db)
|
||||
if err := runner.Down(ctx); err != nil {
|
||||
t.Fatalf("metadata migration down: %v", err)
|
||||
}
|
||||
if err := runner.Down(ctx); err == nil {
|
||||
t.Fatal("date sync migration down succeeded with retained watermark")
|
||||
}
|
||||
@@ -334,22 +354,24 @@ func freightBatch(index int, firstHash, secondHash string) domain.FreightImportB
|
||||
CanonicalSHA256: repeatHex("c"),
|
||||
Items: []domain.FreightImportItem{
|
||||
{
|
||||
ID: uuid(index + 1),
|
||||
ExternalItemID: "88",
|
||||
Title: "商品一",
|
||||
ProductSpec: "黑色,L",
|
||||
SKU: "BLACK-L",
|
||||
Quantity: &quantityOne,
|
||||
CanonicalSHA256: repeatHex(firstHash),
|
||||
ID: uuid(index + 1),
|
||||
ExternalItemID: "88",
|
||||
Title: "商品一",
|
||||
ProductSpec: "黑色,L",
|
||||
SKU: "黑色,L",
|
||||
Quantity: &quantityOne,
|
||||
OriginalCurrency: domain.FreightCurrencyTWD,
|
||||
CanonicalSHA256: repeatHex(firstHash),
|
||||
},
|
||||
{
|
||||
ID: uuid(index + 2),
|
||||
ExternalItemID: "89",
|
||||
Title: "商品二",
|
||||
ProductSpec: "白色,M",
|
||||
SKU: "WHITE-M",
|
||||
Quantity: &quantityTwo,
|
||||
CanonicalSHA256: repeatHex(secondHash),
|
||||
ID: uuid(index + 2),
|
||||
ExternalItemID: "89",
|
||||
Title: "商品二",
|
||||
ProductSpec: "白色,M",
|
||||
SKU: "白色,M",
|
||||
Quantity: &quantityTwo,
|
||||
OriginalCurrency: domain.FreightCurrencyTWD,
|
||||
CanonicalSHA256: repeatHex(secondHash),
|
||||
},
|
||||
},
|
||||
}}}
|
||||
|
||||
@@ -21,7 +21,8 @@ func (store *Store) GetProcurementSourceItem(
|
||||
`SELECT
|
||||
item.id, item.freight_order_id, item.external_item_id,
|
||||
item.title, item.product_spec, item.sku, item.quantity,
|
||||
item.product_thumb_ref, item.purchase_status,
|
||||
item.product_thumb_ref, item.original_unit_price_minor,
|
||||
item.original_currency, item.purchase_status,
|
||||
item.canonical_sha256, item.revision, item.is_present,
|
||||
item.first_sync_run_id, item.last_sync_run_id,
|
||||
item.created_at, item.updated_at
|
||||
|
||||
@@ -238,6 +238,9 @@ func TestProcurementRequestsArePerItemAndTaskSnapshotIsImmutable(
|
||||
if err != nil {
|
||||
t.Fatalf("migration.New() error = %v", err)
|
||||
}
|
||||
if err := runner.Down(ctx); err != nil {
|
||||
t.Fatalf("metadata migration down: %v", err)
|
||||
}
|
||||
if err := runner.Down(ctx); err != nil {
|
||||
t.Fatalf("date sync migration down: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user