feat: 添加订单退款功能的测试用例及相关逻辑

This commit is contained in:
2025-12-23 09:26:22 +08:00
parent ead821ac2c
commit dd7bcdfb98
3 changed files with 104 additions and 43 deletions

View File

@@ -1077,8 +1077,8 @@ func (s *OrderTestSuite) Test_AdminRefundOrder() {
So(err, ShouldNotBeNil)
})
Convey("成功退款应回收权益并入账", func() {
s.seedTenantUser(ctx, tenantID, buyerUserID, 0, 0)
Convey("成功退款应回收权益并入账", func() {
s.seedTenantUser(ctx, tenantID, buyerUserID, 0, 0)
contentID := int64(123)
orderModel := &models.Order{
@@ -1122,26 +1122,45 @@ func (s *OrderTestSuite) Test_AdminRefundOrder() {
}
So(access.Create(ctx), ShouldBeNil)
refunding, err := Order.AdminRefundOrder(ctx, tenantID, operatorUserID, orderModel.ID, false, "原因", "", now.Add(time.Minute))
So(err, ShouldBeNil)
So(refunding, ShouldNotBeNil)
So(refunding.Status, ShouldEqual, consts.OrderStatusRefunding)
refunding, err := Order.AdminRefundOrder(ctx, tenantID, operatorUserID, orderModel.ID, false, "原因", "", now.Add(time.Minute))
So(err, ShouldBeNil)
So(refunding, ShouldNotBeNil)
So(refunding.Status, ShouldEqual, consts.OrderStatusRefunding)
refunded, err := Order.ProcessRefundingOrder(ctx, &ProcessRefundingOrderParams{
TenantID: tenantID,
OrderID: orderModel.ID,
OperatorUserID: operatorUserID,
Force: false,
Reason: "原因",
Now: now.Add(2 * time.Minute),
})
So(err, ShouldBeNil)
So(refunded, ShouldNotBeNil)
So(refunded.Status, ShouldEqual, consts.OrderStatusRefunded)
// refunding 期间重复请求应幂等返回 refunding并允许重复触发入队不影响最终结果
refunding2, err := Order.AdminRefundOrder(ctx, tenantID, operatorUserID, orderModel.ID, false, "原因2", "", now.Add(90*time.Second))
So(err, ShouldBeNil)
So(refunding2, ShouldNotBeNil)
So(refunding2.Status, ShouldEqual, consts.OrderStatusRefunding)
var tu models.TenantUser
So(_db.WithContext(ctx).Where("tenant_id = ? AND user_id = ?", tenantID, buyerUserID).First(&tu).Error, ShouldBeNil)
So(tu.Balance, ShouldEqual, 300)
refunded, err := Order.ProcessRefundingOrder(ctx, &ProcessRefundingOrderParams{
TenantID: tenantID,
OrderID: orderModel.ID,
OperatorUserID: operatorUserID,
Force: false,
Reason: "原因",
Now: now.Add(2 * time.Minute),
})
So(err, ShouldBeNil)
So(refunded, ShouldNotBeNil)
So(refunded.Status, ShouldEqual, consts.OrderStatusRefunded)
// worker 重试/重复执行应幂等:不重复入账、不重复回收权益。
refundedRetry, err := Order.ProcessRefundingOrder(ctx, &ProcessRefundingOrderParams{
TenantID: tenantID,
OrderID: orderModel.ID,
OperatorUserID: operatorUserID,
Force: false,
Reason: "原因",
Now: now.Add(5 * time.Minute),
})
So(err, ShouldBeNil)
So(refundedRetry, ShouldNotBeNil)
So(refundedRetry.Status, ShouldEqual, consts.OrderStatusRefunded)
var tu models.TenantUser
So(_db.WithContext(ctx).Where("tenant_id = ? AND user_id = ?", tenantID, buyerUserID).First(&tu).Error, ShouldBeNil)
So(tu.Balance, ShouldEqual, 300)
var access2 models.ContentAccess
So(_db.WithContext(ctx).Where("tenant_id = ? AND user_id = ? AND content_id = ?", tenantID, buyerUserID, contentID).First(&access2).Error, ShouldBeNil)
@@ -1157,13 +1176,26 @@ func (s *OrderTestSuite) Test_AdminRefundOrder() {
So(tu2.Balance, ShouldEqual, 300)
var ledgers []*models.TenantLedger
So(_db.WithContext(ctx).
Where("tenant_id = ? AND user_id = ? AND idempotency_key = ?", tenantID, buyerUserID, fmt.Sprintf("refund:%d", orderModel.ID)).
Find(&ledgers).Error, ShouldBeNil)
So(len(ledgers), ShouldEqual, 1)
So(_db.WithContext(ctx).
Where("tenant_id = ? AND user_id = ? AND idempotency_key = ?", tenantID, buyerUserID, fmt.Sprintf("refund:%d", orderModel.ID)).
Find(&ledgers).Error, ShouldBeNil)
So(len(ledgers), ShouldEqual, 1)
})
Convey("不可重试错误分类应稳定", func() {
So(IsRefundJobNonRetryableError(nil), ShouldBeFalse)
So(IsRefundJobNonRetryableError(errors.New("x")), ShouldBeFalse)
So(IsRefundJobNonRetryableError(errorx.ErrInvalidParameter), ShouldBeTrue)
So(IsRefundJobNonRetryableError(errorx.ErrRecordNotFound), ShouldBeTrue)
So(IsRefundJobNonRetryableError(errorx.ErrStatusConflict), ShouldBeTrue)
So(IsRefundJobNonRetryableError(errorx.ErrPreconditionFailed), ShouldBeTrue)
So(IsRefundJobNonRetryableError(errorx.ErrPermissionDenied), ShouldBeTrue)
So(IsRefundJobNonRetryableError(errorx.ErrInternalError), ShouldBeFalse)
})
})
})
}
}
func (s *OrderTestSuite) Test_PurchaseContent() {
Convey("Order.PurchaseContent", s.T(), func() {