feat: implement coupon management and receive flow
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"quyun/v2/app/errorx"
|
||||
"quyun/v2/app/http/v1/dto"
|
||||
"quyun/v2/app/requests"
|
||||
"quyun/v2/app/services"
|
||||
@@ -359,3 +360,103 @@ func (c *Creator) Withdraw(ctx fiber.Ctx, user *models.User, form *dto.WithdrawF
|
||||
tenantID := getTenantID(ctx)
|
||||
return services.Creator.Withdraw(ctx, tenantID, user.ID, form)
|
||||
}
|
||||
|
||||
// Create coupon
|
||||
//
|
||||
// @Router /t/:tenantCode/v1/creator/coupons [post]
|
||||
// @Summary Create coupon
|
||||
// @Description Create coupon template
|
||||
// @Tags CreatorCenter
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param form body dto.CouponCreateForm true "Coupon form"
|
||||
// @Success 200 {object} dto.CouponItem
|
||||
// @Bind user local key(__ctx_user)
|
||||
// @Bind form body
|
||||
func (c *Creator) CreateCoupon(ctx fiber.Ctx, user *models.User, form *dto.CouponCreateForm) (*dto.CouponItem, error) {
|
||||
tenantID := getTenantID(ctx)
|
||||
return services.Coupon.Create(ctx, tenantID, user.ID, form)
|
||||
}
|
||||
|
||||
// List coupons
|
||||
//
|
||||
// @Router /t/:tenantCode/v1/creator/coupons [get]
|
||||
// @Summary List coupons
|
||||
// @Description List coupon templates
|
||||
// @Tags CreatorCenter
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "Page"
|
||||
// @Param limit query int false "Limit"
|
||||
// @Param type query string false "Type (fix_amount/discount)"
|
||||
// @Param status query string false "Status (active/expired)"
|
||||
// @Param keyword query string false "Keyword"
|
||||
// @Success 200 {object} requests.Pager
|
||||
// @Bind user local key(__ctx_user)
|
||||
// @Bind filter query
|
||||
func (c *Creator) ListCoupons(ctx fiber.Ctx, user *models.User, filter *dto.CouponListFilter) (*requests.Pager, error) {
|
||||
tenantID := getTenantID(ctx)
|
||||
return services.Coupon.List(ctx, tenantID, filter)
|
||||
}
|
||||
|
||||
// Get coupon
|
||||
//
|
||||
// @Router /t/:tenantCode/v1/creator/coupons/:id<int> [get]
|
||||
// @Summary Get coupon
|
||||
// @Description Get coupon template detail
|
||||
// @Tags CreatorCenter
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int64 true "Coupon ID"
|
||||
// @Success 200 {object} dto.CouponItem
|
||||
// @Bind user local key(__ctx_user)
|
||||
// @Bind id path
|
||||
func (c *Creator) GetCoupon(ctx fiber.Ctx, user *models.User, id int64) (*dto.CouponItem, error) {
|
||||
tenantID := getTenantID(ctx)
|
||||
return services.Coupon.Get(ctx, tenantID, id)
|
||||
}
|
||||
|
||||
// Update coupon
|
||||
//
|
||||
// @Router /t/:tenantCode/v1/creator/coupons/:id<int> [put]
|
||||
// @Summary Update coupon
|
||||
// @Description Update coupon template
|
||||
// @Tags CreatorCenter
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int64 true "Coupon ID"
|
||||
// @Param form body dto.CouponUpdateForm true "Coupon form"
|
||||
// @Success 200 {object} dto.CouponItem
|
||||
// @Bind user local key(__ctx_user)
|
||||
// @Bind id path
|
||||
// @Bind form body
|
||||
func (c *Creator) UpdateCoupon(ctx fiber.Ctx, user *models.User, id int64, form *dto.CouponUpdateForm) (*dto.CouponItem, error) {
|
||||
tenantID := getTenantID(ctx)
|
||||
return services.Coupon.Update(ctx, tenantID, user.ID, id, form)
|
||||
}
|
||||
|
||||
// Grant coupon
|
||||
//
|
||||
// @Router /t/:tenantCode/v1/creator/coupons/:id<int>/grant [post]
|
||||
// @Summary Grant coupon
|
||||
// @Description Grant coupon to users
|
||||
// @Tags CreatorCenter
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int64 true "Coupon ID"
|
||||
// @Param form body dto.CouponGrantForm true "Grant form"
|
||||
// @Success 200 {string} string "Granted"
|
||||
// @Bind user local key(__ctx_user)
|
||||
// @Bind id path
|
||||
// @Bind form body
|
||||
func (c *Creator) GrantCoupon(ctx fiber.Ctx, user *models.User, id int64, form *dto.CouponGrantForm) (string, error) {
|
||||
tenantID := getTenantID(ctx)
|
||||
if form == nil {
|
||||
return "", errorx.ErrInvalidParameter.WithMsg("参数无效")
|
||||
}
|
||||
_, err := services.Coupon.Grant(ctx, tenantID, id, form.UserIDs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "Granted", nil
|
||||
}
|
||||
|
||||
@@ -1,5 +1,99 @@
|
||||
package dto
|
||||
|
||||
import "quyun/v2/app/requests"
|
||||
|
||||
type CouponCreateForm struct {
|
||||
// Title 优惠券标题。
|
||||
Title string `json:"title"`
|
||||
// Description 优惠券描述。
|
||||
Description string `json:"description"`
|
||||
// Type 优惠券类型(fix_amount/discount)。
|
||||
Type string `json:"type"`
|
||||
// Value 优惠券面值(分/折扣百分比)。
|
||||
Value int64 `json:"value"`
|
||||
// MinOrderAmount 使用门槛金额(分)。
|
||||
MinOrderAmount int64 `json:"min_order_amount"`
|
||||
// MaxDiscount 折扣券最高抵扣金额(分)。
|
||||
MaxDiscount int64 `json:"max_discount"`
|
||||
// TotalQuantity 发行总量(0 表示不限量)。
|
||||
TotalQuantity int32 `json:"total_quantity"`
|
||||
// StartAt 生效时间(RFC3339,可为空)。
|
||||
StartAt string `json:"start_at"`
|
||||
// EndAt 过期时间(RFC3339,可为空)。
|
||||
EndAt string `json:"end_at"`
|
||||
}
|
||||
|
||||
type CouponUpdateForm struct {
|
||||
// Title 优惠券标题(为空表示不修改)。
|
||||
Title *string `json:"title"`
|
||||
// Description 优惠券描述(为空表示不修改)。
|
||||
Description *string `json:"description"`
|
||||
// Type 优惠券类型(fix_amount/discount)。
|
||||
Type *string `json:"type"`
|
||||
// Value 优惠券面值(分/折扣百分比)。
|
||||
Value *int64 `json:"value"`
|
||||
// MinOrderAmount 使用门槛金额(分)。
|
||||
MinOrderAmount *int64 `json:"min_order_amount"`
|
||||
// MaxDiscount 折扣券最高抵扣金额(分)。
|
||||
MaxDiscount *int64 `json:"max_discount"`
|
||||
// TotalQuantity 发行总量(0 表示不限量)。
|
||||
TotalQuantity *int32 `json:"total_quantity"`
|
||||
// StartAt 生效时间(RFC3339,可为空)。
|
||||
StartAt *string `json:"start_at"`
|
||||
// EndAt 过期时间(RFC3339,可为空)。
|
||||
EndAt *string `json:"end_at"`
|
||||
}
|
||||
|
||||
type CouponItem struct {
|
||||
// ID 券模板ID。
|
||||
ID int64 `json:"id"`
|
||||
// Title 优惠券标题。
|
||||
Title string `json:"title"`
|
||||
// Description 优惠券描述。
|
||||
Description string `json:"description"`
|
||||
// Type 优惠券类型(fix_amount/discount)。
|
||||
Type string `json:"type"`
|
||||
// Value 优惠券面值(分/折扣百分比)。
|
||||
Value int64 `json:"value"`
|
||||
// MinOrderAmount 使用门槛金额(分)。
|
||||
MinOrderAmount int64 `json:"min_order_amount"`
|
||||
// MaxDiscount 折扣券最高抵扣金额(分)。
|
||||
MaxDiscount int64 `json:"max_discount"`
|
||||
// TotalQuantity 发行总量。
|
||||
TotalQuantity int32 `json:"total_quantity"`
|
||||
// UsedQuantity 已使用数量。
|
||||
UsedQuantity int32 `json:"used_quantity"`
|
||||
// StartAt 生效时间(RFC3339)。
|
||||
StartAt string `json:"start_at"`
|
||||
// EndAt 过期时间(RFC3339)。
|
||||
EndAt string `json:"end_at"`
|
||||
// CreatedAt 创建时间(RFC3339)。
|
||||
CreatedAt string `json:"created_at"`
|
||||
// UpdatedAt 更新时间(RFC3339)。
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
type CouponListFilter struct {
|
||||
// Pagination 分页参数(page/limit)。
|
||||
requests.Pagination
|
||||
// Type 优惠券类型过滤。
|
||||
Type *string `query:"type"`
|
||||
// Status 状态过滤(active/expired)。
|
||||
Status *string `query:"status"`
|
||||
// Keyword 关键词搜索(标题/描述)。
|
||||
Keyword *string `query:"keyword"`
|
||||
}
|
||||
|
||||
type CouponReceiveForm struct {
|
||||
// CouponID 券模板ID。
|
||||
CouponID int64 `json:"coupon_id"`
|
||||
}
|
||||
|
||||
type CouponGrantForm struct {
|
||||
// UserIDs 领取用户ID集合。
|
||||
UserIDs []int64 `json:"user_ids"`
|
||||
}
|
||||
|
||||
type UserCouponItem struct {
|
||||
// ID 用户券ID。
|
||||
ID int64 `json:"id"`
|
||||
|
||||
@@ -175,6 +175,18 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
Local[*models.User]("__ctx_user"),
|
||||
PathParam[int64]("id"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /t/:tenantCode/v1/creator/coupons -> creator.ListCoupons")
|
||||
router.Get("/t/:tenantCode/v1/creator/coupons"[len(r.Path()):], DataFunc2(
|
||||
r.creator.ListCoupons,
|
||||
Local[*models.User]("__ctx_user"),
|
||||
Query[dto.CouponListFilter]("filter"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /t/:tenantCode/v1/creator/coupons/:id<int> -> creator.GetCoupon")
|
||||
router.Get("/t/:tenantCode/v1/creator/coupons/:id<int>"[len(r.Path()):], DataFunc2(
|
||||
r.creator.GetCoupon,
|
||||
Local[*models.User]("__ctx_user"),
|
||||
PathParam[int64]("id"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /t/:tenantCode/v1/creator/dashboard -> creator.Dashboard")
|
||||
router.Get("/t/:tenantCode/v1/creator/dashboard"[len(r.Path()):], DataFunc1(
|
||||
r.creator.Dashboard,
|
||||
@@ -214,6 +226,19 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
Local[*models.User]("__ctx_user"),
|
||||
Body[dto.ContentCreateForm]("form"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Post /t/:tenantCode/v1/creator/coupons -> creator.CreateCoupon")
|
||||
router.Post("/t/:tenantCode/v1/creator/coupons"[len(r.Path()):], DataFunc2(
|
||||
r.creator.CreateCoupon,
|
||||
Local[*models.User]("__ctx_user"),
|
||||
Body[dto.CouponCreateForm]("form"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Post /t/:tenantCode/v1/creator/coupons/:id<int>/grant -> creator.GrantCoupon")
|
||||
router.Post("/t/:tenantCode/v1/creator/coupons/:id<int>/grant"[len(r.Path()):], DataFunc3(
|
||||
r.creator.GrantCoupon,
|
||||
Local[*models.User]("__ctx_user"),
|
||||
PathParam[int64]("id"),
|
||||
Body[dto.CouponGrantForm]("form"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Post /t/:tenantCode/v1/creator/members/:id<int>/review -> creator.ReviewMember")
|
||||
router.Post("/t/:tenantCode/v1/creator/members/:id<int>/review"[len(r.Path()):], Func3(
|
||||
r.creator.ReviewMember,
|
||||
@@ -259,6 +284,13 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
PathParam[int64]("id"),
|
||||
Body[dto.ContentUpdateForm]("form"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Put /t/:tenantCode/v1/creator/coupons/:id<int> -> creator.UpdateCoupon")
|
||||
router.Put("/t/:tenantCode/v1/creator/coupons/:id<int>"[len(r.Path()):], DataFunc3(
|
||||
r.creator.UpdateCoupon,
|
||||
Local[*models.User]("__ctx_user"),
|
||||
PathParam[int64]("id"),
|
||||
Body[dto.CouponUpdateForm]("form"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Put /t/:tenantCode/v1/creator/settings -> creator.UpdateSettings")
|
||||
router.Put("/t/:tenantCode/v1/creator/settings"[len(r.Path()):], Func2(
|
||||
r.creator.UpdateSettings,
|
||||
@@ -374,6 +406,12 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
Local[*models.User]("__ctx_user"),
|
||||
QueryParam[string]("status"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /t/:tenantCode/v1/me/coupons/available -> user.AvailableCoupons")
|
||||
router.Get("/t/:tenantCode/v1/me/coupons/available"[len(r.Path()):], DataFunc2(
|
||||
r.user.AvailableCoupons,
|
||||
Local[*models.User]("__ctx_user"),
|
||||
QueryParam[int64]("amount"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /t/:tenantCode/v1/me/favorites -> user.Favorites")
|
||||
router.Get("/t/:tenantCode/v1/me/favorites"[len(r.Path()):], DataFunc1(
|
||||
r.user.Favorites,
|
||||
@@ -418,6 +456,12 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
r.user.Wallet,
|
||||
Local[*models.User]("__ctx_user"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Post /t/:tenantCode/v1/me/coupons/receive -> user.ReceiveCoupon")
|
||||
router.Post("/t/:tenantCode/v1/me/coupons/receive"[len(r.Path()):], DataFunc2(
|
||||
r.user.ReceiveCoupon,
|
||||
Local[*models.User]("__ctx_user"),
|
||||
Body[dto.CouponReceiveForm]("form"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Post /t/:tenantCode/v1/me/favorites -> user.AddFavorite")
|
||||
router.Post("/t/:tenantCode/v1/me/favorites"[len(r.Path()):], Func2(
|
||||
r.user.AddFavorite,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"quyun/v2/app/errorx"
|
||||
"quyun/v2/app/http/v1/dto"
|
||||
auth_dto "quyun/v2/app/http/v1/dto"
|
||||
"quyun/v2/app/requests"
|
||||
@@ -319,3 +320,40 @@ func (u *User) MyCoupons(ctx fiber.Ctx, user *models.User, status string) ([]dto
|
||||
tenantID := getTenantID(ctx)
|
||||
return services.Coupon.ListUserCoupons(ctx, tenantID, user.ID, status)
|
||||
}
|
||||
|
||||
// List available coupons for order amount
|
||||
//
|
||||
// @Router /t/:tenantCode/v1/me/coupons/available [get]
|
||||
// @Summary List available coupons
|
||||
// @Description List coupons available for the given order amount
|
||||
// @Tags UserCenter
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param amount query int64 true "Order amount (cents)"
|
||||
// @Success 200 {array} dto.UserCouponItem
|
||||
// @Bind user local key(__ctx_user)
|
||||
// @Bind amount query
|
||||
func (u *User) AvailableCoupons(ctx fiber.Ctx, user *models.User, amount int64) ([]dto.UserCouponItem, error) {
|
||||
tenantID := getTenantID(ctx)
|
||||
return services.Coupon.ListAvailable(ctx, tenantID, user.ID, amount)
|
||||
}
|
||||
|
||||
// Receive coupon
|
||||
//
|
||||
// @Router /t/:tenantCode/v1/me/coupons/receive [post]
|
||||
// @Summary Receive coupon
|
||||
// @Description Receive a coupon by coupon_id
|
||||
// @Tags UserCenter
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param form body dto.CouponReceiveForm true "Receive form"
|
||||
// @Success 200 {object} dto.UserCouponItem
|
||||
// @Bind user local key(__ctx_user)
|
||||
// @Bind form body
|
||||
func (u *User) ReceiveCoupon(ctx fiber.Ctx, user *models.User, form *dto.CouponReceiveForm) (*dto.UserCouponItem, error) {
|
||||
tenantID := getTenantID(ctx)
|
||||
if form == nil {
|
||||
return nil, errorx.ErrInvalidParameter.WithMsg("参数无效")
|
||||
}
|
||||
return services.Coupon.Receive(ctx, tenantID, user.ID, form.CouponID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user