用户余额查询

This commit is contained in:
2026-04-25 14:15:37 +08:00
parent 0edc883084
commit d59f4ca37f
8 changed files with 153 additions and 32 deletions

View File

@@ -11,6 +11,65 @@ import (
"github.com/gofiber/fiber/v2"
)
// PageBalanceActivity 分页查询当前用户的余额变动记录
func PageBalanceActivity(c *fiber.Ctx) error {
// 获取当前用户ID
authCtx, err := auth.GetAuthCtx(c).PermitUser()
if err != nil {
return err
}
// 解析请求参数
req := new(PageBalanceActivityByUserReq)
if err := g.Validator.ParseBody(c, req); err != nil {
return err
}
// 构造查询条件
do := q.BalanceActivity.Where(q.BalanceActivity.UserID.Eq(authCtx.User.ID))
if req.BillNo != nil {
do = do.Where(q.Bill.As("Bill").BillNo.Eq(*req.BillNo))
}
if req.CreatedAtStart != nil {
t := u.DateHead(*req.CreatedAtStart)
do = do.Where(q.BalanceActivity.CreatedAt.Gte(t))
}
if req.CreatedAtEnd != nil {
t := u.DateTail(*req.CreatedAtEnd)
do = do.Where(q.BalanceActivity.CreatedAt.Lte(t))
}
// 查询余额变动列表
list, total, err := q.BalanceActivity.
Joins(q.BalanceActivity.Bill).
Select(
q.BalanceActivity.ALL,
q.Bill.As("Bill").ID.As("Bill__id"),
q.Bill.As("Bill").BillNo.As("Bill__bill_no"),
).
Where(do).
Order(q.BalanceActivity.CreatedAt.Desc()).
FindByPage(req.GetOffset(), req.GetLimit())
if err != nil {
return core.NewBizErr("获取数据失败", err)
}
// 返回结果
return c.JSON(core.PageResp{
List: list,
Total: int(total),
Page: req.GetPage(),
Size: req.GetSize(),
})
}
type PageBalanceActivityByUserReq struct {
core.PageReq
BillNo *string `json:"bill_no,omitempty"`
CreatedAtStart *time.Time `json:"created_at_start,omitempty"`
CreatedAtEnd *time.Time `json:"created_at_end,omitempty"`
}
// PageBalanceActivityByAdmin 分页查询所有余额变动记录
func PageBalanceActivityByAdmin(c *fiber.Ctx) error {
// 检查权限

View File

@@ -260,7 +260,7 @@ type UpdateUserBalanceByAdminData struct {
// 绑定管理员
func BindAdmin(c *fiber.Ctx) error {
// 检查权限
authCtx, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeUserWrite)
authCtx, err := auth.GetAuthCtx(c).PermitAdmin(core.ScopeUserWriteBind)
if err != nil {
return err
}

View File

@@ -4,13 +4,13 @@ import "time"
// CouponUser 优惠券发放表
type CouponUser struct {
ID int32 `json:"id" gorm:"column:id;primaryKey"` // 记录ID
CouponID int32 `json:"coupon_id" gorm:"column:coupon_id"` // 优惠券ID
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
Status CouponStatus `json:"status" gorm:"column:status"` // 使用状态0-未使用1-已使用
ExpireAt *time.Time `json:"expire_at,omitempty" gorm:"column:expire_at"` // 过期时间
UsedAt *time.Time `json:"used_at,omitempty" gorm:"column:used_at"` // 使用时间
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` // 创建时间
ID int32 `json:"id" gorm:"column:id;primaryKey"` // 记录ID
CouponID int32 `json:"coupon_id" gorm:"column:coupon_id"` // 优惠券ID
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
Status CouponUserStatus `json:"status" gorm:"column:status"` // 使用状态0-未使用1-已使用2-已禁用
ExpireAt *time.Time `json:"expire_at,omitempty" gorm:"column:expire_at"` // 过期时间
UsedAt *time.Time `json:"used_at,omitempty" gorm:"column:used_at"` // 使用时间
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` // 创建时间
Coupon *Coupon `json:"coupon,omitempty" gorm:"foreignKey:CouponID"`
User *User `json:"user,omitempty" gorm:"foreignKey:UserID"`

View File

@@ -91,6 +91,10 @@ func userRouter(api fiber.Router) {
bill := api.Group("/bill")
bill.Post("/list", handlers.ListBill)
// 余额变动
balance := api.Group("/balance")
balance.Post("/page", handlers.PageBalanceActivity)
// 公告
announcement := api.Group("/announcement")
announcement.Post("/list", handlers.ListAnnouncements)

View File

@@ -68,14 +68,24 @@ func (s *couponService) Update(data UpdateCouponData) error {
do = append(do, q.Coupon.Status.Value(int(*data.Status)))
}
if data.ExpireType != nil {
switch *data.ExpireType {
case m.CouponExpireTypeNever:
do = append(do, q.Coupon.ExpireAt.Null(), q.Coupon.ExpireIn.Null())
case m.CouponExpireTypeFixed:
if data.ExpireAt == nil {
return core.NewBizErr("expire_at 不能为空")
}
do = append(do, q.Coupon.ExpireAt.Value(*data.ExpireAt), q.Coupon.ExpireIn.Null())
case m.CouponExpireTypeRelative:
if data.ExpireIn == nil {
return core.NewBizErr("expire_in 不能为空")
}
do = append(do, q.Coupon.ExpireAt.Null(), q.Coupon.ExpireIn.Value(*data.ExpireIn))
}
do = append(do, q.Coupon.ExpireType.Value(int(*data.ExpireType)))
}
if data.ExpireAt != nil {
do = append(do, q.Coupon.ExpireAt.Value(*data.ExpireAt))
}
if data.ExpireIn != nil {
do = append(do, q.Coupon.ExpireIn.Value(*data.ExpireIn))
}
_, err := q.Coupon.Where(q.Coupon.ID.Eq(data.ID)).UpdateSimple(do...)
return err
@@ -98,6 +108,56 @@ func (s *couponService) Delete(id int32) error {
return err
}
// 发放优惠券
func (s *couponService) Assign(couponID int32, userID int32) error {
// 获取优惠券信息
coupon, err := q.Coupon.Where(q.Coupon.ID.Eq(couponID)).Take()
if errors.Is(err, gorm.ErrRecordNotFound) {
return core.NewBizErr("优惠券不存在")
}
if err != nil {
return core.NewBizErr("获取优惠券数据失败", err)
}
// 检查优惠券是否可用
// 1. 状态必须为正常
if coupon.Status != m.CouponStatusEnabled {
return core.NewBizErr("优惠券不可用")
}
// 2. 数量必须大于0
if coupon.Count <= 0 {
return core.NewBizErr("优惠券已发放完")
}
// 发放优惠券
err = q.Q.Transaction(func(q *q.Query) error {
// 创建用户优惠券记录
err := q.CouponUser.Create(&m.CouponUser{
UserID: userID,
CouponID: couponID,
Status: m.CouponUserStatusUnused,
})
if err != nil {
return err
}
// 扣减优惠券数量
_, err = q.Coupon.
Where(q.Coupon.ID.Eq(couponID), q.Coupon.Count_.Eq(coupon.Count)).
UpdateSimple(q.Coupon.Count_.Value(coupon.Count - 1))
if err != nil {
return err
}
return nil
})
if err != nil {
return core.NewBizErr("发放优惠券失败", err)
}
return nil
}
// GetUserCoupon 获取用户的指定优惠券
func (s *couponService) GetUserCoupon(uid int32, cuid int32, amount decimal.Decimal) (*m.CouponUser, error) {
// 获取优惠券