Files
quyun-v2/backend/app/services/coupon_test.go
2026-01-09 16:23:42 +08:00

120 lines
3.1 KiB
Go

package services
import (
"database/sql"
"testing"
"quyun/v2/app/commands/testx"
order_dto "quyun/v2/app/http/v1/dto"
"quyun/v2/database"
"quyun/v2/database/models"
"quyun/v2/pkg/consts"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/suite"
"go.ipao.vip/atom/contracts"
"go.uber.org/dig"
)
type CouponTestSuiteInjectParams struct {
dig.In
DB *sql.DB
Initials []contracts.Initial `group:"initials"`
}
type CouponTestSuite struct {
suite.Suite
CouponTestSuiteInjectParams
}
func Test_Coupon(t *testing.T) {
providers := testx.Default().With(Provide)
testx.Serve(providers, t, func(p CouponTestSuiteInjectParams) {
suite.Run(t, &CouponTestSuite{CouponTestSuiteInjectParams: p})
})
}
func (s *CouponTestSuite) Test_CouponFlow() {
Convey("Coupon Flow", s.T(), func() {
ctx := s.T().Context()
tenantID := int64(1)
database.Truncate(
ctx,
s.DB,
models.TableNameCoupon,
models.TableNameUserCoupon,
models.TableNameOrder,
models.TableNameUser,
models.TableNameContent,
models.TableNameContentPrice,
)
user := &models.User{Username: "coupon_user", Phone: "13800000001"}
models.UserQuery.WithContext(ctx).Create(user)
// 1. Create Coupon (Fixed 5.00 CNY, Min 10.00 CNY)
cp := &models.Coupon{
TenantID: tenantID,
Title: "Save 5",
Type: "fix_amount",
Value: 500,
MinOrderAmount: 1000,
}
models.CouponQuery.WithContext(ctx).Create(cp)
// 2. Give to User
uc := &models.UserCoupon{
UserID: user.ID,
CouponID: cp.ID,
Status: "unused",
}
models.UserCouponQuery.WithContext(ctx).Create(uc)
Convey("should validate coupon successfully", func() {
discount, err := Coupon.Validate(ctx, tenantID, user.ID, uc.ID, 1500)
So(err, ShouldBeNil)
So(discount, ShouldEqual, 500)
})
Convey("should fail if below min amount", func() {
_, err := Coupon.Validate(ctx, tenantID, user.ID, uc.ID, 800)
So(err, ShouldNotBeNil)
})
Convey("should apply in Order.Create", func() {
// Setup Content
c := &models.Content{TenantID: tenantID, UserID: 99, Title: "Test", Status: consts.ContentStatusPublished}
models.ContentQuery.WithContext(ctx).Create(c)
models.ContentPriceQuery.WithContext(ctx).Create(&models.ContentPrice{
TenantID: tenantID,
ContentID: c.ID,
PriceAmount: 2000, // 20.00 CNY
Currency: "CNY",
})
form := &order_dto.OrderCreateForm{
ContentID: c.ID,
UserCouponID: uc.ID,
}
// Simulate Auth context for Order service
res, err := Order.Create(ctx, tenantID, user.ID, form)
So(err, ShouldBeNil)
// Verify Order
oid := res.OrderID
o, _ := models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.ID.Eq(oid)).First()
So(o.AmountOriginal, ShouldEqual, 2000)
So(o.AmountDiscount, ShouldEqual, 500)
So(o.AmountPaid, ShouldEqual, 1500)
So(o.CouponID, ShouldEqual, cp.ID)
// Verify Coupon Status
ucReload, _ := models.UserCouponQuery.WithContext(ctx).Where(models.UserCouponQuery.ID.Eq(uc.ID)).First()
So(ucReload.Status, ShouldEqual, "used")
So(ucReload.OrderID, ShouldEqual, oid)
})
})
}