package services import ( "errors" "fmt" "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.Find() } func (s *couponService) Page(req *core.PageReq) (result []*m.Coupon, count int64, err error) { return q.Coupon.FindByPage(req.GetOffset(), req.GetLimit()) } func (s *couponService) Create(data CreateCouponData) error { return q.Coupon.Create(&m.Coupon{ UserID: data.UserID, Code: data.Code, Remark: data.Remark, Amount: data.Amount, MinAmount: data.MinAmount, Status: m.CouponStatusUnused, ExpireAt: data.ExpireAt, }) } type CreateCouponData struct { UserID *int32 `json:"user_id"` Code string `json:"code" validate:"required"` Remark *string `json:"remark"` Amount decimal.Decimal `json:"amount" validate:"required"` MinAmount decimal.Decimal `json:"min_amount"` ExpireAt *time.Time `json:"expire_at"` } func (s *couponService) Update(data UpdateCouponData) error { do := make([]field.AssignExpr, 0) if data.UserID != nil { do = append(do, q.Coupon.UserID.Value(*data.UserID)) } if data.Code != nil { do = append(do, q.Coupon.Code.Value(*data.Code)) } if data.Remark != nil { do = append(do, q.Coupon.Remark.Value(*data.Remark)) } 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.Status != nil { do = append(do, q.Coupon.Status.Value(int(*data.Status))) } if data.ExpireAt != nil { do = append(do, q.Coupon.ExpireAt.Value(*data.ExpireAt)) } _, err := q.Coupon.Where(q.Coupon.ID.Eq(data.ID)).UpdateSimple(do...) return err } type UpdateCouponData struct { ID int32 `json:"id" validate:"required"` UserID *int32 `json:"user_id"` Code *string `json:"code"` Remark *string `json:"remark"` Amount *decimal.Decimal `json:"amount"` MinAmount *decimal.Decimal `json:"min_amount"` Status *m.CouponStatus `json:"status"` ExpireAt *time.Time `json:"expire_at"` } func (s *couponService) Delete(id int32) error { _, err := q.Coupon.Where(q.Coupon.ID.Eq(id)).UpdateColumn(q.Coupon.DeletedAt, time.Now()) return err } func (s *couponService) GetCouponAvailableByCode(code string, amount decimal.Decimal, uid *int32) (*m.Coupon, error) { // 获取优惠券 coupon, err := q.Coupon.Where( q.Coupon.Code.Eq(code), q.Coupon.Status.Eq(int(m.CouponStatusUnused)), q.Coupon. Where(q.Coupon.ExpireAt.Gt(time.Now())). Or(q.Coupon.ExpireAt.IsNull()), ).Take() if errors.Is(err, gorm.ErrRecordNotFound) { return nil, core.NewBizErr("优惠券不存在或已失效") } if err != nil { return nil, core.NewBizErr("获取优惠券数据失败", err) } // 检查最小使用额度 if amount.Cmp(coupon.MinAmount) < 0 { return nil, core.NewBizErr(fmt.Sprintf("使用此优惠券的最小额度为 %s", coupon.MinAmount)) } // 检查所属 if coupon.UserID != nil { if uid == nil { return nil, core.NewBizErr("检查优惠券所属用户失败") } if *coupon.UserID != *uid { return nil, core.NewBizErr("优惠券不属于当前用户") } } return coupon, nil } func (s *couponService) UseCoupon(q *q.Query, id int32) error { _, err := q.Coupon. Where( q.Coupon.ID.Eq(id), q.Coupon.Status.Eq(int(m.CouponStatusUnused)), q.Coupon.ExpireAt.Gt(time.Now()), ). UpdateSimple( q.Coupon.Status.Value(int(m.CouponStatusUsed)), ) return err }