Files
quyun-v2/backend/app/services/coupon_test.go

199 lines
5.2 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: consts.CouponTypeFixAmount,
Value: 500,
MinOrderAmount: 1000,
}
models.CouponQuery.WithContext(ctx).Create(cp)
// 2. Give to User
uc := &models.UserCoupon{
UserID: user.ID,
CouponID: cp.ID,
Status: consts.UserCouponStatusUnused,
}
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: consts.CurrencyCNY,
})
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, consts.UserCouponStatusUsed)
So(ucReload.OrderID, ShouldEqual, oid)
})
})
}
func (s *CouponTestSuite) Test_Receive() {
Convey("Receive", s.T(), func() {
ctx := s.T().Context()
tenantID := int64(2)
database.Truncate(
ctx,
s.DB,
models.TableNameCoupon,
models.TableNameUserCoupon,
models.TableNameUser,
)
user := &models.User{Username: "coupon_receive", Phone: "13800000002"}
So(models.UserQuery.WithContext(ctx).Create(user), ShouldBeNil)
cp := &models.Coupon{
TenantID: tenantID,
Title: "Receive Test",
Type: consts.CouponTypeFixAmount,
Value: 300,
MinOrderAmount: 0,
TotalQuantity: 1,
}
So(models.CouponQuery.WithContext(ctx).Create(cp), ShouldBeNil)
item, err := Coupon.Receive(ctx, tenantID, user.ID, cp.ID)
So(err, ShouldBeNil)
So(item, ShouldNotBeNil)
So(item.CouponID, ShouldEqual, cp.ID)
// second receive should return existing
item2, err := Coupon.Receive(ctx, tenantID, user.ID, cp.ID)
So(err, ShouldBeNil)
So(item2.CouponID, ShouldEqual, cp.ID)
})
}
func (s *CouponTestSuite) Test_ListAvailable() {
Convey("ListAvailable", s.T(), func() {
ctx := s.T().Context()
tenantID := int64(3)
database.Truncate(
ctx,
s.DB,
models.TableNameCoupon,
models.TableNameUserCoupon,
models.TableNameUser,
)
user := &models.User{Username: "coupon_available", Phone: "13800000003"}
So(models.UserQuery.WithContext(ctx).Create(user), ShouldBeNil)
cp := &models.Coupon{
TenantID: tenantID,
Title: "Available Test",
Type: consts.CouponTypeFixAmount,
Value: 500,
MinOrderAmount: 1000,
}
So(models.CouponQuery.WithContext(ctx).Create(cp), ShouldBeNil)
uc := &models.UserCoupon{
UserID: user.ID,
CouponID: cp.ID,
Status: consts.UserCouponStatusUnused,
}
So(models.UserCouponQuery.WithContext(ctx).Create(uc), ShouldBeNil)
list, err := Coupon.ListAvailable(ctx, tenantID, user.ID, 500)
So(err, ShouldBeNil)
So(len(list), ShouldEqual, 0)
list, err = Coupon.ListAvailable(ctx, tenantID, user.ID, 1200)
So(err, ShouldBeNil)
So(len(list), ShouldEqual, 1)
So(list[0].CouponID, ShouldEqual, cp.ID)
})
}