123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173 |
- package upcrmservice
- import (
- "context"
- "errors"
- "fmt"
- "sort"
- "strings"
- "time"
- "go-common/app/admin/main/up/dao/global"
- "go-common/app/admin/main/up/model"
- "go-common/app/admin/main/up/model/signmodel"
- "go-common/app/admin/main/up/model/upcrmmodel"
- "go-common/app/admin/main/up/service/cache"
- "go-common/app/admin/main/up/util"
- accgrpc "go-common/app/service/main/account/api"
- "go-common/library/log"
- "go-common/library/net/http/blademaster"
- "go-common/library/net/metadata"
- xtime "go-common/library/time"
- "github.com/jinzhu/gorm"
- )
- // SignUpAuditLogs .
- func (s *Service) SignUpAuditLogs(c context.Context, arg *signmodel.SignOpSearchArg) (res *signmodel.SignAuditListReply, err error) {
- return s.mng.SignUpAuditLogs(c, arg)
- }
- // SignAdd add sign info
- func (s *Service) SignAdd(context context.Context, arg *signmodel.SignUpArg) (result signmodel.CommonResponse, err error) {
- if arg == nil {
- log.Error("sign add arg is nil")
- return
- }
- // 处理合同信息
- var contractInfo []*signmodel.SignContractInfoArg
- for _, v := range arg.ContractInfo {
- if v == nil || strings.Trim(v.Filename, " ") == "" {
- continue
- }
- if strings.Trim(v.Filelink, " \n\r") == "" {
- err = model.ErrNoFileLink
- log.Error("no file link for contract, please upload file, arg=%v", arg)
- return
- }
- contractInfo = append(contractInfo, v)
- }
- arg.ContractInfo = contractInfo
- // 从context 里拿后台登录信息
- var bmContext, ok = context.(*blademaster.Context)
- if ok {
- uid, ok := util.GetContextValueInt64(bmContext, "uid")
- if ok {
- arg.AdminID = int(uid)
- }
- name, ok := util.GetContextValueString(bmContext, "username")
- if ok {
- arg.AdminName = name
- }
- }
- log.Info("add sign up, req=%+v, admin id=%d, admin name=%s", arg, arg.AdminID, arg.AdminName)
- // 事物
- tx := s.crmdb.BeginTran(context)
- defer func() {
- if err != nil {
- tx.Rollback()
- } else {
- tx.Commit()
- }
- }()
- // 获取up主基础信息中的分区id
- upInfo, _ := s.crmdb.QueryUpBaseInfo(arg.Mid, "active_tid")
- // 1.先去sign up里插入一条记录,然后获得对应的id
- var dbSignUp signmodel.SignUp
- // 把请求信息制作签约up的db内容
- arg.CopyTo(&dbSignUp)
- if upInfo.ActiveTid != 0 {
- // 把up主的分区id赋值到签约up主信息
- dbSignUp.ActiveTid = int16(upInfo.ActiveTid)
- }
- _, e := s.crmdb.InsertSignUp(tx, &dbSignUp)
- err = e
- if err != nil {
- log.Error("fail to add into sign up db, req=%+v, err=%+v", arg, err)
- return
- }
- log.Info("add sign up ok, new id=%d, next add other info", dbSignUp.ID)
- // 2.把id写入pay/task/contract的sign_id字段中,然后分别将这三种信息插入到数据库
- for _, v := range arg.PayInfo {
- v.SignID = dbSignUp.ID
- v.Mid = dbSignUp.Mid
- if _, err = s.addPayInfo(tx, v); err != nil {
- log.Error("insert payinfo db fail, err=%+v", err)
- break
- }
- }
- for _, v := range arg.TaskInfo {
- v.SignID = dbSignUp.ID
- v.Mid = dbSignUp.Mid
- if _, err = s.addTaskInfo(tx, v); err != nil {
- log.Error("insert payinfo db fail, err=%+v", err)
- break
- }
- }
- for _, v := range arg.ContractInfo {
- v.SignID = dbSignUp.ID
- v.Mid = dbSignUp.Mid
- if _, err = s.addContractInfo(tx, v); err != nil {
- log.Error("insert payinfo db fail, err=%+v", err)
- break
- }
- }
- log.Info("add sign up, new id=%d, all info finish", dbSignUp.ID)
- index := []interface{}{}
- content := map[string]interface{}{
- "new": arg,
- "old": nil,
- "change_type": new([]int8),
- }
- // 上报添加的签约日志
- s.AddAuditLog(signmodel.SignUpLogBizID, signmodel.SignUpMidAdd, "新增", int64(arg.AdminID), arg.AdminName, []int64{int64(arg.Mid)}, index, content)
- return
- }
- // SignUpdate .
- func (s *Service) SignUpdate(context context.Context, arg *signmodel.SignUpArg) (result signmodel.CommonResponse, err error) {
- if arg == nil || arg.ID == 0 {
- log.Error("sign up arg is nil")
- return
- }
- // 处理合同信息
- var contractInfo []*signmodel.SignContractInfoArg
- for _, v := range arg.ContractInfo {
- if v == nil || strings.Trim(v.Filename, " ") == "" {
- continue
- }
- if strings.Trim(v.Filelink, " \n\r") == "" {
- err = model.ErrNoFileLink
- log.Error("no file link for contract, please upload file, arg=%v", arg)
- return
- }
- contractInfo = append(contractInfo, v)
- }
- arg.ContractInfo = contractInfo
- // 从context 里拿后台登录信息
- var bmContext, ok = context.(*blademaster.Context)
- if ok {
- uid, ok := util.GetContextValueInt64(bmContext, "uid")
- if ok {
- arg.AdminID = int(uid)
- }
- name, ok := util.GetContextValueString(bmContext, "username")
- if ok {
- arg.AdminName = name
- }
- }
- log.Info("add sign up, req=%+v, admin id=%d, admin name=%s", arg, arg.AdminID, arg.AdminName)
- // 预处理声明参数
- var (
- oriSignUp *signmodel.SignUp
- oriSignPayMap map[int64]*signmodel.SignPay
- oriSignTaskMap map[int64]*signmodel.SignTask
- oriSignContractMap map[int64]*signmodel.SignContract
- signPayIDMap, signTaskIDMap, signContractIDMap map[int64]struct{}
- delSignPayIDs, delSignTaskIDs, delSignContractIDs []int64
- changeType []int8
- signPays []*signmodel.SignPay
- signTasks []*signmodel.SignTask
- signContracts []*signmodel.SignContract
- fields = make(map[int8]struct{})
- signUp = &signmodel.SignUp{}
- oriSignUpArg = new(signmodel.SignUpArg)
- )
- // 从db获取签约信息 、付款信息、任务信息、合同信息
- if oriSignUp, oriSignPayMap, oriSignTaskMap, oriSignContractMap, err = s.crmdb.SignUpID(arg.ID); err != nil {
- log.Error("s.crmdb.SignUpID(%+d) error(%+v)", arg.ID, err)
- return
- }
- if oriSignUp.State == 1 || oriSignUp.State == 100 {
- err = fmt.Errorf("up签约已过期或者已被删除")
- return
- }
- // 把请求参数制作成签约up的db
- arg.CopyTo(signUp)
- // 请求的签约up信息和db的签约up信息做diff, fields包含了修改哪些信息
- signUp.Diff(oriSignUp, fields)
- // 把db内的签约信息制作成请求参数类型数据, 放入上报日志需要
- oriSignUpArg.SignUpBaseInfo.CopyFrom(oriSignUp)
- // 需要更新的付款信息的db id
- signPayIDMap = map[int64]struct{}{}
- // 对比请求的付款信息,diff 出变更的数据
- for _, v := range arg.PayInfo {
- var sp = &signmodel.SignPay{}
- v.CopyTo(sp)
- sp.Diff(oriSignPayMap, fields)
- sp.SignID = arg.ID
- sp.Mid = arg.Mid
- v.SignID = arg.ID
- v.Mid = arg.Mid
- signPays = append(signPays, sp)
- signPayIDMap[v.ID] = struct{}{}
- }
- // 把db内付款信息制作成上报日志需要结构
- for _, v := range oriSignPayMap {
- var pi = &signmodel.SignPayInfoArg{}
- pi.CopyFrom(v)
- pi.SignID = arg.ID
- pi.Mid = arg.Mid
- oriSignUpArg.PayInfo = append(oriSignUpArg.PayInfo, pi)
- if _, ok := signPayIDMap[v.ID]; !ok && v.ID != 0 {
- delSignPayIDs = append(delSignPayIDs, int64(v.ID))
- }
- }
- // 付款信息是否存在删除
- if len(delSignPayIDs) > 0 {
- fields[signmodel.ChangeSignPayHistory] = struct{}{}
- }
- // 需要更新的任务的db id
- signTaskIDMap = map[int64]struct{}{}
- // 对比请求的任务信息,diff 出变更的数据
- for _, v := range arg.TaskInfo {
- var st = &signmodel.SignTask{SignID: arg.ID, Mid: arg.Mid}
- v.CopyTo(st)
- st.Diff(oriSignTaskMap, fields)
- st.SignID = arg.ID
- st.Mid = arg.Mid
- v.SignID = arg.ID
- v.Mid = arg.Mid
- signTasks = append(signTasks, st)
- signTaskIDMap[v.ID] = struct{}{}
- }
- // 把db内任务信息制作成上报日志需要结构
- for _, v := range oriSignTaskMap {
- var ti = &signmodel.SignTaskInfoArg{}
- ti.CopyFrom(v)
- ti.SignID = arg.ID
- ti.Mid = arg.Mid
- oriSignUpArg.TaskInfo = append(oriSignUpArg.TaskInfo, ti)
- if _, ok := signTaskIDMap[v.ID]; !ok && v.ID != 0 {
- delSignTaskIDs = append(delSignTaskIDs, int64(v.ID))
- }
- }
- // 任务是否存在删除
- if len(delSignTaskIDs) > 0 {
- fields[signmodel.ChangeSignTaskHistory] = struct{}{}
- }
- // 需要更新的合同的db id
- signContractIDMap = map[int64]struct{}{}
- // 对比请求的合同信息,diff 出变更的数据
- for _, v := range arg.ContractInfo {
- var sc = &signmodel.SignContract{SignID: arg.ID, Mid: arg.Mid}
- v.CopyTo(sc)
- sc.Diff(oriSignContractMap, fields)
- sc.SignID = arg.ID
- sc.Mid = arg.Mid
- v.SignID = arg.ID
- v.Mid = arg.Mid
- signContracts = append(signContracts, sc)
- signContractIDMap[v.ID] = struct{}{}
- }
- // 把db内合同信息制作成上报日志需要结构
- for _, v := range oriSignContractMap {
- var si = &signmodel.SignContractInfoArg{}
- si.CopyFrom(v)
- si.SignID = arg.ID
- si.Mid = arg.Mid
- oriSignUpArg.ContractInfo = append(oriSignUpArg.ContractInfo, si)
- if _, ok := signContractIDMap[v.ID]; !ok && v.ID != 0 {
- delSignContractIDs = append(delSignContractIDs, int64(v.ID))
- }
- }
- // 合同是否存在删除
- if len(delSignContractIDs) > 0 {
- fields[signmodel.ChangeSignContractHistory] = struct{}{}
- }
- for k := range fields {
- changeType = append(changeType, k)
- }
- if len(changeType) == 0 {
- err = fmt.Errorf("up签约信息暂无修改")
- return
- }
- tx := s.crmdb.BeginTran(context)
- defer func() {
- if err != nil {
- tx.Rollback()
- } else {
- tx.Commit()
- }
- }()
- if _, err = s.crmdb.InsertSignUp(tx, signUp); err != nil {
- log.Error("fail to add into sign up db, req=%+v, err=%+v", arg, err)
- return
- }
- for _, v := range signPays {
- if _, err = s.crmdb.InsertPayInfo(tx, v); err != nil {
- log.Error("insert pay info db fail, err=%+v", err)
- break
- }
- }
- for _, v := range signTasks {
- if _, err = s.crmdb.InsertTaskInfo(tx, v); err != nil {
- log.Error("insert task info db fail, err=%+v", err)
- break
- }
- var (
- init bool
- sth *signmodel.SignTaskHistory
- )
- if sth, init, err = s.crmdb.GetOrCreateTaskHistory(tx, v); err != nil {
- log.Error("s.crmdb.GetOrCreateTaskHistory, err=%+v", err)
- break
- }
- if !init {
- sth.Attribute = v.Attribute
- sth.TaskCondition = v.TaskCondition
- sth.TaskType = v.TaskType
- if err = s.crmdb.UpSignTaskHistory(tx, sth); err != nil {
- log.Error("s.crmdb.UpSignTaskHistory, err=%+v", err)
- break
- }
- }
- }
- for _, v := range signContracts {
- if _, err = s.crmdb.InsertContractInfo(tx, v); err != nil {
- log.Error("insert contract info db fail, err=%+v", err)
- break
- }
- }
- if _, err = s.crmdb.DelPayInfo(tx, delSignPayIDs); err != nil {
- log.Error("delete task info db fail, err=%+v", err)
- return
- }
- if _, err = s.crmdb.DelTaskInfo(tx, delSignTaskIDs); err != nil {
- log.Error("delete task info db fail, err=%+v", err)
- return
- }
- if _, err = s.crmdb.DelSignContract(tx, delSignContractIDs); err != nil {
- log.Error("delete task info db fail, err=%+v", err)
- return
- }
- index := []interface{}{int64(arg.ID)}
- content := map[string]interface{}{
- "new": arg,
- "old": oriSignUpArg,
- "change_type": changeType,
- }
- // 上报变更信息
- s.AddAuditLog(signmodel.SignUpLogBizID, signmodel.SignUpMidUpdate, "修改", int64(arg.AdminID), arg.AdminName, []int64{int64(arg.Mid)}, index, content)
- return
- }
- // ViolationAdd .
- func (s *Service) ViolationAdd(context context.Context, arg *signmodel.ViolationArg) (result signmodel.CommonResponse, err error) {
- if arg == nil || arg.SignID == 0 {
- log.Error("violation add arg is nil")
- return
- }
- su := &signmodel.SignUp{}
- if err = s.crmdb.GetDb().Table(signmodel.TableSignUp).Where("id = ? AND state = 0", arg.SignID).Find(su).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("db fail, err=%+v", err)
- return
- }
- if err == gorm.ErrRecordNotFound {
- err = fmt.Errorf("签约ID(%d)不存在", arg.SignID)
- return
- }
- var bmContext, ok = context.(*blademaster.Context)
- if ok {
- uid, ok := util.GetContextValueInt64(bmContext, "uid")
- if ok {
- arg.AdminID = uid
- }
- name, ok := util.GetContextValueString(bmContext, "username")
- if ok {
- arg.AdminName = name
- }
- }
- log.Info("add sign up, req=%+v, admin id=%d, admin name=%s", arg, arg.AdminID, arg.AdminName)
- tx := s.crmdb.BeginTran(context)
- defer func() {
- if err != nil {
- tx.Rollback()
- } else {
- tx.Commit()
- }
- }()
- // 新增违约历史
- vh := &signmodel.SignViolationHistory{}
- arg.CopyTo(vh)
- if err = tx.Save(vh).Error; err != nil {
- log.Error("sign violation up fail, err=%+v", err)
- return
- }
- // 新增违约次数
- if err = tx.Table(signmodel.TableSignUp).Where("id = ?", arg.SignID).UpdateColumns(
- map[string]interface{}{
- "violation_times": gorm.Expr("violation_times + ?", 1),
- "admin_id": arg.AdminID,
- "admin_name": arg.AdminName,
- }).Error; err != nil {
- log.Error("sign up add violation times fail, err=%+v", err)
- }
- return
- }
- // ViolationRetract .
- func (s *Service) ViolationRetract(context context.Context, arg *signmodel.IDArg) (result signmodel.CommonResponse, err error) {
- var bmContext, ok = context.(*blademaster.Context)
- if ok {
- uid, ok := util.GetContextValueInt64(bmContext, "uid")
- if ok {
- arg.AdminID = uid
- }
- name, ok := util.GetContextValueString(bmContext, "username")
- if ok {
- arg.AdminName = name
- }
- }
- log.Info("add sign up, req=%+v, admin id=%d, admin name=%s", arg, arg.AdminID, arg.AdminName)
- tx := s.crmdb.BeginTran(context)
- defer func() {
- if err != nil {
- tx.Rollback()
- } else {
- tx.Commit()
- }
- }()
- // 删除违约历史
- if err = tx.Table(signmodel.TableSignViolationHistory).Where("id = ?", arg.ID).UpdateColumns(
- map[string]interface{}{
- "state": 100,
- "admin_id": arg.AdminID,
- "admin_name": arg.AdminName,
- }).Error; err != nil {
- log.Error("sign violation Retract fail, err=%+v", err)
- }
- // 减少违约次数
- if err = tx.Table(signmodel.TableSignUp).Where("id = ?", arg.SignID).UpdateColumns(
- map[string]interface{}{
- "violation_times": gorm.Expr("violation_times - ?", 1),
- "admin_id": arg.AdminID,
- "admin_name": arg.AdminName,
- }).Error; err != nil {
- log.Error("sign up dec violation times fail, err=%+v", err)
- }
- return
- }
- // ViolationList .
- func (s *Service) ViolationList(context context.Context, arg *signmodel.PageArg) (result *signmodel.ViolationResult, err error) {
- if arg == nil {
- log.Error("arg is nil")
- return
- }
- if arg.Page <= 0 {
- arg.Page = 1
- }
- if arg.Size <= 0 || arg.Size >= 50 {
- arg.Size = 20
- }
- result = new(signmodel.ViolationResult)
- result.Result = []*signmodel.ViolationArg{}
- result.Page = arg.Page
- result.Size = arg.Size
- var (
- count int
- offset = (arg.Page - 1) * arg.Size
- vhs = []*signmodel.SignViolationHistory{}
- )
- if err = s.crmdb.GetDb().Table(signmodel.TableSignViolationHistory).Where("sign_id = ?", arg.SignID).Count(&count).Error; err != nil {
- log.Error("violation count fail, err=%+v", err)
- return
- }
- if count <= 0 {
- return
- }
- result.TotalCount = count
- if err = s.crmdb.GetDb().Table(signmodel.TableSignViolationHistory).Where("sign_id = ?", arg.SignID).Order(fmt.Sprintf("%s %s", "mtime", "DESC")).
- Offset(offset).
- Limit(arg.Size).
- Find(&vhs).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("violationList fail, err=%+v", err)
- }
- for _, v := range vhs {
- var re = &signmodel.ViolationArg{}
- re.CopyFrom(v)
- result.Result = append(result.Result, re)
- }
- return
- }
- // AbsenceAdd .
- func (s *Service) AbsenceAdd(context context.Context, arg *signmodel.AbsenceArg) (result signmodel.CommonResponse, err error) {
- if arg == nil || arg.SignID == 0 {
- log.Error("violation add arg is nil")
- return
- }
- su := &signmodel.SignUp{}
- if err = s.crmdb.GetDb().Table(signmodel.TableSignUp).Where("id = ? AND state = 0", arg.SignID).Find(su).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("db fail, err=%+v", err)
- return
- }
- if err == gorm.ErrRecordNotFound {
- err = fmt.Errorf("签约ID(%d)不存在", arg.SignID)
- return
- }
- var Result struct {
- LeaveTimes int
- }
- if err = s.crmdb.GetDb().Table(signmodel.TableSignTaskAbsence).Select("SUM(absence_count) as leave_times").Where("sign_id = ? AND state = 0", arg.SignID).Scan(&Result).Error; err != nil {
- log.Error("sign task absence sum fail, err=%+v", err)
- return
- }
- var bmContext, ok = context.(*blademaster.Context)
- if ok {
- uid, ok := util.GetContextValueInt64(bmContext, "uid")
- if ok {
- arg.AdminID = uid
- }
- name, ok := util.GetContextValueString(bmContext, "username")
- if ok {
- arg.AdminName = name
- }
- }
- log.Info("add sign up, req=%+v, admin id=%d, admin name=%s", arg, arg.AdminID, arg.AdminName)
- tx := s.crmdb.BeginTran(context)
- defer func() {
- if err != nil {
- tx.Rollback()
- } else {
- tx.Commit()
- }
- }()
- var sth *signmodel.SignTaskHistory
- // 查询签约周期任务历史数据,没有新增
- if sth, err = s.getOrCreateTaskHistory(tx, arg.SignID); err != nil {
- log.Error("s.getOrCreateTaskHistory(%d), err=%+v", arg.SignID, err)
- return
- }
- // 增加请假历史
- ta := &signmodel.SignTaskAbsence{}
- arg.CopyTo(ta)
- ta.TaskHistoryID = sth.ID
- if err = tx.Save(ta).Error; err != nil {
- log.Error("sign task absence fail, err=%+v", err)
- return
- }
- // 新增请假历史
- if err = tx.Table(signmodel.TableSignUp).Where("id = ?", arg.SignID).UpdateColumns(
- map[string]interface{}{
- "leave_times": Result.LeaveTimes + arg.AbsenceCount,
- "admin_id": arg.AdminID,
- "admin_name": arg.AdminName,
- }).Error; err != nil {
- log.Error("sign up add leave time fail, err=%+v", err)
- }
- return
- }
- // get task history, if not exist, then will create it
- func (s *Service) getOrCreateTaskHistory(tx *gorm.DB, signID int64) (res *signmodel.SignTaskHistory, err error) {
- st := new(signmodel.SignTask)
- if err = s.crmdb.GetDb().Select("*").Where("sign_id = ?", signID).Find(&st).Error; err != nil {
- return
- }
- if res, _, err = s.crmdb.GetOrCreateTaskHistory(tx, st); err != nil {
- log.Error("s.crmdb.GetOrCreateTaskHistory, err=%+v", err)
- }
- return
- }
- // AbsenceRetract .
- func (s *Service) AbsenceRetract(context context.Context, arg *signmodel.IDArg) (result signmodel.CommonResponse, err error) {
- var bmContext, ok = context.(*blademaster.Context)
- if ok {
- uid, ok := util.GetContextValueInt64(bmContext, "uid")
- if ok {
- arg.AdminID = uid
- }
- name, ok := util.GetContextValueString(bmContext, "username")
- if ok {
- arg.AdminName = name
- }
- }
- log.Info("add sign up, req=%+v, admin id=%d, admin name=%s", arg, arg.AdminID, arg.AdminName)
- tx := s.crmdb.BeginTran(context)
- defer func() {
- if err != nil {
- tx.Rollback()
- } else {
- tx.Commit()
- }
- }()
- signTaskAbsences := &signmodel.SignTaskAbsence{}
- if err = s.crmdb.GetDb().Table(signmodel.TableSignTaskAbsence).Select("absence_count").Where("id = ? AND state = 0", arg.ID).Find(&signTaskAbsences).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("sign task absence_count fail, err=%+v", err)
- return
- }
- if err == gorm.ErrRecordNotFound {
- err = fmt.Errorf("签约ID(%d)的请假ID(%d)不存在", arg.SignID, arg.ID)
- return
- }
- // 删除请假历史
- if err = tx.Table(signmodel.TableSignTaskAbsence).Where("id = ?", arg.ID).UpdateColumns(
- map[string]interface{}{
- "state": 100,
- "admin_id": arg.AdminID,
- "admin_name": arg.AdminName,
- }).Error; err != nil {
- log.Error("task absence Retract fail, err=%+v", err)
- }
- // 减少请假次数
- if err = tx.Table(signmodel.TableSignUp).Where("id = ?", arg.SignID).UpdateColumns(
- map[string]interface{}{
- "leave_times": gorm.Expr("leave_times - ?", signTaskAbsences.AbsenceCount),
- "admin_id": arg.AdminID,
- "admin_name": arg.AdminName,
- }).Error; err != nil {
- log.Error("sign up dec leave times fail, err=%+v", err)
- }
- return
- }
- // AbsenceList .
- func (s *Service) AbsenceList(context context.Context, arg *signmodel.PageArg) (result *signmodel.AbsenceResult, err error) {
- if arg == nil {
- log.Error("arg is nil")
- return
- }
- if arg.Page <= 0 {
- arg.Page = 1
- }
- if arg.Size <= 0 || arg.Size >= 50 {
- arg.Size = 20
- }
- result = new(signmodel.AbsenceResult)
- result.Result = []*signmodel.AbsenceArg{}
- result.Page = arg.Page
- result.Size = arg.Size
- var (
- count int
- taskHisIDs []int64
- mst = make(map[int64]*signmodel.SignTaskHistory)
- offset = (arg.Page - 1) * arg.Size
- tas = []*signmodel.SignTaskAbsence{}
- sts = []*signmodel.SignTaskHistory{}
- su = &signmodel.SignUp{}
- )
- if err = s.crmdb.GetDb().Table(signmodel.TableSignUp).Where("id = ? AND state IN (0,1)", arg.SignID).Find(su).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("db fail, err=%+v", err)
- return
- }
- if err == gorm.ErrRecordNotFound {
- err = fmt.Errorf("up签约不存在")
- return
- }
- if err = s.crmdb.GetDb().Table(signmodel.TableSignTaskAbsence).Where("sign_id = ?", arg.SignID).Count(&count).Error; err != nil {
- log.Error("sign task absence count fail, err=%+v", err)
- return
- }
- if count <= 0 {
- return
- }
- result.TotalCount = count
- if err = s.crmdb.GetDb().Table(signmodel.TableSignTaskAbsence).Where("sign_id = ?", arg.SignID).Order(fmt.Sprintf("%s %s", "mtime", "DESC")).
- Offset(offset).
- Limit(arg.Size).
- Find(&tas).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("absenceList fail, err=%+v", err)
- }
- for _, v := range tas {
- taskHisIDs = append(taskHisIDs, v.TaskHistoryID)
- }
- if err = s.crmdb.GetDb().Table(signmodel.TableSignTaskHistory).Where("id IN (?) AND sign_id = ?", taskHisIDs, arg.SignID).Find(&sts).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("sign task history fail, err=%+v", err)
- return
- }
- for _, v := range sts {
- mst[v.ID] = v
- }
- for _, v := range tas {
- var (
- ok bool
- sDate, eDate time.Time
- st *signmodel.SignTaskHistory
- re = &signmodel.AbsenceArg{}
- )
- // 从任务历史里面获取签约周期
- if st, ok = mst[int64(v.TaskHistoryID)]; ok {
- if st.TaskType != signmodel.TaskTypeAccumulate {
- sDate, eDate = signmodel.GetTaskDuration(st.GenerateDate.Time(), st.TaskType)
- re.TaskBegin = xtime.Time(sDate.Unix())
- re.TaskEnd = xtime.Time(eDate.Unix())
- } else {
- re.TaskBegin = su.BeginDate
- re.TaskEnd = su.EndDate
- }
- }
- re.CopyFrom(v)
- result.Result = append(result.Result, re)
- }
- return
- }
- // ViewCheck .
- func (s *Service) ViewCheck(context context.Context, arg *signmodel.PowerCheckArg) (res *signmodel.PowerCheckReply, err error) {
- res = &signmodel.PowerCheckReply{}
- if arg == nil || arg.Mid == 0 {
- log.Error("view arg is nil")
- return
- }
- var count int64
- if err = s.crmdb.GetDb().Table(signmodel.TableSignUp).Where("mid = ?", arg.Mid).Count(&count).Error; err != nil {
- log.Error("db fail, err=%+v", err)
- return
- }
- if count > 0 {
- res.IsSign = true
- }
- var baseInfo upcrmmodel.UpBaseInfo
- if baseInfo, err = s.crmdb.QueryUpBaseInfo(arg.Mid, "active_tid"); err != nil && err != gorm.ErrRecordNotFound {
- log.Error("s.crmdb.QueryUpBaseInfo(%d), err=%+v", arg.Mid, err)
- return
- }
- if err == gorm.ErrRecordNotFound {
- err = nil
- return
- }
- for _, tid := range arg.TIDs {
- if tid == int16(baseInfo.ActiveTid) {
- res.IsPower = true
- return
- }
- }
- return
- }
- /*
- id, 最后插入的id
- */
- func (s *Service) addPayInfo(tx *gorm.DB, arg *signmodel.SignPayInfoArg) (id int64, err error) {
- if arg == nil {
- err = errors.New("add pay info nil pointer")
- return
- }
- var dbInfo signmodel.SignPay
- arg.CopyTo(&dbInfo)
- var _, e = s.crmdb.InsertPayInfo(tx, &dbInfo)
- err = e
- id = dbInfo.ID
- return
- }
- func (s *Service) addTaskInfo(tx *gorm.DB, arg *signmodel.SignTaskInfoArg) (id int64, err error) {
- if arg == nil {
- err = errors.New("add task info nil pointer")
- return
- }
- var dbInfo signmodel.SignTask
- arg.CopyTo(&dbInfo)
- if _, err = s.crmdb.InsertTaskInfo(tx, &dbInfo); err != nil {
- log.Error("s.crmdb.InsertTaskInfo(%+v) error(%+v)", &dbInfo, err)
- return
- }
- id = dbInfo.ID
- if _, _, err = s.crmdb.GetOrCreateTaskHistory(tx, &dbInfo); err != nil {
- log.Error("s.crmdb.GetOrCreateTaskHistory(%+v) error(%+v)", &dbInfo, err)
- }
- return
- }
- func (s *Service) addContractInfo(tx *gorm.DB, arg *signmodel.SignContractInfoArg) (id int64, err error) {
- if arg == nil {
- err = errors.New("add contract info nil pointer")
- return
- }
- var dbInfo signmodel.SignContract
- arg.CopyTo(&dbInfo)
- var _, e = s.crmdb.InsertContractInfo(tx, &dbInfo)
- err = e
- id = dbInfo.ID
- return
- }
- // type sortPayFunc func(p1, p2 *signmodel.SignPayInfoArg) bool
- // type paySorter struct {
- // datas []*signmodel.SignPayInfoArg
- // by sortPayFunc // Closure used in the Less method.
- // }
- // Len is part of sort.Interface.
- // func (s *paySorter) Len() int {
- // return len(s.datas)
- // }
- // // Swap is part of sort.Interface.
- // func (s *paySorter) Swap(i, j int) {
- // s.datas[i], s.datas[j] = s.datas[j], s.datas[i]
- // }
- // // Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
- // func (s *paySorter) Less(i, j int) bool {
- // return s.by(s.datas[i], s.datas[j])
- // }
- // func sortPayInfo(planets []*signmodel.SignPayInfoArg, sortfunc sortPayFunc) {
- // ps := &paySorter{
- // datas: planets,
- // by: sortfunc, // The Sort method's receiver is the function (closure) that defines the sort order.
- // }
- // sort.Sort(ps)
- // }
- // func sortByDueAsc(p1, p2 *signmodel.SignPayInfoArg) bool {
- // var v1, _ = time.Parse(upcrmmodel.TimeFmtDate, p1.DueDate)
- // var v2, _ = time.Parse(upcrmmodel.TimeFmtDate, p2.DueDate)
- // return v1.Before(v2)
- // }
- //SignQuery sign query
- func (s *Service) SignQuery(c context.Context, arg *signmodel.SignQueryArg) (res *signmodel.SignQueryResult, err error) {
- if arg == nil {
- log.Error("arg is nil")
- return
- }
- if arg.Page <= 0 {
- arg.Page = 1
- }
- if arg.IsDetail == signmodel.SignUpDetail {
- arg.Size = 5
- } else {
- if arg.Size <= 0 || arg.Size > 20 {
- arg.Size = 20
- }
- }
- var (
- count int
- mids []int64
- tids []int64
- signIDs []int64
- signTaskIDs []int64
- signTaskHistoryIDs []int64
- tpNames map[int64]string
- db = s.crmdb.GetDb()
- signUpHandle = db.Table(signmodel.TableSignUp)
- signPayHandle = db.Table(signmodel.TableSignPay)
- signContractHandle = db.Table(signmodel.TableSignContract)
- signTaskHistoryHandle = db.Table(signmodel.TableSignTaskHistory)
- signAbsenceHandle = db.Table(signmodel.TableSignTaskAbsence)
- signTaskHandle = db.Table(signmodel.TableSignTask)
- signUps = []*signmodel.SignUp{}
- signPayInfos = []*signmodel.SignPay{}
- signContractInfos = []*signmodel.SignContract{}
- signTaskHistorys = []*signmodel.SignTaskHistory{}
- signTaskAbsences = []*signmodel.SignTaskAbsence{}
- signTasks = []*signmodel.SignTask{}
- signUpBaseInfos = []*signmodel.SignUpBaseInfo{}
- signPayInfoMap = make(map[int64][]*signmodel.SignPayInfoArg)
- signContractInfoMap = make(map[int64][]*signmodel.SignContractInfoArg)
- signTaskHistoryMap = make(map[int64][]*signmodel.SignTaskHistoryArg)
- offset = (arg.Page - 1) * arg.Size
- )
- res = new(signmodel.SignQueryResult)
- res.Page = arg.Page
- res.Size = arg.Size
- res.Result = []*signmodel.SignUpsArg{}
- if len(arg.Tids) != 0 {
- signUpHandle = signUpHandle.Where("active_tid IN (?)", arg.Tids)
- }
- if arg.Mid != 0 {
- signUpHandle = signUpHandle.Where("mid = ?", arg.Mid)
- }
- if arg.DueSign != 0 {
- signUpHandle = signUpHandle.Where("due_warn = ?", 2)
- }
- if arg.DuePay != 0 {
- signUpHandle = signUpHandle.Where("pay_expire_state = ?", 2)
- }
- if arg.ExpireSign != 0 {
- signUpHandle = signUpHandle.Where("state = ?", 1)
- }
- if arg.Sex != -1 {
- signUpHandle = signUpHandle.Where("sex = ?", arg.Sex)
- }
- if len(arg.Country) != 0 {
- signUpHandle = signUpHandle.Where("country IN (?)", arg.Country)
- }
- if arg.ActiveTID != 0 {
- signUpHandle = signUpHandle.Where("active_tid = ?", arg.ActiveTID)
- }
- if arg.SignType != 0 {
- signUpHandle = signUpHandle.Where("sign_type = ?", arg.SignType)
- }
- if arg.TaskState != 0 {
- signUpHandle = signUpHandle.Where("task_state = ?", arg.TaskState)
- }
- if arg.SignBegin != 0 {
- signUpHandle = signUpHandle.Where("begin_date >= ?", arg.SignBegin)
- }
- if arg.SignEnd != 0 {
- signUpHandle = signUpHandle.Where("end_date <= ?", arg.SignEnd)
- }
- signUpHandle = signUpHandle.Where("state IN (0,1)")
- if err = signUpHandle.Count(&count).Error; err != nil {
- log.Error("signUps count fail, err=%+v", err)
- return
- }
- if count <= 0 {
- return
- }
- res.TotalCount = count
- if arg.IsDetail == signmodel.SignUpDetail {
- signUpHandle = signUpHandle.Order(fmt.Sprintf("%s %s", "id", "DESC"))
- } else {
- signUpHandle = signUpHandle.Order(fmt.Sprintf("%s %s", "mtime", "DESC"))
- }
- if err = signUpHandle.Offset(offset).Limit(arg.Size).Find(&signUps).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("signUps fail, err=%+v", err)
- return
- }
- for _, v := range signUps {
- var signUpBaseInfo = &signmodel.SignUpBaseInfo{}
- signUpBaseInfo.CopyFrom(v)
- signUpBaseInfos = append(signUpBaseInfos, signUpBaseInfo)
- signIDs = append(signIDs, v.ID)
- mids = append(mids, v.Mid)
- tids = append(tids, int64(v.ActiveTid))
- }
- tpNames = cache.GetTidName(tids...)
- var infosReply *accgrpc.InfosReply
- if infosReply, err = global.GetAccClient().Infos3(c, &accgrpc.MidsReq{Mids: mids, RealIp: metadata.String(c, metadata.RemoteIP)}); err != nil {
- log.Error("global.GetAccClient().Infos3(%+v) error(%+v)", mids, err)
- err = nil
- }
- if err = signPayHandle.Where("sign_id IN (?) AND state IN (0,1)", signIDs).Order(fmt.Sprintf("%s %s", "due_date", "ASC")).Find(&signPayInfos).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("sign pays fail, err=%+v", err)
- return
- }
- for _, v := range signPayInfos {
- var signPayInfo = &signmodel.SignPayInfoArg{}
- signPayInfo.CopyFrom(v)
- signPayInfoMap[v.SignID] = append(signPayInfoMap[v.SignID], signPayInfo)
- }
- if err = signContractHandle.Where("sign_id IN (?) AND state = 0", signIDs).Order(fmt.Sprintf("%s %s", "id", "ASC")).Find(&signContractInfos).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("sign contract fail, err=%+v", err)
- return
- }
- for _, v := range signContractInfos {
- var signContractInfo = &signmodel.SignContractInfoArg{}
- signContractInfo.CopyFrom(v)
- signContractInfoMap[v.SignID] = append(signContractInfoMap[v.SignID], signContractInfo)
- }
- // task
- if err = signTaskHandle.Where("sign_id IN (?) AND state = 0", signIDs).Find(&signTasks).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("sign task fail, err=%+v", err)
- return
- }
- for _, v := range signTasks {
- signTaskIDs = append(signTaskIDs, v.ID)
- }
- // task history NOTE: mtime 解决generate_date为累积时没用办法排序 有一定风险会错乱
- if arg.IsDetail == signmodel.SignUpList {
- var signTaskHistorySQL = `SELECT * FROM sign_task_history WHERE task_template_id IN (?) AND state IN (1,2) AND mtime = (SELECT MAX(mtime) FROM sign_task_history s
- WHERE s.sign_id=sign_task_history.sign_id AND s.task_template_id IN (?) AND s.state IN (1,2))`
- if err = signTaskHistoryHandle.Raw(signTaskHistorySQL, signTaskIDs, signTaskIDs).Find(&signTaskHistorys).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("sign task history fail, err=%+v", err)
- return
- }
- } else {
- if err = signTaskHistoryHandle.Where("task_template_id IN (?) AND state IN (1,2)", signTaskIDs).Order(fmt.Sprintf("%s %s", "id", "DESC")).Find(&signTaskHistorys).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("sign task history fail, err=%+v", err)
- return
- }
- }
- for _, v := range signTaskHistorys {
- signTaskHistoryIDs = append(signTaskHistoryIDs, v.ID)
- }
- if err = signAbsenceHandle.Raw("select sum(absence_count)as absence_count, task_history_id from sign_task_absence where task_history_id IN (?) AND state = 0 group by task_history_id", signTaskHistoryIDs).Find(&signTaskAbsences).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("sign absence fail, err=%+v", err)
- return
- }
- var hidMap = make(map[int64]int)
- for _, v := range signTaskAbsences {
- hidMap[v.TaskHistoryID] = v.AbsenceCount
- }
- for _, v := range signTaskHistorys {
- var (
- absenceCounter int
- signTaskHistoryArg = &signmodel.SignTaskHistoryArg{}
- )
- if count, ok := hidMap[v.ID]; ok {
- absenceCounter = count
- }
- signTaskHistoryArg.CopyFrom(v, absenceCounter)
- signTaskHistoryMap[v.SignID] = append(signTaskHistoryMap[v.SignID], signTaskHistoryArg)
- }
- for _, v := range signUpBaseInfos {
- if tpName, ok := tpNames[int64(v.ActiveTid)]; ok {
- v.TypeName = tpName
- }
- if infosReply != nil && infosReply.Infos != nil {
- if info, ok := infosReply.Infos[v.Mid]; ok {
- v.Name = info.Name
- }
- }
- if arg.IsDetail == signmodel.SignUpDetail {
- res.SignBaseInfo = v
- }
- var signUpsArg = &signmodel.SignUpsArg{}
- signUpsArg.SignUpBaseInfo = *v
- if signPayInfoArg, ok := signPayInfoMap[v.ID]; ok {
- signUpsArg.PayInfo = signPayInfoArg
- }
- if signContractInfoArg, ok := signContractInfoMap[v.ID]; ok {
- signUpsArg.ContractInfo = signContractInfoArg
- }
- if signTaskHistoryArg, ok := signTaskHistoryMap[v.ID]; ok {
- for _, sth := range signTaskHistoryArg {
- if sth.TaskType == signmodel.TaskTypeAccumulate {
- sth.TaskBegin = v.BeginDate
- sth.TaskEnd = v.EndDate
- }
- }
- signUpsArg.TaskHistoryInfo = signTaskHistoryArg
- }
- res.Result = append(res.Result, signUpsArg)
- }
- return
- }
- // SignQueryID .
- func (s *Service) SignQueryID(c context.Context, arg *signmodel.SignIDArg) (res *signmodel.SignUpArg, err error) {
- var (
- tpNames map[int64]string
- signUp *signmodel.SignUp
- signPayMap map[int64]*signmodel.SignPay
- signTaskMap map[int64]*signmodel.SignTask
- signContractMap map[int64]*signmodel.SignContract
- )
- res = new(signmodel.SignUpArg)
- if signUp, signPayMap, signTaskMap, signContractMap, err = s.crmdb.SignUpID(arg.ID); err != nil {
- log.Error("s.crmdb.SignUpID(%+d) error(%+v)", arg.ID, err)
- return
- }
- if signUp == nil {
- return
- }
- var infoReply *accgrpc.InfoReply
- if infoReply, err = global.GetAccClient().Info3(c, &accgrpc.MidReq{Mid: signUp.Mid, RealIp: metadata.String(c, metadata.RemoteIP)}); err != nil {
- log.Error("global.GetAccClient().Infos3(%d) error(%+v)", signUp.Mid, err)
- err = nil
- }
- tpNames = cache.GetTidName(int64(signUp.ActiveTid))
- res.SignUpBaseInfo.CopyFrom(signUp)
- if infoReply != nil && infoReply.Info != nil {
- res.SignUpBaseInfo.Name = infoReply.Info.Name
- }
- if tpName, ok := tpNames[int64(signUp.ActiveTid)]; ok {
- res.SignUpBaseInfo.TypeName = tpName
- }
- for _, v := range signPayMap {
- var payInfo = &signmodel.SignPayInfoArg{}
- payInfo.CopyFrom(v)
- res.PayInfo = append(res.PayInfo, payInfo)
- }
- if signPayMap != nil {
- sort.Slice(res.PayInfo, func(i int, j int) bool {
- return res.PayInfo[i].DueDate < res.PayInfo[j].DueDate
- })
- }
- for _, v := range signTaskMap {
- var taskInfo = &signmodel.SignTaskInfoArg{}
- taskInfo.CopyFrom(v)
- res.TaskInfo = append(res.TaskInfo, taskInfo)
- }
- if signTaskMap != nil {
- sort.Slice(res.TaskInfo, func(i int, j int) bool {
- return res.TaskInfo[i].ID < res.TaskInfo[j].ID
- })
- }
- for _, v := range signContractMap {
- var contractInfo = &signmodel.SignContractInfoArg{}
- contractInfo.CopyFrom(v)
- res.ContractInfo = append(res.ContractInfo, contractInfo)
- }
- if signContractMap != nil {
- sort.Slice(res.ContractInfo, func(i int, j int) bool {
- return res.ContractInfo[i].ID < res.ContractInfo[j].ID
- })
- }
- return
- }
- // SignPayComplete complete sign pay
- func (s *Service) SignPayComplete(con context.Context, arg *signmodel.SignPayCompleteArg) (result signmodel.SignPayCompleteResult, err error) {
- var affectedrow, e = s.crmdb.PayComplete(arg.IDs)
- if e != nil {
- err = e
- log.Error("fail to complete pay task, err=%+v", e)
- return
- }
- log.Info("complete pay, id=%+v, affected row=%d", arg.IDs, affectedrow)
- return
- }
- // SignCheckExist check sign up has an valid contract
- func (s *Service) SignCheckExist(c context.Context, arg *signmodel.SignCheckExsitArg) (result signmodel.SignCheckExsitResult, err error) {
- result.Exist, err = s.crmdb.CheckUpHasValidContract(arg.Mid, time.Now())
- if err != nil {
- log.Error("check up has valid contract fail, err=%+v", err)
- }
- return
- }
- // Countrys .
- func (s *Service) Countrys(c context.Context, arg *signmodel.CommonArg) (res *signmodel.SignCountrysReply, err error) {
- var (
- signUp []*signmodel.SignUp
- db = s.crmdb.GetDb()
- signUpHandle = db.Table(signmodel.TableSignUp)
- )
- res = new(signmodel.SignCountrysReply)
- if err = signUpHandle.Raw("select DISTINCT(country) from sign_up").Find(&signUp).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("sign up fail, err=%+v", err)
- }
- if err == gorm.ErrRecordNotFound {
- err = nil
- return
- }
- for _, v := range signUp {
- if v.Country == "" {
- continue
- }
- res.List = append(res.List, v.Country)
- }
- return
- }
- // Tids .
- func (s *Service) Tids(c context.Context, arg *signmodel.CommonArg) (res *signmodel.SignTidsReply, err error) {
- var (
- tids []int64
- signUp []*signmodel.SignUp
- db = s.crmdb.GetDb()
- signUpHandle = db.Table(signmodel.TableSignUp)
- )
- res = new(signmodel.SignTidsReply)
- if err = signUpHandle.Raw("select DISTINCT(active_tid) from sign_up").Find(&signUp).Error; err != nil && err != gorm.ErrRecordNotFound {
- log.Error("sign up fail, err=%+v", err)
- }
- if err == gorm.ErrRecordNotFound {
- err = nil
- return
- }
- for _, v := range signUp {
- if v.ActiveTid == 0 {
- continue
- }
- tids = append(tids, int64(v.ActiveTid))
- }
- res.List = cache.GetTidName(tids...)
- return
- }
|