package services import ( "errors" "fmt" "platform/pkg/u" "platform/web/core" m "platform/web/models" q "platform/web/queries" "time" "github.com/shopspring/decimal" "gorm.io/gen/field" "gorm.io/gorm" ) var Coupon = &couponService{} type couponService struct{} func (s *couponService) All() (result []*m.Coupon, err error) { return q.Coupon.Order(q.Coupon.CreatedAt.Desc()).Find() } func (s *couponService) Page(req *core.PageReq) (result []*m.Coupon, count int64, err error) { return q.Coupon.Order(q.Coupon.CreatedAt.Desc()).FindByPage(req.GetOffset(), req.GetLimit()) } func (s *couponService) Create(data CreateCouponData) error { return q.Coupon.Create(&m.Coupon{ Name: data.Name, Amount: data.Amount, MinAmount: data.MinAmount, Count: int32(u.Else(data.Count, 1)), Status: u.Else(data.Status, m.CouponStatusEnabled), ExpireType: u.Else(data.ExpireType, m.CouponExpireTypeNever), ExpireAt: data.ExpireAt, ExpireIn: data.ExpireIn, }) } type CreateCouponData struct { Name string `json:"name" validate:"required"` Amount decimal.Decimal `json:"amount" validate:"required"` MinAmount decimal.Decimal `json:"min_amount"` Count *int `json:"count"` Status *m.CouponStatus `json:"status"` ExpireType *m.CouponExpireType `json:"expire_type"` ExpireAt *time.Time `json:"expire_at"` ExpireIn *int `json:"expire_in"` } func (s *couponService) Update(data UpdateCouponData) error { do := make([]field.AssignExpr, 0) if data.Name != nil { do = append(do, q.Coupon.Name.Value(*data.Name)) } if data.Amount != nil { do = append(do, q.Coupon.Amount.Value(*data.Amount)) } if data.MinAmount != nil { do = append(do, q.Coupon.MinAmount.Value(*data.MinAmount)) } if data.Count != nil { do = append(do, q.Coupon.Count_.Value(int32(*data.Count))) } if data.Status != nil { do = append(do, q.Coupon.Status.Value(int(*data.Status))) } if data.ExpireType != nil { 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 } type UpdateCouponData struct { ID int32 `json:"id" validate:"required"` Name *string `json:"name"` Amount *decimal.Decimal `json:"amount"` MinAmount *decimal.Decimal `json:"min_amount"` Count *int `json:"count"` Status *m.CouponStatus `json:"status"` ExpireType *m.CouponExpireType `json:"expire_type"` ExpireAt *time.Time `json:"expire_at"` ExpireIn *int `json:"expire_in"` } func (s *couponService) Delete(id int32) error { _, err := q.Coupon.Where(q.Coupon.ID.Eq(id)).UpdateColumn(q.Coupon.DeletedAt, time.Now()) return err } // GetUserCoupon 获取用户的指定优惠券 func (s *couponService) GetUserCoupon(uid int32, cuid int32, amount decimal.Decimal) (*m.CouponUser, error) { // 获取优惠券 assigned, err := q.CouponUser.Joins(q.CouponUser.Coupon).Where( q.CouponUser.ID.Eq(cuid), q.CouponUser.UserID.Eq(uid), q.CouponUser.Status.Eq(int(m.CouponUserStatusUnused)), q.CouponUser.ExpireAt.Gt(time.Now()), ).Take() if errors.Is(err, gorm.ErrRecordNotFound) { return nil, core.NewBizErr("优惠券不存在或已失效") } if err != nil { return nil, core.NewBizErr("获取优惠券数据失败", err) } // 检查最小使用额度 if amount.Cmp(assigned.Coupon.MinAmount) < 0 { return nil, core.NewBizErr(fmt.Sprintf("使用此优惠券的最小额度为 %s", assigned.Coupon.MinAmount)) } return assigned, nil } func (s *couponService) UseCoupon(q *q.Query, cuid int32) error { _, err := q.CouponUser. Where( q.CouponUser.ID.Eq(cuid), q.CouponUser.Status.Eq(int(m.CouponUserStatusUnused)), ). UpdateSimple( q.CouponUser.Status.Value(int(m.CouponUserStatusUsed)), q.CouponUser.UsedAt.Value(time.Now()), ) return err }