123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988 |
- package service
- import (
- "context"
- "encoding/json"
- "fmt"
- "math"
- "net/url"
- "sort"
- "strconv"
- "time"
- "go-common/app/admin/main/credit/model/blocked"
- "go-common/app/admin/main/workflow/model"
- "go-common/app/admin/main/workflow/model/param"
- "go-common/app/admin/main/workflow/model/search"
- "go-common/library/ecode"
- "go-common/library/log"
- "github.com/jinzhu/gorm"
- "golang.org/x/sync/errgroup"
- )
- // GroupListV3 .
- func (s *Service) GroupListV3(c context.Context, cond *search.GroupSearchCommonCond) (grpPage *model.GroupListPage, err error) {
- var (
- ok bool
- groupSearchCommonResp *search.GroupSearchCommonResp
- wg = &errgroup.Group{}
- )
- if groupSearchCommonResp, err = s.dao.SearchGroup(c, cond); err != nil {
- log.Error("Failed to s.dao.SearchGroup(%v): %v", cond, err)
- err = ecode.WkfSearchGroupFailed
- return
- }
- if len(groupSearchCommonResp.Result) == 0 {
- grpPage = &model.GroupListPage{
- Items: []*model.Group{},
- Page: &model.Page{},
- }
- return
- }
- eids, oids, gids, mids := []int64{}, []int64{}, []int64{}, []int64{}
- fut := make(map[int64]int64, len(groupSearchCommonResp.Result))
- for _, v := range groupSearchCommonResp.Result {
- gids = append(gids, v.ID)
- oids = append(oids, v.Oid)
- eids = append(eids, v.Eid)
- if v.Mid > 0 {
- mids = append(mids, v.Mid)
- }
- fut[v.ID] = v.FirstUserTid
- }
- // last chall mids
- cscc := &search.ChallSearchCommonCond{
- Fields: []string{"id", "gid", "mid"},
- Business: cond.Business,
- Gids: gids,
- Order: "ctime",
- Sort: "desc",
- Distinct: []string{"gid"},
- PS: 999,
- PN: 1,
- }
- var (
- cResp *search.ChallSearchCommonResp
- lastChalls = make(map[int64]*model.Chall)
- )
- if cResp, err = s.dao.SearchChallenge(c, cscc); err != nil {
- log.Error("s.dao.SearchChallenge(%v) error(%v)", cscc, err)
- } else {
- for _, r := range cResp.Result {
- if r.Mid > 0 {
- mids = append(mids, r.Mid)
- }
- lastChalls[r.Gid] = &model.Chall{Cid: r.ID, Mid: r.Mid}
- }
- }
- // group object
- var groups map[int64]*model.Group
- wg.Go(func() error {
- if groups, err = s.dao.Groups(c, gids); err != nil {
- log.Error("Failed to s.dao.Groups(%v): %v", gids, err)
- return err
- }
- return nil
- })
- // todo load data from db, search, external api
- // tag count of challenge
- var gidToChallTagCount map[int64]map[int64]int64
- wg.Go(func() error {
- // todo: count tag in es
- if gidToChallTagCount, err = s.dao.ChallTagsCountV3(c, gids); err != nil {
- log.Error("s.dao.ChallTagsCountV3(%v) error(%v)", gids, err)
- err = nil
- } else {
- log.Info("gidToChallTagCount (%+v)", gidToChallTagCount)
- }
- return nil
- })
- var grpLastLog map[int64]string
- wg.Go(func() error {
- if grpLastLog, err = s.LastLog(c, gids, []int{model.WLogModuleGroup, model.WLogModuleRoleShift}); err != nil {
- log.Error("s.LastLog(%v,%d) error(%v)", gids, model.WLogModuleGroup, err)
- err = nil
- }
- return nil
- })
- // search account
- var users map[int64]*model.Account
- wg.Go(func() error {
- users = s.dao.AccountInfoRPC(c, mids)
- //get uper group
- var uperTagMap map[int64][]*model.SpecialTag
- if uperTagMap, err = s.dao.BatchUperSpecial(c, mids); err != nil {
- log.Error("s.dao.BatchUperSpecial(%v) error(%v)", mids, err)
- err = nil
- } else {
- for id, user := range users {
- var st []*model.SpecialTag
- if st, ok = uperTagMap[id]; !ok {
- log.Warn("not find special tag mid(%d)", id)
- continue
- }
- user.SpecialTag = st
- }
- }
- return nil
- })
- // object table
- // todo: judge if need read local object
- var bus map[int64]*model.Business
- var archives map[int64]*model.Archive
- wg.Go(func() error {
- if bus, err = s.dao.BusObjectByGids(c, gids); err != nil {
- log.Error("s.dao.BusObjectByGids(%v) error(%v)", gids, err)
- err = nil
- }
- // search archive
- // todo: judge if need search archive
- aids := []int64{}
- for _, b := range bus {
- aids = append(aids, b.Oid)
- }
- if archives, err = s.dao.ArchiveRPC(c, aids); err != nil {
- log.Error("s.dao.ArchiveRPC(%v) error(%v)", oids, err)
- err = nil
- }
- return nil
- })
- // external meta
- var metas map[int64]*model.GroupMeta
- wg.Go(func() error {
- if metas, err = s.externalMeta(c, cond.Business, gids, oids, eids); err != nil {
- log.Error("s.ExternalMeta(%d,%v,%v,%v) error(%v)", cond.Business, gids, oids, eids, err)
- err = nil
- } else {
- log.Info("external meta (%+v)", metas)
- }
- return nil
- })
- // wait all wg.go()
- if err = wg.Wait(); err != nil {
- return
- }
- //todo make response
- grpPage = new(model.GroupListPage)
- rgs := make([]*model.Group, 0, len(groupSearchCommonResp.Result))
- for _, v := range groupSearchCommonResp.Result {
- var (
- rg *model.Group
- ok bool
- )
- if rg, ok = groups[v.ID]; !ok {
- log.Warn("Failed to retrive group by group id %d", v.ID)
- continue
- }
- if !dbCheck(cond, rg) {
- continue
- }
- rg.TypeID = v.TypeID
- // fill last log
- var l string
- if l, ok = grpLastLog[v.ID]; ok {
- rg.LastLog = l
- }
- // fill tag name
- // using tid from group row can ensure the lastest tid fetched
- if tid := rg.Tid; tid != 0 {
- var t *model.TagMeta
- if t, err = s.tag(rg.Business, tid); err != nil {
- log.Error("Failed to retrive tag by bid(%d) tag_id(%d)", rg.Business, tid)
- err = nil
- } else {
- rg.Tag = t.Name
- }
- }
- rg.ChallengeTags = model.ChallTagSlice{}
- var tc map[int64]int64
- if tc, ok = gidToChallTagCount[v.ID]; ok {
- total := int64(0)
- for _, count := range tc {
- total += count
- }
- for tid, c := range tc {
- tname := "<Unknow>"
- tround := int8(0)
- var t *model.TagMeta
- if t, err = s.tag(rg.Business, tid); err != nil {
- log.Error("Failed to retrive tag by bid(%d) tag_id(%d)", rg.Business, tid)
- err = nil
- } else {
- tname = t.Name
- tround = t.RID
- }
- ct := &model.ChallTag{
- ID: tid,
- Tag: tname,
- Count: c,
- Percent: 100,
- Round: tround,
- }
- if total != 0 {
- ct.Percent = round((float64(c) / float64(total)) * 100)
- }
- rg.ChallengeTags = append(rg.ChallengeTags, ct)
- }
- log.Warn("challenge tags of gid(%d) %+v", rg.ID, rg.ChallengeTags)
- } else {
- log.Warn("not found chall tag count of gid(%d)", v.ID)
- }
- sort.Sort(rg.ChallengeTags)
- // fill last producer
- var lc *model.Chall
- if lc, ok = lastChalls[rg.ID]; ok {
- if rg.LastProducer, ok = users[lc.Mid]; !ok {
- log.Warn("gid(%d) has last producer mid(%d) but not found account", rg.ID, lc.Mid)
- }
- log.Info("gid(%d) load last producer mid(%d) success (%+v)", rg.ID, lc.Mid, rg.LastProducer)
- } else {
- log.Warn("not found account of last producer gid(%d)", rg.ID)
- }
- // fill meta
- s.warpMeta(cond.Business, rg, metas, archives, users, bus)
- // oid to string
- rg.OidStr = strconv.FormatInt(rg.Oid, 10)
- // eid to string
- rg.EidStr = strconv.FormatInt(rg.Eid, 10)
- rgs = append(rgs, rg)
- // fill first_user_tid
- rg.FirstUserTid = fut[rg.ID]
- }
- grpPage.Items = rgs
- grpPage.Page = &model.Page{
- Num: groupSearchCommonResp.Page.Num,
- Size: groupSearchCommonResp.Page.Size,
- Total: groupSearchCommonResp.Page.Total,
- }
- return
- }
- // UpGroup will update a group
- func (s *Service) UpGroup(c context.Context, gp *param.GroupParam) (err error) {
- var (
- tx *gorm.DB
- l *model.WLog
- g *model.Group
- )
- // double write rid
- tMeta := &model.TagMeta{}
- if tMeta, err = s.tag(gp.Business, gp.Tid); err != nil {
- log.Error("TagListCache not found bid(%d) tag_id(%d)", gp.Business, gp.Tid)
- return
- }
- gp.Rid = tMeta.RID
- // Check group and tag is exist
- if g, err = s.dao.GroupByOid(c, gp.Oid, gp.Business); err != nil {
- log.Error("s.dao.GroupByOid(%d, %d) error(%v)", gp.Oid, gp.Business, err)
- return
- }
- if g == nil {
- log.Error("Group(%d, %d) not exist", gp.Oid, gp.Business)
- err = ecode.WkfGroupNotFound
- return
- }
- tx = s.dao.ORM.Begin()
- if err = tx.Error; err != nil {
- return
- }
- defer func() {
- if r := recover(); r != nil {
- tx.Rollback()
- log.Error("Service.UpGroup() panic(%v)", r)
- }
- }()
- if err = s.dao.TxUpGroup(tx, gp.Oid, gp.Business, gp.Tid, gp.Note, gp.Rid); err != nil {
- tx.Rollback()
- log.Error("s.TxUpGroup(%d, %d, %d, %s, %d) error(%v)", gp.Oid, gp.Business, gp.Tid, gp.Note, gp.Rid, err)
- return
- }
- if err = tx.Commit().Error; err != nil {
- tx.Rollback()
- log.Error("tx.Commit() error(%v)", err)
- return
- }
- s.task(func() {
- l = &model.WLog{
- AdminID: gp.AdminID,
- Admin: gp.AdminName,
- Oid: g.Oid,
- Business: g.Business,
- Target: g.ID,
- Module: model.WLogModuleGroup,
- Remark: fmt.Sprintf(`工单编号 %d “管理 Tag”更新为“%s”`, g.ID, tMeta.Name),
- Note: gp.Note,
- }
- s.writeAuditLog(l)
- })
- return
- }
- // UpGroupRole will 流转工单
- func (s *Service) UpGroupRole(c context.Context, grsp *param.GroupRoleSetParam) (err error) {
- var groups map[int64]*model.Group
- // Check group and tag is exist
- if groups, err = s.dao.Groups(c, grsp.GID); err != nil {
- log.Error("s.dao.Groups(%v) error(%v)", grsp.GID, err)
- return
- }
- if len(groups) == 0 {
- log.Error("Group(%v) not exist", grsp.GID)
- err = ecode.WkfGroupNotFound
- return
- }
- // check bid
- for _, g := range groups {
- if g.Business != grsp.BID {
- err = ecode.WkfBusinessNotConsistent
- return
- }
- }
- // check tid available
- var tMeta *model.TagMeta
- if tMeta, err = s.tag(grsp.BID, grsp.TID); err != nil {
- return
- }
- grsp.RID = tMeta.RID
- if err = s.dao.UpGroupRole(c, grsp); err != nil {
- log.Error("s.UpGroupRole(%+v) error(%v)", grsp, err)
- return
- }
- s.task(func() {
- s.afterSetGroupRole(grsp, groups)
- })
- return
- }
- // SetGroupResult will set a group result
- func (s *Service) SetGroupResult(c context.Context, grp *param.GroupResParam) (err error) {
- var (
- tx *gorm.DB
- g *model.Group
- tinyChalls map[int64]*model.TinyChall
- cids []int64
- )
- if g, err = s.dao.GroupByOid(c, grp.Oid, grp.Business); err != nil {
- log.Error("s.dao.GroupByOid() error(%v)", err)
- return
- }
- if g == nil {
- log.Error("Group(%d, %d) not exist", grp.Oid, grp.Business)
- err = ecode.NothingFound
- return
- }
- if g.State != model.Pending {
- log.Error("Group(%d, %d) not pending", grp.Oid, grp.Business)
- return
- }
- tx = s.dao.ORM.Begin()
- if err = tx.Error; err != nil {
- log.Error("s.dao.ORM.Begin() error(%v)", err)
- return
- }
- defer func() {
- if r := recover(); r != nil {
- tx.Rollback()
- log.Error("Service.SetGroupResult() panic(%v)", r)
- }
- }()
- // Update Group State
- if err = s.dao.TxUpGroupState(tx, g.ID, grp.State); err != nil {
- tx.Rollback()
- log.Error("s.txUpGroupState(%+v) error(%v)", g, err)
- return
- }
- // set grouo handling field to 0
- if err = s.dao.TxUpGroupHandling(tx, g.ID, 0); err != nil {
- tx.Rollback()
- log.Error("s.txUpGroupHandling(%+v, 0) error(%v)", g.ID, err)
- return
- }
- if err = tx.Commit().Error; err != nil {
- tx.Rollback()
- log.Error("tx.Commit() error(%v)", err)
- return
- }
- s.task(func() {
- var result []*search.ChallSearchCommonData
- cond := &search.ChallSearchCommonCond{
- Fields: []string{"id", "gid", "mid", "state", "ctime"},
- Gids: []int64{g.ID},
- States: []int64{int64(model.Pending)},
- }
- if result, err = s.dao.SearchChallengeMultiPage(context.Background(), cond); err != nil {
- log.Error("s.dao.SearchChallengeMultiPage(%+v) error(%v)", cond, err)
- return
- }
- tinyChalls = make(map[int64]*model.TinyChall, len(cids))
- for _, c := range result {
- cids = append(cids, c.ID)
- tc := &model.TinyChall{
- Cid: c.ID,
- Gid: c.Gid,
- Mid: c.Mid,
- }
- var ctime time.Time
- ctime, err = time.ParseInLocation("2006-01-02 15:04:05", c.CTime, time.Local)
- if err != nil {
- log.Error("time.Parse(%v) error(%v)", c.CTime, err)
- }
- tc.CTime.Scan(ctime)
- log.Info("tc.CTime.Scan(%v) get (%v) cid(%v) gid(%v)", ctime.Unix(), tc.CTime.Time(), tc.Cid, tc.Gid)
- if str, ok := c.State.(string); ok {
- st, _ := strconv.Atoi(str)
- tc.State = int8(st)
- }
- if f, ok := c.State.(float64); ok {
- tc.State = int8(math.Floor(f))
- }
- tinyChalls[c.ID] = tc
- }
- if err = s.dao.BatchUpChallByIDs(cids, uint32(grp.State), grp.AdminID); err != nil {
- log.Error("s.dao.TxBatchUpChallByIDs(%v,%d) error(%v)", cids, grp.State, err)
- return
- }
- s.afterSetGrpResult(grp, g, tinyChalls)
- })
- return
- }
- // BatchSetGroupResult will set a set of groups result
- func (s *Service) BatchSetGroupResult(c context.Context, bgrp *param.BatchGroupResParam) (err error) {
- var (
- tx *gorm.DB
- groups map[int64]*model.Group
- tinyChalls map[int64]*model.TinyChall
- gids []int64
- cids []int64
- )
- tx = s.dao.ORM.Begin()
- if err = tx.Error; err != nil {
- log.Error("s.dao.ORM.Begin() error(%v)", err)
- return
- }
- defer func() {
- if r := recover(); r != nil {
- tx.Rollback()
- log.Error("Service.BatchSetGroupResult() panic(%v)", r)
- }
- }()
- if groups, err = s.dao.TxGroupsByOidsStates(tx, bgrp.Oids, bgrp.Business, model.Pending); err != nil {
- log.Error("s.dao.TxGroupsByOidsStates() error(%v)", err)
- return
- }
- if len(groups) <= 0 {
- log.Warn("No pending groups found with conditon(%+v, %d, %d)", bgrp.Oids, bgrp.Business, model.Pending)
- return
- }
- // collect all gids
- for gid := range groups {
- gids = append(gids, int64(gid))
- }
- if err = s.dao.TxBatchUpGroupState(tx, gids, bgrp.State); err != nil {
- tx.Rollback()
- log.Error("s.TxBatchUpGroupState(%+v) error(%v)", bgrp, err)
- return
- }
- // Set group handling count to 0
- if err = s.dao.TxBatchUpGroupHandling(tx, gids, 0); err != nil {
- tx.Rollback()
- log.Error("s.TxBatchUpGroupHandling(%+v, 0) error(%v)", gids, err)
- return
- }
- if err = tx.Commit().Error; err != nil {
- tx.Rollback()
- log.Error("tx.Commit() error(%v)", err)
- return
- }
- s.task(func() {
- var result []*search.ChallSearchCommonData
- cond := &search.ChallSearchCommonCond{
- Fields: []string{"id", "gid", "mid", "state", "ctime"},
- Gids: gids,
- States: []int64{int64(model.Pending)},
- }
- if result, err = s.dao.SearchChallengeMultiPage(context.Background(), cond); err != nil {
- log.Error("s.dao.SearchChallengeMultiPage(%+v) error(%v)", cond, err)
- return
- }
- tinyChalls = make(map[int64]*model.TinyChall, len(cids))
- for _, c := range result {
- cids = append(cids, c.ID)
- tc := &model.TinyChall{
- Cid: c.ID,
- Gid: c.Gid,
- Mid: c.Mid,
- }
- var ctime time.Time
- ctime, err = time.ParseInLocation("2006-01-02 15:04:05", c.CTime, time.Local)
- if err != nil {
- log.Error("time.Parse(%v) error(%v)", c.CTime, err)
- }
- tc.CTime.Scan(ctime)
- log.Info("tc.CTime.Scan(%v) get (%v) cid(%v) gid(%v)", ctime.Unix(), tc.CTime.Time(), tc.Cid, tc.Gid)
- if str, ok := c.State.(string); ok {
- st, _ := strconv.Atoi(str)
- tc.State = int8(st)
- }
- if f, ok := c.State.(float64); ok {
- tc.State = int8(math.Floor(f))
- }
- tinyChalls[c.ID] = tc
- }
- if err = s.dao.BatchUpChallByIDs(cids, uint32(bgrp.State), bgrp.AdminID); err != nil {
- log.Error("s.dao.BatchUpChallByIDs(%v,%d) error(%v)", cids, bgrp.State, err)
- return
- }
- s.afterBatchSetGrpResult(bgrp, groups, tinyChalls)
- })
- return
- }
- // SetGroupState 修改未处理的工单状态
- func (s *Service) SetGroupState(c context.Context, gssp *param.GroupStateSetParam) (err error) {
- var (
- groups map[int64]*model.Group
- tinyChalls map[int64]*model.TinyChall
- gids, cids []int64
- newRid int8
- )
- //check tid 有效处理验证tid
- if gssp.State == model.Effective {
- var tmeta *model.TagMeta
- if tmeta, err = s.tag(gssp.Business, gssp.Tid); err != nil {
- return
- }
- newRid = tmeta.RID
- }
- tx := s.dao.ORM.Begin()
- if err = tx.Error; err != nil {
- log.Error("s.dao.ORM.Begin() error(%v)", err)
- return
- }
- defer func() {
- if r := recover(); r != nil {
- tx.Rollback()
- log.Error("s.SetGroupState() panic(%v)", r)
- }
- if err != nil {
- tx.Rollback()
- }
- }()
- if groups, err = s.dao.Groups(c, gssp.ID); err != nil {
- log.Error("s.dao.TxGroups(%v) error(%v)", gssp.ID, err)
- return
- }
- // ignore group if state not pending
- for id, g := range groups {
- if g.State != model.Pending || g.Business != gssp.Business || g.Rid != gssp.Rid {
- delete(groups, id)
- continue
- }
- gids = append(gids, id)
- }
- if len(gids) <= 0 {
- log.Warn("No settable groups found with conditon(%+v)", *gssp)
- err = ecode.WkfGroupNotFound
- return
- }
- // 有效处理同步修改tid & rid
- if gssp.State == model.Effective {
- if err = s.dao.TxSetGroupStateTid(tx, gids, gssp.State, newRid, gssp.Tid); err != nil {
- log.Error("s.TxSetGroupStateTid(%v,%d,%d) error(%v)", gids, gssp.State, gssp.Tid, err)
- return
- }
- } else {
- if err = s.dao.TxSimpleSetGroupState(tx, gids, gssp.State); err != nil {
- log.Error("s.TxSimpleSetGroupState(%v,%d,%d) error(%v)", gids, gssp.State, gssp.Tid, err)
- return
- }
- }
- // Set group handling count to 0
- if err = s.dao.TxBatchUpGroupHandling(tx, gids, 0); err != nil {
- log.Error("s.TxBatchUpGroupHandling(%+v, 0) error(%v)", gids, err)
- return
- }
- if err = tx.Commit().Error; err != nil {
- log.Error("tx.Commit() error(%v)", err)
- return
- }
- s.task(func() {
- // group bus object
- var gidToBus map[int64]*model.Business
- if gidToBus, err = s.dao.BusObjectByGids(context.Background(), gids); err != nil {
- log.Error("s.dao.BusObjectByGids(%v) error(%v)", gids, err)
- return
- }
- for _, g := range groups {
- g.BusinessObject = gidToBus[g.ID]
- }
- var result []*search.ChallSearchCommonData
- cond := &search.ChallSearchCommonCond{
- Fields: []string{"id", "gid", "mid", "state", "title", "oid", "tid", "business"},
- Gids: gids,
- States: []int64{int64(model.Pending)},
- }
- if result, err = s.dao.SearchChallengeMultiPage(context.Background(), cond); err != nil {
- log.Error("s.dao.SearchChallengeMultiPage(%+v) error(%v)", cond, err)
- return
- }
- tinyChalls = make(map[int64]*model.TinyChall, len(cids)) // map[id]*tc
- for _, c := range result {
- cids = append(cids, c.ID)
- tc := &model.TinyChall{
- Cid: c.ID,
- Gid: c.Gid,
- Mid: c.Mid,
- Title: c.Title,
- }
- if str, ok := c.State.(string); ok {
- st, _ := strconv.Atoi(str)
- tc.State = int8(st)
- }
- if f, ok := c.State.(float64); ok {
- tc.State = int8(math.Floor(f))
- }
- tinyChalls[c.ID] = tc
- }
- // async set challenge state
- if err = s.dao.BatchUpChallByIDs(cids, uint32(gssp.State), gssp.AdminID); err != nil {
- log.Error("s.dao.BatchUpChallByIDs(%v,%d) error(%v)", cids, gssp.State, err)
- return
- }
- s.afterSetGroupState(gssp, groups, tinyChalls)
- })
- return
- }
- // SetPublicReferee 移交众裁
- func (s *Service) SetPublicReferee(c context.Context, gspr *param.GroupStatePublicReferee) (err error) {
- tx := s.dao.ORM.Begin()
- if err = tx.Error; err != nil {
- log.Error("s.dao.ORM.Begin() error(%v)", err)
- return
- }
- defer func() {
- if r := recover(); r != nil {
- tx.Rollback()
- log.Error("s.SetPublicReferee() panic(%v)", r)
- }
- if err != nil {
- tx.Rollback()
- }
- }()
- var groups map[int64]*model.Group
- if groups, err = s.dao.TxGroups(tx, gspr.ID); err != nil {
- log.Error("s.dao.TxGroups(%v) error(%v)", gspr.ID, err)
- return
- }
- // ignore group if state not pending
- var gids, oids, eids []int64
- for id, g := range groups {
- if g.State != model.Pending || g.Business != gspr.Business {
- delete(groups, id)
- continue
- }
- gids = append(gids, id)
- oids = append(oids, g.Oid)
- eids = append(eids, g.Eid)
- }
- if len(gids) <= 0 {
- log.Warn("No pending groups found with conditon(%+v)", *gspr)
- err = ecode.WkfGroupNotFound
- return
- }
- // set state to public referee
- gspr.State = model.PublicReferee
- // start block add case
- // object
- var gidBus map[int64]*model.Business
- if gidBus, err = s.dao.BusObjectByGids(c, gids); err != nil {
- log.Error("s.dao.BusObjectByGids(%v) error(%v)", gids, err)
- err = ecode.WkfSetPublicRefereeFailed
- return
- }
- // external
- var metas map[int64]*model.GroupMeta
- if metas, err = s.externalMeta(c, gspr.Business, gids, oids, eids); err != nil {
- log.Error("s.SearchMeta(%d,%v,%v,%v) error(%v)", gspr.Business, gids, oids, eids, err)
- err = ecode.WkfSetPublicRefereeFailed
- return
- }
- var data []model.BlockCaseAdd
- for _, g := range groups {
- log.Info("start add case gid(%d)", g.ID)
- if _, ok := gidBus[g.ID]; !ok {
- log.Warn("gid(%d) not found bus object", g.ID)
- err = ecode.WkfSetPublicRefereeFailed
- return
- }
- bus := gidBus[g.ID]
- var (
- extra map[string]interface{}
- external map[string]interface{}
- link, title string
- ok bool
- ctime float64
- )
- if err = json.Unmarshal([]byte(bus.Extra), &extra); err != nil {
- log.Error("json.Unmarshal(%s) failed error(%v)", bus.Extra, err)
- err = ecode.WkfSetPublicRefereeFailed
- return
- }
- // redirect url
- if link, ok = extra["link"].(string); !ok {
- log.Error("gid(%d) assert business extra link failed", g.ID)
- err = ecode.WkfSetPublicRefereeFailed
- return
- }
- // object title
- if title, ok = extra["title"].(string); !ok {
- log.Error("gid(%d) assert business extra title failed", g.ID)
- err = ecode.WkfSetPublicRefereeFailed
- return
- }
- if _, ok = metas[g.ID]; !ok {
- log.Error("gid(%d) not found meta data", g.ID)
- err = ecode.WkfSetPublicRefereeFailed
- return
- }
- if external, ok = metas[g.ID].External.(map[string]interface{}); !ok {
- log.Error("gid(%d) external meta data assert failed", g.ID)
- err = ecode.WkfSetPublicRefereeFailed
- return
- }
- // business object ctime
- if ctime, ok = external["ctime"].(float64); !ok {
- log.Error("gid(%d) external ctime assert failed", g.ID)
- err = ecode.WkfSetPublicRefereeFailed
- return
- }
- d := model.BlockCaseAdd{
- RpID: g.Eid,
- Oid: g.Oid,
- Type: g.Fid,
- Mid: bus.Mid,
- Operator: gspr.AdminName,
- OperID: gspr.AdminID,
- OriginContent: bus.Title,
- ReasonType: g.Tid,
- BusinessTime: int64(ctime),
- OriginType: int64(blocked.OriginReply), // fixme: support multi business
- OriginTitle: title,
- OriginURL: link,
- }
- data = append(data, d)
- }
- // request credit
- var content []byte
- if content, err = json.Marshal(data); err != nil {
- log.Error("json.Marshal(%v) error(%v)", data, err)
- err = ecode.WkfSetPublicRefereeFailed
- return
- }
- uv := url.Values{}
- uv.Set("data", string(content))
- if err = s.dao.AddCreditCase(c, uv); err != nil {
- return
- }
- // set group set only
- if err = s.dao.TxSimpleSetGroupState(tx, gids, gspr.State); err != nil {
- log.Error("s.TxSimpleSetGroupState(%v,%d) error(%v)", gids, gspr.State, err)
- return
- }
- // set group handling count to 0
- if err = s.dao.TxBatchUpGroupHandling(tx, gids, 0); err != nil {
- log.Error("s.TxBatchUpGroupHandling(%+v, 0) error(%v)", gids, err)
- return
- }
- if err = tx.Commit().Error; err != nil {
- log.Error("tx.Commit() error(%v)", err)
- return
- }
- s.task(func() {
- // async set challenge state
- var (
- result []*search.ChallSearchCommonData
- cids []int64
- )
- cond := &search.ChallSearchCommonCond{
- Fields: []string{"id"},
- Gids: gids,
- States: []int64{int64(model.Pending)},
- }
- if result, err = s.dao.SearchChallengeMultiPage(context.Background(), cond); err != nil {
- log.Error("s.dao.SearchChallengeMultiPage(%+v) error(%v)", cond, err)
- return
- }
- for _, c := range result {
- cids = append(cids, c.ID)
- }
- if err = s.dao.BatchUpChallByIDs(cids, uint32(gspr.State), gspr.AdminID); err != nil {
- log.Error("s.dao.BatchUpChallByIDs(%v,%d) error(%v)", cids, gspr.State, err)
- return
- }
- s.afterSimpleSetState(gspr, groups)
- })
- return
- }
- // GroupPendingCount 当前 bid/rid 待办工单数
- func (s *Service) GroupPendingCount(c context.Context, cond *search.GroupSearchCommonCond) (gpc *model.GroupPendingCount, err error) {
- var groupSearchCommonResp *search.GroupSearchCommonResp
- if groupSearchCommonResp, err = s.dao.SearchGroup(c, cond); err != nil {
- log.Error("Failed to s.dao.SearchGroup(%v): %v", cond, err)
- err = ecode.WkfSearchGroupFailed
- return
- }
- gpc = &model.GroupPendingCount{
- Total: groupSearchCommonResp.Page.Total,
- }
- return
- }
- // ExternalMeta external dependency
- func (s *Service) externalMeta(c context.Context, business int8, gids, oids, eids []int64) (metas map[int64]*model.GroupMeta, err error) {
- metas = make(map[int64]*model.GroupMeta)
- // check if has external uri
- if _, ok := s.callbackCache[business]; !ok {
- return
- }
- uri := ""
- if uri = s.callbackCache[business].ExternalAPI; uri == "" {
- log.Warn("bid %d not found external api", business)
- return
- }
- // search meta
- //todo: common extra info
- var data map[string]interface{}
- if data, err = s.dao.CommonExtraInfo(c, business, uri, gids, oids, eids); err != nil {
- log.Error("s.dao.CommonExtraInfo() error(%v)", err)
- return
- }
- log.Info("bid(%d) external data(%v)", business, data)
- for gidStr, ext := range data {
- gid, _ := strconv.ParseInt(gidStr, 10, 64)
- metas[gid] = &model.GroupMeta{
- External: ext,
- }
- }
- return
- }
- // WarpMeta .
- func (s *Service) warpMeta(business int8, group *model.Group, metas map[int64]*model.GroupMeta, archives map[int64]*model.Archive, users map[int64]*model.Account, bus map[int64]*model.Business) {
- // not has external data
- if _, ok := metas[group.ID]; !ok {
- metas[group.ID] = &model.GroupMeta{}
- }
- var (
- b *model.Business
- ok bool
- )
- if b, ok = bus[group.ID]; ok {
- metas[group.ID].Object = b
- group.Defendant = users[b.Mid]
- metas[group.ID].Archive = archives[b.Oid]
- }
- group.MetaData = metas[group.ID]
- log.Info("WarpMeta gid(%d) oid(%d) eid(%d) meta.External(%+v)", group.ID, group.Oid, group.Eid, metas[group.ID].External)
- }
- // UpGroupExtra update business extra of gid, only cover business extra field
- func (s *Service) UpGroupExtra(c context.Context, uep *param.UpExtraParam) (err error) {
- if err = s.dao.UpExtraV3(uep.Gids, uep.AdminID, uep.Extra); err != nil {
- log.Error("s.dao.UpExtraV3(%v, %d, %v) error(%v)", uep.Gids, uep.AdminID, uep.Extra, err)
- }
- // todo: after up extra
- return
- }
- // dbCheck check group state & rid in db
- func dbCheck(cond *search.GroupSearchCommonCond, rg *model.Group) (isCheck bool) {
- var (
- isStateCheck bool
- isRidCheck bool
- )
- // check db state
- if len(cond.States) == 0 {
- isStateCheck = true
- } else {
- for _, state := range cond.States {
- if rg.State == state {
- isStateCheck = true
- break
- }
- }
- }
- // check rid
- if len(cond.RID) == 0 {
- isRidCheck = true
- } else {
- for _, rid := range cond.RID {
- if rg.Rid == rid {
- isRidCheck = true
- break
- }
- }
- }
- if isStateCheck && isRidCheck {
- isCheck = true
- }
- return
- }
- func round(num float64) int32 {
- return int32(num + math.Copysign(0.5, num))
- }
|