feat: add manual fulfillment order creation

This commit is contained in:
yml2213
2026-08-11 11:49:58 +08:00
parent 2264851d5d
commit b686a82e60
12 changed files with 278 additions and 121 deletions
@@ -123,6 +123,66 @@ func TestFulfillmentCreateOrderDebitsWalletAndIsIdempotent(t *testing.T) {
}
}
func TestFulfillmentCreateManualOrderDebitsWalletAndStock(t *testing.T) {
db := newServiceTestDB(t)
merchantID, product := seedFulfillmentMerchant(t, db, "merchant-manual-order", 1000, 5, 200)
svc := NewFulfillmentService(db, nil)
created, err := svc.CreateManualOrder(CreateManualOrderInput{
MerchantID: merchantID,
ActorUserID: 42,
ClientOrderNo: "manual-001",
SKU: product.SKU,
Quantity: 2,
BuyerReference: "manual-buyer",
RequestData: map[string]string{"game_account": "123456"},
})
if err != nil {
t.Fatalf("create manual order: %v", err)
}
if created.Idempotent || created.Order.OrderSource != model.OrderSourceManual || created.Order.Amount != 400 {
t.Fatalf("unexpected manual order: %+v", created)
}
again, err := svc.CreateManualOrder(CreateManualOrderInput{
MerchantID: merchantID,
ActorUserID: 42,
ClientOrderNo: "manual-001",
SKU: product.SKU,
Quantity: 2,
BuyerReference: "manual-buyer",
RequestData: map[string]string{"game_account": "123456"},
})
if err != nil {
t.Fatalf("idempotent manual order: %v", err)
}
if !again.Idempotent || again.Order.OrderNo != created.Order.OrderNo {
t.Fatalf("manual order should be idempotent, got %+v", again)
}
var wallet model.WalletAccount
if err := db.Where("merchant_id = ?", merchantID).First(&wallet).Error; err != nil {
t.Fatalf("query wallet: %v", err)
}
if wallet.AvailableBalance != 600 {
t.Fatalf("wallet should debit once, got %d", wallet.AvailableBalance)
}
var refreshed model.MerchantProduct
if err := db.First(&refreshed, product.ID).Error; err != nil {
t.Fatalf("query product: %v", err)
}
if refreshed.Stock != 3 {
t.Fatalf("stock should decrease once, got %d", refreshed.Stock)
}
var audit model.AuditLog
if err := db.Where("entity_id = ? AND action = ?", created.Order.OrderNo, "merchant_order.manual_create").First(&audit).Error; err != nil {
t.Fatalf("query manual creation audit: %v", err)
}
if audit.ActorUserID == nil || *audit.ActorUserID != 42 || audit.APIClientID != nil {
t.Fatalf("unexpected manual creation audit: %+v", audit)
}
}
func TestFulfillmentCreateOrderRejectsIdempotencyMismatch(t *testing.T) {
db := newServiceTestDB(t)
merchantID, product := seedFulfillmentMerchant(t, db, "merchant-idempotency-mismatch", 1000, 5, 200)