From fe71276e62f07f6f5e03b15321e81c6a9a895ce9 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Fri, 31 Jul 2026 00:03:29 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E5=B1=A5=E7=BA=A6=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/003_drop_fulfillment_jobs.sql | 2 + backend/internal/model/merchant.go | 22 ---------- backend/internal/service/fulfillment.go | 44 ------------------- backend/internal/service/fulfillment_test.go | 10 +---- docs/API对接关系.md | 2 + 5 files changed, 5 insertions(+), 75 deletions(-) create mode 100644 backend/internal/database/migrations/003_drop_fulfillment_jobs.sql diff --git a/backend/internal/database/migrations/003_drop_fulfillment_jobs.sql b/backend/internal/database/migrations/003_drop_fulfillment_jobs.sql new file mode 100644 index 0000000..aedef7a --- /dev/null +++ b/backend/internal/database/migrations/003_drop_fulfillment_jobs.sql @@ -0,0 +1,2 @@ +-- 当前履约流程由上游通过 URL 获取订单号后主动查单和回传结果,不再维护独立任务表。 +DROP TABLE IF EXISTS fulfillment_jobs; diff --git a/backend/internal/model/merchant.go b/backend/internal/model/merchant.go index 30f87f0..2468f9b 100644 --- a/backend/internal/model/merchant.go +++ b/backend/internal/model/merchant.go @@ -45,11 +45,6 @@ const ( FulfillmentStatusFailed = "failed" FulfillmentStatusCancelled = "cancelled" - FulfillmentJobStatusPending = "pending" - FulfillmentJobStatusProcessing = "processing" - FulfillmentJobStatusSucceeded = "succeeded" - FulfillmentJobStatusFailed = "failed" - WalletLedgerCredit = "credit" WalletLedgerDebit = "debit" WalletLedgerRefund = "refund" @@ -228,23 +223,6 @@ type FulfillmentOrder struct { MerchantProduct *MerchantProduct `gorm:"foreignKey:MerchantProductID" json:"merchant_product,omitempty"` } -// FulfillmentJob 为后续履约器保留可重试的持久化任务边界。 -type FulfillmentJob struct { - ID uint `gorm:"primarykey" json:"id"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - - MerchantID uint `gorm:"not null;index" json:"merchant_id"` - OrderID uint `gorm:"not null;uniqueIndex" json:"order_id"` - Status string `gorm:"size:16;not null;default:pending;index" json:"status"` - Attempts int `gorm:"not null;default:0" json:"attempts"` - NextRunAt time.Time `gorm:"not null;index" json:"next_run_at"` - ProviderOrderNo string `gorm:"size:96;index" json:"provider_order_no"` - RequestPayload string `gorm:"type:text" json:"request_payload"` - ResultPayload string `gorm:"type:text" json:"result_payload"` - LastError string `gorm:"size:512" json:"last_error"` -} - // CallbackSubscription 为商户提供独立、可禁用的事件订阅。 type CallbackSubscription struct { ID uint `gorm:"primarykey" json:"id"` diff --git a/backend/internal/service/fulfillment.go b/backend/internal/service/fulfillment.go index ad5b767..6dcfa6a 100644 --- a/backend/internal/service/fulfillment.go +++ b/backend/internal/service/fulfillment.go @@ -181,14 +181,6 @@ func (s *FulfillmentService) CreateOrder(in CreateFulfillmentOrderInput) (*Creat return err } } - if err := tx.Create(&model.FulfillmentJob{ - MerchantID: in.MerchantID, - OrderID: order.ID, - Status: model.FulfillmentJobStatusPending, - NextRunAt: time.Now(), - }).Error; err != nil { - return err - } if err := writeAudit(tx, &in.MerchantID, nil, &in.APIClientID, "open_order.create", "fulfillment_order", order.OrderNo, map[string]interface{}{"client_order_no": in.ClientOrderNo, "sku": in.SKU}); err != nil { return err } @@ -415,20 +407,6 @@ func (s *FulfillmentService) UpdateFulfillment(in FulfillmentUpdateInput) (*mode if err := tx.Model(&order).Updates(updates).Error; err != nil { return err } - jobStatus := model.FulfillmentJobStatusProcessing - if in.Status == model.FulfillmentStatusSucceeded { - jobStatus = model.FulfillmentJobStatusSucceeded - } else if in.Status == model.FulfillmentStatusFailed { - jobStatus = model.FulfillmentJobStatusFailed - } - if err := tx.Model(&model.FulfillmentJob{}).Where("order_id = ?", order.ID).Updates(map[string]interface{}{ - "status": jobStatus, - "provider_order_no": in.ProviderOrderNo, - "result_payload": resultData, - "last_error": in.FailureReason, - }).Error; err != nil { - return err - } if err := tx.First(&out, order.ID).Error; err != nil { return err } @@ -509,12 +487,6 @@ func (s *FulfillmentService) CancelOrder(merchantID, apiClientID uint, orderNo, return err } } - if err := tx.Model(&model.FulfillmentJob{}).Where("order_id = ?", order.ID).Updates(map[string]interface{}{ - "status": model.FulfillmentJobStatusFailed, - "last_error": "订单已取消", - }).Error; err != nil { - return err - } if err := tx.First(&out, order.ID).Error; err != nil { return err } @@ -941,22 +913,6 @@ func (s *FulfillmentService) HandleShipNotify(in ShipNotifyInput) (*ShipNotifyRe return err } - jobStatus := model.FulfillmentJobStatusFailed - if nextStatus == model.FulfillmentStatusSucceeded { - jobStatus = model.FulfillmentJobStatusSucceeded - } - jobUpdates := map[string]interface{}{ - "status": jobStatus, - "result_payload": resultData, - "last_error": in.FailReason, - } - if in.ProviderOrderNo != "" { - jobUpdates["provider_order_no"] = in.ProviderOrderNo - } - if err := tx.Model(&model.FulfillmentJob{}).Where("order_id = ?", order.ID).Updates(jobUpdates).Error; err != nil { - return err - } - if err := writeAudit(tx, &order.MerchantID, nil, nil, "ship.notify", "fulfillment_order", order.OrderNo, shipNotifyAuditMetadata(in, nextStatus, message)); err != nil { return err diff --git a/backend/internal/service/fulfillment_test.go b/backend/internal/service/fulfillment_test.go index 6f2b4ba..521a547 100644 --- a/backend/internal/service/fulfillment_test.go +++ b/backend/internal/service/fulfillment_test.go @@ -19,7 +19,6 @@ func newServiceTestDB(t *testing.T) *gorm.DB { &model.WalletAccount{}, &model.WalletLedgerEntry{}, &model.FulfillmentOrder{}, - &model.FulfillmentJob{}, &model.CallbackSubscription{}, &model.CallbackDelivery{}, &model.AuditLog{}, @@ -458,7 +457,7 @@ func TestCreateTestOrderSupportsFailedFulfillableStatus(t *testing.T) { } } -func TestHandleShipNotifyUpdatesOrderJobAndEnqueuesMerchantCallback(t *testing.T) { +func TestHandleShipNotifyUpdatesOrderAndEnqueuesMerchantCallback(t *testing.T) { db := newServiceTestDB(t) merchantID, product := seedFulfillmentMerchant(t, db, "merchant-source-notify", 1000, 2, 100) codec, err := NewSecretCodec("test-master-key") @@ -504,13 +503,6 @@ func TestHandleShipNotifyUpdatesOrderJobAndEnqueuesMerchantCallback(t *testing.T if order.FulfillmentStatus != model.FulfillmentStatusSucceeded || order.ProviderOrderNo != "SRC-10001" || order.DeliveredAt == nil { t.Fatalf("unexpected order after source notify: %+v", order) } - var job model.FulfillmentJob - if err := db.Where("order_id = ?", created.Order.ID).First(&job).Error; err != nil { - t.Fatalf("query fulfillment job: %v", err) - } - if job.Status != model.FulfillmentJobStatusSucceeded || job.ProviderOrderNo != "SRC-10001" { - t.Fatalf("unexpected job after source notify: %+v", job) - } var delivery model.CallbackDelivery if err := db.Where("merchant_id = ? AND event = ?", merchantID, "order.fulfillment.updated").First(&delivery).Error; err != nil { t.Fatalf("query callback delivery: %v", err) diff --git a/docs/API对接关系.md b/docs/API对接关系.md index e61824b..492c326 100644 --- a/docs/API对接关系.md +++ b/docs/API对接关系.md @@ -33,6 +33,8 @@ 商户回调 / 商户查询订单 ``` +当前流程不再维护独立的 `fulfillment_jobs` 任务表;履约事实以订单表里的 `fulfillment_status`、上游单号、发货时间和失败原因等字段为准。 + ## 3. 鉴权不要混用 | 项 | 商户侧 `/api/client/v1` | 源头侧 `/api/open/v1` |