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.
718 lines
15 KiB
Go
718 lines
15 KiB
Go
package players
|
|
|
|
import (
|
|
"context"
|
|
"joybuywork/internal/app"
|
|
"joybuywork/internal/consts"
|
|
"joybuywork/internal/consts/ckey"
|
|
"joybuywork/internal/plugins/jsonm"
|
|
"joybuywork/internal/repository/cache"
|
|
"joybuywork/internal/repository/dao"
|
|
"joybuywork/internal/repository/dbcheck"
|
|
"joybuywork/internal/repository/model"
|
|
"joybuywork/internal/repository/mtype"
|
|
"joybuywork/internal/repository/withdefault"
|
|
"joybuywork/internal/service/cmm"
|
|
"joybuywork/internal/service/provider"
|
|
"joybuywork/internal/service/provider/award"
|
|
"joybuywork/internal/service/provider/fissionaction"
|
|
"joybuywork/internal/utils"
|
|
"fmt"
|
|
"time"
|
|
|
|
"gits.branchcn.com/backend/joybuywork/proto/go_proto/workerr"
|
|
)
|
|
|
|
// Qa 现金转盘交互逻辑
|
|
type Qa struct {
|
|
Player
|
|
player *model.FissionQa
|
|
conf *model.FissionCampaignQa
|
|
|
|
fissionPlayerSetInitOnceKey string
|
|
}
|
|
|
|
func NewQa(ctx context.Context, user *model.FissionUser, fissionId int64, opts ...Option) (player *Qa, err error) {
|
|
player = &Qa{}
|
|
|
|
err = player.Init(ctx, user, fissionId, opts...)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = player.initPlayer()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// ReceiveReward 手动领取奖励
|
|
func (s *Qa) ReceiveReward(taskRewards ...*model.FissionUserTaskReward) (chance int32, reward *award.RewardRes, err error) {
|
|
|
|
err = s._receiveReward(taskRewards, func(tasks []*model.FissionCampaignTask, records []*award.RewardRes) error {
|
|
chance, err = s.taskFinish(tasks, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(records) == 0 {
|
|
return nil
|
|
}
|
|
|
|
reward = records[0]
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// FinishTask 完成任务
|
|
func (s *Qa) FinishTask(tasks ...*model.FissionCampaignTask) (err error) {
|
|
_, err = s.taskFinish(tasks, true)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// 完成任务
|
|
func (s *Qa) taskFinish(tasks []*model.FissionCampaignTask, checkManual bool) (chance int32, err error) {
|
|
player := s.GetPlayer()
|
|
|
|
var logs []*model.FissionQaLog
|
|
for _, task := range tasks {
|
|
if checkManual && task.AwardMode == mtype.FissionCampaignTaskAwardModeManual {
|
|
continue
|
|
}
|
|
|
|
switch task.PropMark {
|
|
case mtype.FissionCampaignTaskPropMarkChance:
|
|
chance += task.Chance
|
|
}
|
|
|
|
val, _ := jsonm.MarshalToString(mtype.AnswerLogVal{
|
|
TaskId: task.ID,
|
|
Chance: task.Chance,
|
|
})
|
|
|
|
log := withdefault.FissionQaLog(&model.FissionQaLog{
|
|
UserID: player.UserID,
|
|
CampaignID: player.CampaignID,
|
|
QaID: player.ID,
|
|
Type: mtype.FissionQaLogTypeAdd,
|
|
Val: val,
|
|
})
|
|
|
|
switch task.TaskType {
|
|
case mtype.FissionCampaignTaskTypeRegister:
|
|
log.Source = mtype.FissionLogSourceRegister
|
|
case mtype.FissionCampaignTaskTypeInstall:
|
|
log.Source = mtype.FissionLogSourceInstall
|
|
case mtype.FissionCampaignTaskTypeCondAll:
|
|
log.Source = utils.Ternary[string](task.AwardMode == mtype.FissionCampaignTaskAwardModeManual, mtype.FissionLogSourceManualCondAll, mtype.FissionLogSourceCondAll)
|
|
case mtype.FissionCampaignTaskTypeCondOne:
|
|
log.Source = utils.Ternary[string](task.AwardMode == mtype.FissionCampaignTaskAwardModeManual, mtype.FissionLogSourceManualCondOne, mtype.FissionLogSourceCondOne)
|
|
}
|
|
|
|
logs = append(logs, log)
|
|
}
|
|
|
|
if chance == 0 {
|
|
return
|
|
}
|
|
|
|
m := s.GetDao().FissionQa
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(player.ID)).UpdateSimple(m.TaskChance.Add(chance), m.Chance.Add(chance))
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = s._addLog(logs...)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
type QaAnswer struct {
|
|
QID int64 `json:"qid"`
|
|
AID []int64 `json:"aid"`
|
|
}
|
|
|
|
func (s *Qa) Answer(submits []*QaAnswer) (score, qaRightNum int32, win bool, reward *model.FissionCampaignReward, record *model.FissionRewardRecord, info provider.RewardAutoLang, err error) {
|
|
player := s.GetPlayer()
|
|
|
|
if player.Chance <= 0 {
|
|
err = workerr.CChanceNoneError
|
|
return
|
|
}
|
|
|
|
//答卷
|
|
var qaIds []int64
|
|
answer := make(map[int64]map[int64]struct{})
|
|
for _, v := range submits {
|
|
qaIds = append(qaIds, v.QID)
|
|
answer[v.QID] = map[int64]struct{}{}
|
|
for _, v1 := range v.AID {
|
|
answer[v.QID][v1] = struct{}{}
|
|
}
|
|
}
|
|
|
|
var qaNum = int32(len(qaIds))
|
|
var qaGroupId int64
|
|
|
|
switch s.cpn.FissionID {
|
|
case consts.IdPrizeAnswer:
|
|
var checkGroup bool
|
|
temp, _ := cache.NewFissionTemp(s.Ctx).FindById(s.cpn.TemplateID)
|
|
if temp != nil {
|
|
group, _ := cache.NewFissionTempGroup(s.Ctx).FindById(temp.GroupID)
|
|
checkGroup = group.Mark == "answer_tmb"
|
|
}
|
|
|
|
if !checkGroup {
|
|
score, err = s._prizeAnswerScore(qaIds, answer)
|
|
if err != nil {
|
|
return
|
|
}
|
|
} else {
|
|
qaNum, qaGroupId, err = s._getQaGroup()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
score, qaRightNum, err = s._qaScore(qaNum, qaGroupId, qaIds, answer)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
case consts.IdQa, consts.IdQaVideo, consts.IdQaAudio:
|
|
qaNum, qaGroupId, err = s._getQaGroup()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
score, qaRightNum, err = s._qaScore(qaNum, qaGroupId, qaIds, answer)
|
|
if err != nil {
|
|
return
|
|
}
|
|
default:
|
|
return
|
|
}
|
|
|
|
answerSb, _ := jsonm.MarshalToString(submits)
|
|
win, reward, record, info, err = s._getReward(answerSb, score)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
playerM := s.GetDao().FissionQa
|
|
_, err = playerM.WithContext(s.Ctx).Where(playerM.ID.Eq(player.ID)).UpdateSimple(playerM.Chance.Sub(1))
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
val, _ := jsonm.MarshalToString(mtype.AnswerLogVal{
|
|
Chance: 1,
|
|
RewardId: record.RewardID,
|
|
RecordId: record.ID,
|
|
Score: score,
|
|
})
|
|
|
|
log := withdefault.FissionQaLog(&model.FissionQaLog{
|
|
UserID: player.UserID,
|
|
CampaignID: player.CampaignID,
|
|
QaID: player.ID,
|
|
Type: mtype.FissionQaLogTypeDecr,
|
|
Source: mtype.FissionLogSourceAnswer,
|
|
Val: val,
|
|
})
|
|
|
|
err = s._addLog(log)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
fissionaction.NewMarkPoint(s.Ctx).InApp(s.user).SubmitQa(time.Now().Unix(), qaGroupId, qaNum, fmt.Sprint(score))
|
|
|
|
return
|
|
}
|
|
|
|
// Sign 签到
|
|
func (s *Qa) Sign() (err error) {
|
|
player, conf := s.GetPlayer(), s.GetConf()
|
|
if conf.DayChance == 0 {
|
|
return
|
|
}
|
|
|
|
signOk, lastSign := s._lastSign(player.LastSign)
|
|
if !signOk {
|
|
return
|
|
}
|
|
|
|
playerM := s.GetDao().FissionQa
|
|
_, err = playerM.WithContext(s.Ctx).Where(playerM.ID.Eq(player.ID)).UpdateSimple(
|
|
playerM.Chance.Add(conf.DayChance),
|
|
playerM.DayChance.Add(conf.DayChance),
|
|
playerM.LastSign.Value(lastSign),
|
|
)
|
|
if err != nil {
|
|
return s.BE().MysqlError(err)
|
|
}
|
|
|
|
val, _ := jsonm.MarshalToString(mtype.AnswerLogVal{
|
|
Chance: conf.DayChance,
|
|
})
|
|
|
|
log := withdefault.FissionQaLog(&model.FissionQaLog{
|
|
UserID: player.UserID,
|
|
CampaignID: player.CampaignID,
|
|
QaID: player.ID,
|
|
Type: mtype.FissionQaLogTypeAdd,
|
|
Source: mtype.FissionLogSourceSign,
|
|
Val: val,
|
|
})
|
|
|
|
err = s._addLog(log)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
s.player.Chance = player.Chance + conf.DayChance
|
|
|
|
return
|
|
}
|
|
|
|
// SetInit 获得初始次数
|
|
func (s *Qa) SetInit() (err error) {
|
|
player, conf := s.GetPlayer(), s.GetConf()
|
|
if player.SetInit == mtype.Yes || conf.InitChance == 0 {
|
|
return
|
|
}
|
|
|
|
key := s.fissionPlayerSetInitOnceKey
|
|
|
|
if !app.NewRedisLock(s.Ctx, key).SoftLock() {
|
|
return
|
|
}
|
|
|
|
m := s.GetDao().FissionQa
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(player.ID)).UpdateSimple(m.SetInit.Value(mtype.Yes), m.Chance.Add(conf.InitChance))
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
val, _ := jsonm.MarshalToString(mtype.AnswerLogVal{
|
|
Chance: conf.InitChance,
|
|
})
|
|
|
|
log := withdefault.FissionQaLog(&model.FissionQaLog{
|
|
UserID: player.UserID,
|
|
CampaignID: player.CampaignID,
|
|
QaID: player.ID,
|
|
Type: mtype.FissionQaLogTypeAdd,
|
|
Source: mtype.FissionLogSourceInit,
|
|
Val: val,
|
|
})
|
|
|
|
err = s._addLog(log)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
s.player.Chance += conf.InitChance
|
|
|
|
return
|
|
}
|
|
|
|
// GetConf 获取玩法配置
|
|
func (s *Qa) GetConf() *model.FissionCampaignQa {
|
|
if s.conf == nil {
|
|
s.conf, _ = cache.NewCampaignQa(s.Ctx).FindByCampaignId(s.user.CampaignID)
|
|
}
|
|
|
|
return s.conf
|
|
}
|
|
|
|
// GetPlayer 获取玩家基础数据
|
|
func (s *Qa) GetPlayer() *model.FissionQa {
|
|
return s.player
|
|
}
|
|
|
|
// 玩家
|
|
func (s *Qa) initPlayer() (err error) {
|
|
player, err := s._dbFirst()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
defer func() {
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
s.player = player
|
|
s.fissionPlayerSetInitOnceKey = ckey.FissionPlayerSetInitOnce(player.UserID)
|
|
}()
|
|
|
|
if player != nil {
|
|
return
|
|
}
|
|
|
|
player, err = s.firstOrCreate()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 创建玩家基础数据
|
|
func (s *Qa) firstOrCreate() (player *model.FissionQa, err error) {
|
|
lc := app.NewFollower(s.Ctx, ckey.FissionUserCreatePlayerOnce(s.user.ID)).Lock()
|
|
defer lc.Release()
|
|
if lc.Error() != nil {
|
|
err = lc.Error()
|
|
return
|
|
}
|
|
|
|
player, err = s._dbFirst()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if player != nil {
|
|
return
|
|
}
|
|
|
|
return s.createPlayer()
|
|
}
|
|
|
|
// 数据库查询
|
|
func (s *Qa) _dbFirst() (*model.FissionQa, error) {
|
|
playerM := dao.FissionQa
|
|
player, err := playerM.WithContext(s.Ctx).Where(playerM.UserID.Eq(s.user.ID)).Take()
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
return nil, s.BE().MysqlError(err)
|
|
}
|
|
|
|
return player, nil
|
|
}
|
|
|
|
// 创建一个玩家
|
|
func (s *Qa) createPlayer() (player *model.FissionQa, err error) {
|
|
playerM := dao.FissionQa
|
|
player = withdefault.FissionQa(&model.FissionQa{
|
|
CampaignID: s.user.CampaignID,
|
|
UserID: s.user.ID,
|
|
})
|
|
|
|
err = playerM.WithContext(s.Ctx).Create(player)
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Qa) _addLog(logs ...*model.FissionQaLog) (err error) {
|
|
err = s.GetDao().FissionQaLog.WithContext(s.Ctx).Create(logs...)
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Qa) _prizeAnswerScore(qaIds []int64, answer map[int64]map[int64]struct{}) (score int32, err error) {
|
|
conf := s.GetConf()
|
|
|
|
qm := s.GetDao().FissionCampaignQaQuestion
|
|
ql, err := qm.WithContext(s.Ctx).Where(qm.ID.In(qaIds...), qm.QaID.Eq(conf.ID), qm.IsDel.Eq(mtype.No)).Find()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
var qids []int64
|
|
var scoreMap = make(map[int64]int32)
|
|
for _, v := range ql {
|
|
qids = append(qids, v.ID)
|
|
scoreMap[v.ID] = v.Score
|
|
}
|
|
|
|
opm := s.GetDao().FissionCampaignQaOption
|
|
opl, err := opm.WithContext(s.Ctx).Where(opm.QuestionID.In(qids...), opm.IsRight.Eq(mtype.Yes), opm.IsDel.Eq(mtype.No)).Find()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
//问题
|
|
question := map[int64][]int64{}
|
|
for _, v := range opl {
|
|
question[v.QuestionID] = append(question[v.QuestionID], v.ID)
|
|
}
|
|
|
|
for qid, aid := range question {
|
|
sub, ok := answer[qid]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
var allRight = true
|
|
for _, v := range aid {
|
|
_, ok1 := sub[v]
|
|
if !ok1 {
|
|
allRight = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if allRight {
|
|
score += scoreMap[qid]
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Qa) _getReward(answer string, score int32) (win bool, reward *model.FissionCampaignReward, record *model.FissionRewardRecord, info provider.RewardAutoLang, err error) {
|
|
m := s.GetDao().FissionCampaignReward
|
|
rl, err := cmm.NewCMM(s.Ctx, s.GetDao()).UserAppReward(s.user, m.Score, m.ID)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var thinkMap = make(map[int64]*model.FissionCampaignReward)
|
|
var rewardMap = make(map[int32][]*model.FissionCampaignReward)
|
|
var minScore int32 = -1
|
|
for _, v := range rl {
|
|
if v.IsThank == mtype.Yes {
|
|
thinkMap[v.ID] = v
|
|
} else {
|
|
rewardMap[v.Score] = append(rewardMap[v.Score], v)
|
|
|
|
if minScore == -1 {
|
|
minScore = v.Score
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
var stepScore int32
|
|
var scoreRewards []*model.FissionCampaignReward
|
|
for sc, rewards := range rewardMap {
|
|
|
|
if sc > score || sc <= stepScore {
|
|
continue
|
|
}
|
|
|
|
stepScore = sc
|
|
scoreRewards = rewards
|
|
}
|
|
|
|
if len(scoreRewards) == 1 {
|
|
reward = scoreRewards[0]
|
|
var deOk bool
|
|
deOk, err = award.NewAwardIssVerify(s.Ctx, s.user, reward).DeductStock().RuleFilter().IsOK()
|
|
|
|
if deOk {
|
|
win = score >= minScore
|
|
record, info, err = s._answerReward(reward, answer, score)
|
|
return
|
|
}
|
|
} else {
|
|
var scoreRewardsMap = make(map[int64]*model.FissionCampaignReward)
|
|
for _, v := range scoreRewards {
|
|
scoreRewardsMap[v.ID] = v
|
|
}
|
|
|
|
key := ckey.FissionUserRewards(s.user.ID)
|
|
var ids []int64
|
|
idStr := app.Redis.Cache.Get(s.Ctx, key).Val()
|
|
if idStr != "" {
|
|
ids = utils.SplitToInt64(idStr, consts.JoinComma)
|
|
}
|
|
|
|
if len(ids) >= len(scoreRewards) {
|
|
ids = []int64{}
|
|
}
|
|
|
|
var next = make(map[int64]struct{})
|
|
for _, v := range ids {
|
|
next[v] = struct{}{}
|
|
}
|
|
|
|
for _, v := range scoreRewardsMap {
|
|
reward = v
|
|
|
|
if _, ok := next[reward.ID]; ok {
|
|
continue
|
|
}
|
|
|
|
var deOk bool
|
|
deOk, err = award.NewAwardIssVerify(s.Ctx, s.user, reward).DeductStock().RuleFilter().IsOK()
|
|
|
|
if deOk {
|
|
win = score >= minScore
|
|
record, info, err = s._answerReward(reward, answer, score)
|
|
break
|
|
}
|
|
|
|
reward = nil
|
|
}
|
|
|
|
if reward != nil {
|
|
ids = append(ids, reward.ID)
|
|
idStr = utils.Join(ids, consts.JoinComma)
|
|
app.Redis.Cache.SetEX(s.Ctx, key, idStr, consts.TimeDay*2)
|
|
return
|
|
}
|
|
|
|
}
|
|
|
|
for _, v := range thinkMap {
|
|
reward = v
|
|
win = score >= minScore
|
|
record, info, err = s._answerReward(v, answer, score)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 答题奖品
|
|
func (s *Qa) _answerReward(reward *model.FissionCampaignReward, answer string, score int32) (record *model.FissionRewardRecord, info provider.RewardAutoLang, err error) {
|
|
record, info, _, err = award.NewAwardReward(s.Ctx, s.GetDao(), s.cpn.ProjectID, s.user).One(
|
|
reward,
|
|
true,
|
|
award.RewardRecordAnswer(answer, score),
|
|
)
|
|
return
|
|
}
|
|
|
|
func (s *Qa) _qaScore(qal int32, qaGroupId int64, qaIds []int64, answer map[int64]map[int64]struct{}) (score, qaRightNum int32, err error) {
|
|
|
|
qam := s.GetDao().LibraryQa
|
|
ql, err := qam.WithContext(s.Ctx).Where(qam.GroupID.Eq(qaGroupId), qam.ID.In(qaIds...), qam.IsDel.Eq(mtype.No)).Find()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
l := int32(len(ql))
|
|
|
|
if l == 0 {
|
|
return
|
|
}
|
|
|
|
if l < qal {
|
|
qal = l
|
|
}
|
|
|
|
qaScore := 100 / qal
|
|
|
|
var qids []int64
|
|
var scoreMap = make(map[int64]int32)
|
|
for _, v := range ql {
|
|
qids = append(qids, v.ID)
|
|
scoreMap[v.ID] = qaScore
|
|
}
|
|
|
|
opm := s.GetDao().LibraryQaOption
|
|
opl, err := opm.WithContext(s.Ctx).Where(opm.QaID.In(qids...), opm.IsRight.Eq(mtype.Yes), opm.IsDel.Eq(mtype.No)).Find()
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
//问题
|
|
question := map[int64][]int64{}
|
|
for _, v := range opl {
|
|
question[v.QaID] = append(question[v.QaID], v.ID)
|
|
}
|
|
|
|
for qid, aid := range question {
|
|
sub, ok := answer[qid]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
var allRight = true
|
|
for _, v := range aid {
|
|
_, ok1 := sub[v]
|
|
if !ok1 {
|
|
allRight = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if allRight {
|
|
score += scoreMap[qid]
|
|
qaRightNum++
|
|
}
|
|
}
|
|
|
|
if qaRightNum >= qal {
|
|
score = 100
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Qa) _getQaGroup() (qaNum int32, qaGroupId int64, err error) {
|
|
cpn, qa := s.cpn, s.GetConf()
|
|
|
|
qaNum, qaGroupId = qa.QaNum, qa.QaGroupID
|
|
|
|
spLang := cpn.GetLangMarks()
|
|
if len(spLang) == 1 {
|
|
return
|
|
}
|
|
langMark := utils.NotExistGetFirst(s.user.LangMark, spLang)
|
|
|
|
if langMark == spLang[0] {
|
|
return
|
|
}
|
|
|
|
lang, err := cache.NewCampaignLang(s.Ctx).FindByCampaignId(cpn.ID, langMark)
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
if lang == nil {
|
|
return
|
|
}
|
|
|
|
qaGroup := lang.GetQaGroup()
|
|
if qaGroup == nil {
|
|
return
|
|
}
|
|
|
|
group, err := cache.NewLibraryQaGroup(s.Ctx).FindByHashId(qaGroup.QaGroupId)
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
if group == nil {
|
|
return
|
|
}
|
|
|
|
return qaGroup.QaNum, group.ID, nil
|
|
}
|