优化订单履约状态处理
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"affiliate_dash/internal/model"
|
||||
)
|
||||
|
||||
type fulfillmentTransitionKind string
|
||||
|
||||
const (
|
||||
fulfillmentTransitionUpdate fulfillmentTransitionKind = "update"
|
||||
fulfillmentTransitionShipNotify fulfillmentTransitionKind = "ship_notify"
|
||||
fulfillmentTransitionTimeout fulfillmentTransitionKind = "timeout"
|
||||
)
|
||||
|
||||
type orderRequestFingerprintPayload struct {
|
||||
ClientOrderNo string `json:"client_order_no"`
|
||||
SKU string `json:"sku"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
BuyerReference string `json:"buyer_reference"`
|
||||
RequestData string `json:"request_data"`
|
||||
}
|
||||
|
||||
func orderRequestFingerprint(in CreateFulfillmentOrderInput, requestData string) string {
|
||||
raw, _ := json.Marshal(orderRequestFingerprintPayload{
|
||||
ClientOrderNo: in.ClientOrderNo,
|
||||
SKU: in.SKU,
|
||||
Quantity: in.Quantity,
|
||||
BuyerReference: in.BuyerReference,
|
||||
RequestData: requestData,
|
||||
})
|
||||
sum := sha256.Sum256(raw)
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
func storedOrderRequestFingerprint(order *model.FulfillmentOrder) string {
|
||||
if order == nil {
|
||||
return ""
|
||||
}
|
||||
if order.RequestFingerprint != "" {
|
||||
return order.RequestFingerprint
|
||||
}
|
||||
return orderRequestFingerprint(CreateFulfillmentOrderInput{
|
||||
ClientOrderNo: order.ClientOrderNo,
|
||||
SKU: order.ProductSKU,
|
||||
Quantity: order.Quantity,
|
||||
BuyerReference: order.BuyerReference,
|
||||
}, order.RequestData)
|
||||
}
|
||||
|
||||
func ensureSameIdempotentOrder(existing *model.FulfillmentOrder, fingerprint string) error {
|
||||
if existing == nil {
|
||||
return errors.New("订单不存在")
|
||||
}
|
||||
if storedOrderRequestFingerprint(existing) != fingerprint {
|
||||
return errors.New("client_order_no 已存在,但本次请求参数与原订单不一致")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateFulfillmentTransition(order *model.FulfillmentOrder, next string, kind fulfillmentTransitionKind) error {
|
||||
if order == nil {
|
||||
return errors.New("订单不存在")
|
||||
}
|
||||
if order.PaymentStatus != model.PaymentStatusPaid {
|
||||
return errors.New("订单未支付,不能履约")
|
||||
}
|
||||
if order.FulfillmentStatus == next {
|
||||
return nil
|
||||
}
|
||||
switch order.FulfillmentStatus {
|
||||
case model.FulfillmentStatusCancelled:
|
||||
return errors.New("订单已取消,不能更新履约状态")
|
||||
case model.FulfillmentStatusSucceeded:
|
||||
return errors.New("订单已履约成功,不能回退状态")
|
||||
}
|
||||
switch next {
|
||||
case model.FulfillmentStatusProcessing:
|
||||
if order.FulfillmentStatus == model.FulfillmentStatusPending || order.FulfillmentStatus == model.FulfillmentStatusFailed {
|
||||
return nil
|
||||
}
|
||||
case model.FulfillmentStatusSucceeded:
|
||||
if order.FulfillmentStatus == model.FulfillmentStatusPending ||
|
||||
order.FulfillmentStatus == model.FulfillmentStatusFailed ||
|
||||
order.FulfillmentStatus == model.FulfillmentStatusProcessing {
|
||||
return nil
|
||||
}
|
||||
case model.FulfillmentStatusFailed:
|
||||
if kind == fulfillmentTransitionTimeout && order.FulfillmentStatus != model.FulfillmentStatusProcessing {
|
||||
return errors.New("只有履约中的订单可以标记超时")
|
||||
}
|
||||
if order.FulfillmentStatus == model.FulfillmentStatusPending ||
|
||||
order.FulfillmentStatus == model.FulfillmentStatusFailed ||
|
||||
order.FulfillmentStatus == model.FulfillmentStatusProcessing {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("订单当前状态不允许该履约变更")
|
||||
}
|
||||
|
||||
func canCancelOrder(order *model.FulfillmentOrder) error {
|
||||
if order == nil {
|
||||
return errors.New("订单不存在")
|
||||
}
|
||||
if order.FulfillmentStatus == model.FulfillmentStatusCancelled {
|
||||
return nil
|
||||
}
|
||||
if order.PaymentStatus != model.PaymentStatusPaid {
|
||||
return errors.New("订单未支付或已退款,不能取消")
|
||||
}
|
||||
switch order.FulfillmentStatus {
|
||||
case model.FulfillmentStatusPending, model.FulfillmentStatusFailed:
|
||||
return nil
|
||||
case model.FulfillmentStatusProcessing, model.FulfillmentStatusSucceeded:
|
||||
return errors.New("订单已进入履约流程,不能取消")
|
||||
default:
|
||||
return errors.New("订单当前状态不能取消")
|
||||
}
|
||||
}
|
||||
|
||||
func processingTimedOut(order *model.FulfillmentOrder, timeout time.Duration, now time.Time) bool {
|
||||
if order == nil || timeout <= 0 {
|
||||
return false
|
||||
}
|
||||
return order.FulfillmentStatus == model.FulfillmentStatusProcessing && order.UpdatedAt.Before(now.Add(-timeout))
|
||||
}
|
||||
Reference in New Issue
Block a user