You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
5.2 KiB
Go
251 lines
5.2 KiB
Go
package award
|
|
|
|
import (
|
|
"context"
|
|
"joybuywork/internal/repository/cache"
|
|
"joybuywork/internal/repository/dao"
|
|
"joybuywork/internal/repository/dbcheck"
|
|
"joybuywork/internal/repository/model"
|
|
"joybuywork/internal/repository/mtype"
|
|
"joybuywork/internal/service/provider/stocks"
|
|
"joybuywork/internal/utils/merr"
|
|
)
|
|
|
|
const (
|
|
IssVerifyPointDeductStock = "DeductStock" // 扣除库存
|
|
IssVerifyPointDeductPreStock = "DeductSelectStock" // 扣除预备库存
|
|
IssVerifyPointRuleFilter = "RuleFilter" // 规则过滤
|
|
IssVerifyPointUnlock = "Unlock" // 解锁
|
|
)
|
|
|
|
type IssVerify struct {
|
|
ctx context.Context
|
|
be *merr.BusinessError
|
|
user *model.FissionUser
|
|
reward *model.FissionCampaignReward
|
|
|
|
unlimitStock bool // 不限制库存
|
|
|
|
hasFail bool // 是否校验失败
|
|
point string // 当前校验节点
|
|
err error // 错误信息
|
|
|
|
failDone []func() // 验证不通过要做一些操作,如:返还库存
|
|
}
|
|
|
|
// NewAwardIssVerify 奖品发放验证
|
|
func NewAwardIssVerify(ctx context.Context, user *model.FissionUser, reward *model.FissionCampaignReward) *IssVerify {
|
|
return &IssVerify{
|
|
ctx: ctx,
|
|
be: merr.NewBE(ctx),
|
|
user: user,
|
|
reward: reward,
|
|
unlimitStock: reward.IsThank == mtype.Yes ||
|
|
reward.Stock == -1 ||
|
|
reward.PropMark == mtype.FissionCampaignRewardPropMarkPoint,
|
|
}
|
|
}
|
|
|
|
// IsOK 校验结果
|
|
func (s *IssVerify) IsOK() (bool, error) {
|
|
if s.err != nil {
|
|
return false, s.err
|
|
}
|
|
|
|
if s.hasFail {
|
|
for _, f := range s.failDone {
|
|
f()
|
|
}
|
|
}
|
|
|
|
return !s.hasFail, nil
|
|
}
|
|
|
|
// PointOK 返回验证节点,如果错误,当前返回节点校验不通过
|
|
func (s *IssVerify) PointOK() (point string, ok bool, err error) {
|
|
if s.err != nil {
|
|
err = s.err
|
|
return
|
|
}
|
|
|
|
if s.hasFail {
|
|
for _, f := range s.failDone {
|
|
f()
|
|
}
|
|
point = s.point
|
|
return
|
|
}
|
|
|
|
ok = true
|
|
return
|
|
}
|
|
|
|
// DeductStock 扣除库存
|
|
func (s *IssVerify) DeductStock() (next *IssVerify) {
|
|
if s.err != nil || s.hasFail {
|
|
return s
|
|
}
|
|
|
|
s.point = IssVerifyPointDeductStock
|
|
|
|
reward := s.reward
|
|
|
|
stock, err := stocks.NewCampaignReward(s.ctx, reward.ID)
|
|
if err != nil {
|
|
s.err = err
|
|
return s.setVerify(false, err)
|
|
}
|
|
|
|
// 如果是谢谢参与奖,增加使用库存
|
|
if s.unlimitStock {
|
|
err = stock.AddUseStock(1)
|
|
if err != nil {
|
|
s.err = err
|
|
return s.setVerify(false, err)
|
|
}
|
|
|
|
s.failDone = append(s.failDone, func() {
|
|
// 还原库存
|
|
_ = stock.AddUseStock(-1)
|
|
})
|
|
|
|
return s.setVerify(true, nil)
|
|
}
|
|
|
|
ok, err := stock.DecrPoolAndAdd(reward.ID, 1)
|
|
if err != nil || !ok {
|
|
s.err = err
|
|
return s.setVerify(false, err)
|
|
}
|
|
|
|
s.failDone = append(s.failDone, func() {
|
|
// 还原库存
|
|
_, _ = stock.DecrPoolAndAdd(reward.ID, -1)
|
|
})
|
|
|
|
return s.setVerify(true, nil)
|
|
}
|
|
|
|
// DeductSelectStock 扣除选择库存
|
|
func (s *IssVerify) DeductSelectStock() (next *IssVerify) {
|
|
if s.err != nil || s.hasFail {
|
|
return s
|
|
}
|
|
|
|
s.point = IssVerifyPointDeductPreStock
|
|
|
|
reward := s.reward
|
|
|
|
stock, err := stocks.NewCampaignRewardSelect(s.ctx, reward.ID)
|
|
if err != nil {
|
|
s.err = err
|
|
return s.setVerify(false, err)
|
|
}
|
|
|
|
// 如果是谢谢参与奖,增加使用库存
|
|
if s.unlimitStock {
|
|
err = stock.AddUseStock(1)
|
|
if err != nil {
|
|
s.err = err
|
|
return s.setVerify(false, err)
|
|
}
|
|
|
|
s.failDone = append(s.failDone, func() {
|
|
// 还原库存
|
|
_ = stock.AddUseStock(-1)
|
|
})
|
|
|
|
return s.setVerify(true, nil)
|
|
}
|
|
|
|
ok, err := stock.DecrPoolAndAdd(reward.ID, 1)
|
|
if err != nil || !ok {
|
|
s.err = err
|
|
return s.setVerify(false, err)
|
|
}
|
|
|
|
s.failDone = append(s.failDone, func() {
|
|
// 还原库存
|
|
_, _ = stock.DecrPoolAndAdd(reward.ID, -1)
|
|
})
|
|
|
|
return s.setVerify(true, nil)
|
|
}
|
|
|
|
// RuleFilter 规则过滤
|
|
func (s *IssVerify) RuleFilter() (next *IssVerify) {
|
|
if s.err != nil || s.hasFail {
|
|
return s
|
|
}
|
|
|
|
s.point = IssVerifyPointRuleFilter
|
|
|
|
if s.reward.HasRule == mtype.No || s.reward.IsThank == mtype.Yes {
|
|
return s.setVerify(true, nil)
|
|
}
|
|
|
|
rule, err := cache.NewCampaignRewardRule(s.ctx).FindByRewardId(s.reward.ID)
|
|
if err != nil {
|
|
return s.setVerify(false, s.be.CacheError(err))
|
|
}
|
|
|
|
if rule == nil {
|
|
return s.setVerify(true, nil)
|
|
}
|
|
|
|
m := dao.FissionRewardRecord.SubTable(s.user.CampaignID)
|
|
if rule.CampaignLimit > 0 {
|
|
var count int64
|
|
count, err = m.WithContext(s.ctx).Where(m.UserID.Eq(s.user.ID), m.RewardID.Eq(s.reward.ID)).Count()
|
|
if err != nil {
|
|
return s.setVerify(false, s.be.MysqlError(err))
|
|
}
|
|
|
|
if count >= int64(rule.CampaignLimit) {
|
|
return s.setVerify(false, nil)
|
|
}
|
|
}
|
|
|
|
return s.setVerify(true, nil)
|
|
}
|
|
|
|
// Unlock 解锁
|
|
func (s *IssVerify) Unlock() (next *IssVerify) {
|
|
if s.err != nil || s.hasFail {
|
|
return s
|
|
}
|
|
|
|
s.point = IssVerifyPointUnlock
|
|
|
|
if s.reward.OpenTask == mtype.No || s.reward.IsThank == mtype.Yes {
|
|
return s.setVerify(true, nil)
|
|
}
|
|
|
|
cpnId, userId, rewardId := s.user.CampaignID, s.user.ID, s.reward.ID
|
|
m := dao.FissionUnlockReward
|
|
ulr, err := m.WithContext(s.ctx).Where(
|
|
m.CampaignID.Eq(cpnId),
|
|
m.UserID.Eq(userId),
|
|
m.RewardID.Eq(rewardId),
|
|
).Take()
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
s.err = err
|
|
return s.setVerify(false, err)
|
|
}
|
|
|
|
if ulr == nil {
|
|
return s.setVerify(false, nil)
|
|
}
|
|
|
|
return s.setVerify(true, nil)
|
|
}
|
|
|
|
// 设置验证信息
|
|
func (s *IssVerify) setVerify(ok bool, err error) *IssVerify {
|
|
s.err = err
|
|
if !ok {
|
|
s.hasFail = true
|
|
}
|
|
return s
|
|
}
|