feat: add coupon support to orders and create user_coupons model
- Added CouponID field to Order model to track used coupons. - Updated order query generation to include CouponID. - Introduced UserCoupon model to manage user coupon associations. - Implemented query methods for UserCoupon to facilitate CRUD operations. - Updated query context and default query setup to include UserCoupon.
This commit is contained in:
111
backend/app/services/coupon_test.go
Normal file
111
backend/app/services/coupon_test.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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"
|
||||
"quyun/v2/providers/storage"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"github.com/spf13/cast"
|
||||
"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).With(storage.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()
|
||||
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{
|
||||
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, user.ID, uc.ID, 1500)
|
||||
So(err, ShouldBeNil)
|
||||
So(discount, ShouldEqual, 500)
|
||||
})
|
||||
|
||||
Convey("should fail if below min amount", func() {
|
||||
_, err := Coupon.Validate(ctx, user.ID, uc.ID, 800)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("should apply in Order.Create", func() {
|
||||
// Setup Content
|
||||
c := &models.Content{UserID: 99, Title: "Test", Status: consts.ContentStatusPublished}
|
||||
models.ContentQuery.WithContext(ctx).Create(c)
|
||||
models.ContentPriceQuery.WithContext(ctx).Create(&models.ContentPrice{
|
||||
ContentID: c.ID,
|
||||
PriceAmount: 2000, // 20.00 CNY
|
||||
Currency: "CNY",
|
||||
})
|
||||
|
||||
form := &order_dto.OrderCreateForm{
|
||||
ContentID: cast.ToString(c.ID),
|
||||
UserCouponID: cast.ToString(uc.ID),
|
||||
}
|
||||
// Simulate Auth context for Order service
|
||||
authCtx := context.WithValue(ctx, consts.CtxKeyUser, user.ID)
|
||||
res, err := Order.Create(authCtx, form)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// Verify Order
|
||||
oid := cast.ToInt64(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)
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user