Files
go-common/app/service/main/workflow/service/challenge.go
2019-04-22 18:49:16 +08:00

381 lines
14 KiB
Go

package service
import (
"context"
"database/sql"
"errors"
"fmt"
"strings"
"time"
arc "go-common/app/service/main/archive/api"
"go-common/app/service/main/workflow/model"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
const (
_inGroupSQL = "INSERT INTO workflow_group(oid,business,rid,tid,lasttime,count,handling) VALUE(?,?,?,?,?,1,1) ON DUPLICATE KEY UPDATE lasttime=?,state=?,count=count+1,handling=handling+1"
_inGroupSQL3 = "INSERT INTO workflow_group(oid,business,fid,rid,eid,score,tid,lasttime,count,handling) VALUES(?,?,?,?,?,?,?,?,1,1) ON DUPLICATE KEY UPDATE lasttime=?,state=?,count=count+1,handling=handling+1"
//_inBusiness = "INSERT INTO workflow_business(oid,typeid,business,title,content,mid,extra,cid,gid) VALUES(?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE typeid=values(typeid),title=values(title),content=values(content),extra=values(extra)"
_inBusiness3 = "INSERT INTO workflow_business(oid,typeid,business,title,content,mid,extra,cid,gid) VALUES(?,?,?,?,?,?,?,?,?)"
_upBusiness3 = "UPDATE workflow_business SET typeid=?, title=?, content=?, extra=? WHERE gid = ?"
)
// AddChallenge add challenge
func (s *Service) AddChallenge(c context.Context, ap *model.ChallengeParam) (row int64, err error) {
var (
lasttime = time.Now()
apl model.Group
chall *model.Challenge
attach *model.Attachment
)
tx := s.dao.DB.Begin()
if tx.Error != nil {
return
}
if tx.Error != nil {
log.Error("s.dao.AddGroup(%d,%d,%d,%v) error(%v)", ap.Oid, ap.Business, ap.Tid, lasttime, err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("s.dao.AddGroup(%v,%v) rollback error(%v)", ap, lasttime, err1)
}
}
}()
var rid int64
if tag, ok := s.tagsCache.TagMap3Tid[int64(ap.Business)][int64(ap.Tid)]; !ok {
log.Error("not found tag bid(%d) tid(%d)", ap.Business, ap.Tid)
} else {
rid = tag.RID
}
if err = tx.Exec(_inGroupSQL, ap.Oid, ap.Business, rid, ap.Tid, lasttime, lasttime, model.StateTypePending).Error; err != nil {
log.Error("tx.Raw(%d,%d,%d,%v) error(%v)", ap.Oid, ap.Business, ap.Tid, lasttime, err)
return
}
if err = tx.Where("oid=? AND business=?", ap.Oid, ap.Business).Find(&apl).Error; err != nil {
log.Error("tx.Where(%d,%d).Find() error(%v)", ap.Oid, ap.Business, err)
return
}
chall = &model.Challenge{
Tid: ap.Tid,
Gid: apl.ID,
Oid: ap.Oid,
Mid: ap.Mid,
Desc: ap.Desc,
MetaData: ap.MetaData,
Business: ap.Business,
BusinessState: ap.BusinessState,
Adminid: ap.AdminID,
Assignee: ap.AssigneeID,
}
chall.SetState(uint32(0), ap.Role)
if err = tx.Create(chall).Error; err != nil {
log.Error("tx.Create(%+v) error(%v)", chall, err)
return
}
row = int64(chall.ID)
for _, path := range ap.Attachments {
attach = &model.Attachment{Cid: chall.ID, Path: path}
if err = tx.Create(&attach).Error; err != nil {
log.Error("tx.Create(%+v) error(%v)", attach, err)
return
}
}
// 刷新稿件信息
if ap.Business == 1 {
in := &arc.ArcRequest{
Aid: ap.Oid,
}
var res *arc.ArcReply
if res, err = s.arcClient.Arc(c, in); err != nil {
log.Error("s.arcClient.Arc(%d) error(%v)", ap.Oid, err)
return
}
ap.BusinessTypeid = res.Arc.TypeID
ap.BusinessMid = res.Arc.Author.Mid
ap.BusinessTitle = res.Arc.Title
ap.BusinessContent = res.Arc.Desc
}
if ap.CheckBusiness() {
bus := &model.Business{}
if err = tx.Table("workflow_business").Where("gid = ?", apl.ID).Find(bus).Error; err != nil {
if err != gorm.ErrRecordNotFound {
log.Error("s.AddChallenge tx.Where error(%v)", err)
return
}
if err = tx.Exec(_inBusiness3, ap.Oid, ap.BusinessTypeid, ap.Business, ap.BusinessTitle, ap.BusinessContent, ap.BusinessMid, ap.BusinessExtra, chall.ID, apl.ID).Error; err != nil {
log.Error("tx.Exec(%s) params(oid=%d,typeid=%d,business=%d,title=%s,content=%s,mid=%d,extra=%s,cid=%d,gid=%d) error(%v)", _inBusiness3, ap.Oid, ap.BusinessTypeid, ap.Business, ap.BusinessTitle, ap.BusinessContent, ap.BusinessMid, ap.BusinessExtra, chall.ID, apl.ID, err)
return
}
} else {
if err = tx.Exec(_upBusiness3, ap.BusinessTypeid, ap.BusinessTitle, ap.BusinessContent, ap.BusinessExtra, apl.ID).Error; err != nil {
log.Error("tx.Exec(%s) params(typeid=%d,title=%s,content=%s,extra=%s) error(%v)", _upBusiness3, ap.BusinessTypeid, ap.BusinessTitle, ap.BusinessContent, ap.BusinessExtra, err)
}
}
}
if err = tx.Commit().Error; err != nil {
log.Error("tx.Commit() err(%v)", err)
return
}
// upsert
if apl.Count <= 1 {
s.cache.Do(context.Background(), func(c context.Context) {
if err = s.dao.UpdateUserTag(c, int64(apl.ID), ap.Tid); err != nil {
log.Error("s.dao.UpdateUserTag gid:%d error:%v", apl.ID, err)
}
})
}
return
}
// UpChallengeState update challenge business state by mid && id && business
func (s *Service) UpChallengeState(c context.Context, id int32, mid int64, business, role, state int8) (err error) {
if role != model.AuditRole && role != model.CustomerServiceRole {
err = errors.New("UntreatedChallenge Unknown Role")
log.Error("s.dao.UpChallengeState(%d,%d,%d,%d,%d) error(%v)", id, mid, business, role, state, err)
return
}
chall := &model.Challenge{}
if err = s.dao.DB.Where("id=? and mid=? and business=?", id, mid, business).Find(chall).Error; err != nil {
log.Error("s.dao.UpChallengeState(%d,%d,%d,%d,%d) error(%v)", id, mid, business, role, state, err)
return
}
chall.SetState(uint32(state), uint8(role))
if err = s.dao.DB.Model(&model.Challenge{}).Where("id=? and mid=? and business=?", id, mid, business).Update("dispatch_state", chall.DispatchState).Error; err != nil {
log.Error("s.dao.DB.UpState(%d,%d,%d,%d,%d) error(%v)", id, mid, business, role, state, err)
return
}
return
}
// CloseChallenge set challenge business state closed by challenge id
func (s *Service) CloseChallenge(c context.Context, id int32, business, role, businessState int8, note string) (err error) {
if role != model.AuditRole && role != model.CustomerServiceRole {
err = errors.New("UntreatedChallenge Unknown Role")
log.Error("s.dao.CloseChallenge(%d,%d) error(%v)", id, role, err)
return
}
chall := &model.Challenge{}
if err = s.dao.DB.Where("id=? and business=?", id, business).Find(chall).Error; err != nil {
log.Error("s.dao.Challenge(%d,%d) error(%v)", id, business, err)
return
}
chall.SetState(uint32(model.StateClose), uint8(role))
if err = s.dao.DB.Model(&model.Challenge{}).Where("id=? and business=?", id, business).Update("dispatch_state", chall.DispatchState).Error; err != nil {
log.Error("s.dao.UpChallengeState(%d) error(%v)", id, err)
return
}
changeLog := &model.Log{AdminID: chall.Adminid, Oid: chall.Oid, Business: chall.Business, Target: chall.ID, Module: 1, Remark: "close challenge", Note: note}
if err = s.dao.DB.Create(changeLog).Error; err != nil {
log.Error("s.dao.CloseChallengeStateLog(%d) error(%v)", id, err)
}
return
}
// Challenge get challenge info
func (s *Service) Challenge(c context.Context, ap *model.ChallengeParam) (chall *model.Challenge, err error) {
chall = &model.Challenge{}
if err = s.dao.DB.Where("id=? and mid=? and business=?", ap.ID, ap.Mid, ap.Business).Find(chall).Error; err != nil {
log.Error("s.dao.Challenge(%d,%d,%d) error(%v)", ap.ID, ap.Mid, ap.Business, err)
return
}
// read new state field of challenge
chall.FromState()
if err = s.dao.DB.Where("cid=?", ap.ID).Order("id desc").Find(&chall.Attachments).Error; err != nil {
log.Error("s.dao.Attachments(%d) error(%v)", ap.ID, err)
return
}
if err = s.dao.DB.Where("cid=?", ap.ID).Order("id asc").Find(&chall.Events).Error; err != nil {
log.Error("s.dao.Events(%d) error(%v)", ap.ID, err)
return
}
return
}
// Challenges get challenge list
func (s *Service) Challenges(c context.Context, ap *model.ChallengeParam) (challs []*model.Challenge, err error) {
if err = s.dao.DB.Where("mid=? and business=?", ap.Mid, ap.Business).Order("id DESC").Find(&challs).Error; err != nil {
log.Error("s.dao.Challenges(%d,%d) error(%v)", ap.Mid, ap.Business, err)
return
}
// read new state field of challenge
for cid := range challs {
challs[cid].FromState()
}
return
}
// UntreatedChallenge get untreated chanllenges by oid
func (s *Service) UntreatedChallenge(c context.Context, oid int64, role int8) (challs []*model.Challenge, err error) {
if role != model.AuditRole && role != model.CustomerServiceRole {
err = errors.New("UntreatedChallenge Unknown Role")
log.Error("s.dao.UntreatedChallenge(%d,%d) error(%v)", oid, role, err)
return
}
allChalls := []*model.Challenge{}
if err = s.dao.DB.Where("oid=?", oid).Order("id DESC").Find(&allChalls).Error; err != nil {
log.Error("s.dao.UntreatedChallenge(%d,%d) error(%v)", oid, role, err)
return
}
for _, challenge := range allChalls {
if value := challenge.GetState(uint8(role)); value == 0 {
challs = append(challs, challenge)
}
}
for _, chall := range challs {
if err = s.dao.DB.Where("cid=?", chall.ID).Find(&chall.BusinessInfo).Error; err != nil {
log.Error("s.dao.UntreatedChallenge(%d,%d) GetBusiness(%d) error(%v)", oid, role, chall.ID, err)
continue
}
}
err = nil
return
}
// Callback callback audit event to manage
func (s *Service) Callback(c context.Context, chall *model.Challenge, businessID int8) (err error) {
switch chall.Business {
case model.BusinessAudit:
err = s.dao.Callback(c, chall, businessID)
default:
}
return
}
// CallbackByID callback audit event to manage
func (s *Service) CallbackByID(c context.Context, challengeID int32, businessID int8) (err error) {
chall := &model.Challenge{}
if err = s.dao.DB.Where("id=? ", challengeID).Find(chall).Error; err != nil {
log.Error("s.CallbackByID(%d) error(%v)", challengeID, err)
return
}
return s.Callback(c, chall, businessID)
}
// Challenges3 .
func (s *Service) Challenges3(c context.Context, cp3 *model.ChallengeParam3) (res []*model.Challenge3, err error) {
if err = s.dao.DB.Where("business=? AND oid=? AND mid=?", cp3.Business, cp3.Oid, cp3.Mid).Order("id DESC").Find(&res).Error; err != nil {
log.Error("s.Challenges3 error(%v)", err)
}
return
}
// AddChallenge3 .
func (s *Service) AddChallenge3(c context.Context, cp3 *model.ChallengeParam3) (row int64, err error) {
var (
lasttime = time.Now()
group = &model.Group3{}
challenge *model.Challenge
)
tx := s.dao.DB.Begin()
if tx.Error != nil {
log.Error("s.dao.DB.Begin error(%v)", err)
return
}
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
log.Error("s.AddChallenge3 tx.Rollback error(%v)", err)
}
}
}()
if err = tx.Exec(_inGroupSQL3, cp3.Oid, cp3.Business, cp3.Fid, cp3.Rid, cp3.Eid, cp3.Score, cp3.Tid, lasttime, lasttime, model.StateTypePending).Error; err != nil {
log.Error("s.AddChallenge3 tx.Exec error(%v)", err)
return
}
if err = tx.Where("business=? AND oid=? AND eid=?", cp3.Business, cp3.Oid, cp3.Eid).Find(&group).Error; err != nil {
log.Error("s.AddChallenge3 tx.Where error(%v)", err)
return
}
challenge = &model.Challenge{
Tid: cp3.Tid,
Gid: int32(group.ID),
Oid: cp3.Oid,
Mid: cp3.Mid,
Eid: cp3.Eid,
Desc: cp3.Desc,
MetaData: cp3.MetaData,
Business: cp3.Business,
BusinessState: cp3.BusinessState,
Adminid: cp3.AdminID,
Assignee: cp3.AssigneeID,
}
challenge.SetState(uint32(0), cp3.Role)
if err = tx.Create(challenge).Error; err != nil {
log.Error("s.AddChallenge3 tx.Create error(%v)", err)
return
}
row = int64(challenge.ID)
if len(cp3.Attachments) > 0 {
values := []string{}
valueArgs := []interface{}{}
for _, a := range cp3.Attachments {
values = append(values, "(?,?)")
valueArgs = append(valueArgs, challenge.ID, a)
}
stmt := fmt.Sprintf("INSERT INTO workflow_attachment(cid,path) VALUES %s", strings.Join(values, ","))
if err = tx.Exec(stmt, valueArgs...).Error; err != nil {
return
}
}
if cp3.CheckBusiness() {
// todo workflow_business.oid save cp3.aid if exist
var aid = cp3.Oid
if cp3.Aid > 0 {
aid = cp3.Aid
}
// todo insert or update business record
bus := &model.Business{}
if err = tx.Table("workflow_business").Where("gid = ?", group.ID).Find(bus).Error; err != nil {
if err != gorm.ErrRecordNotFound {
log.Error("s.AddChallenge3 tx.Where error(%v)", err)
return
}
// insert business table
if err = tx.Exec(_inBusiness3, aid, cp3.BusinessTypeid, cp3.Business, cp3.BusinessTitle, cp3.BusinessContent, cp3.BusinessMid, cp3.BusinessExtra, challenge.ID, group.ID).Error; err != nil {
log.Error("tx.Exec(%s) params(oid=%d,typeid=%d,business=%d,title=%s,content=%s,mid=%d,extra=%s,cid=%d,gid=%d) error(%v)", _inBusiness3, cp3.Oid, cp3.BusinessTypeid, cp3.Business, cp3.BusinessTitle, cp3.BusinessContent, cp3.BusinessMid, cp3.BusinessExtra, challenge.ID, group.ID, err)
return
}
} else {
// update business table
if err = tx.Exec(_upBusiness3, cp3.BusinessTypeid, cp3.BusinessTitle, cp3.BusinessContent, cp3.BusinessExtra, group.ID).Error; err != nil {
log.Error("tx.Exec(%s) params(typeid=%d,title=%s,content=%s,extra=%s) error(%v)", _upBusiness3, cp3.BusinessTypeid, cp3.BusinessTitle, cp3.BusinessContent, cp3.BusinessExtra, err)
}
}
}
if err = tx.Commit().Error; err != nil {
log.Error("s.AddChallenge3 tx.Commit error(%v)", err)
}
// upsert
if group.Count <= 1 {
s.cache.Do(context.Background(), func(c context.Context) {
if err = s.dao.UpdateUserTag(c, group.ID, cp3.Tid); err != nil {
log.Error("s.dao.UpdateUserTag gid:%d error:%v", group.ID, err)
}
})
}
return
}
// GroupState3 .
func (s *Service) GroupState3(c context.Context, cp3 *model.ChallengeParam3) (state int, err error) {
err = s.dao.DB.Table("workflow_group").Select("state").Where("business=? AND oid=? AND eid=?", cp3.Business, cp3.Oid, cp3.Eid).Row().Scan(&state)
if err == sql.ErrNoRows {
err = nil
state = -1
}
return
}