123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- package yb
- import (
- "errors"
- "fmt"
- "hongze/hz_crm_api/models"
- "hongze/hz_crm_api/models/company"
- "hongze/hz_crm_api/models/system"
- "hongze/hz_crm_api/models/yb"
- "hongze/hz_crm_api/models/yb/response"
- "hongze/hz_crm_api/services"
- "hongze/hz_crm_api/services/alarm_msg"
- "hongze/hz_crm_api/utils"
- "strconv"
- "strings"
- "time"
- )
- // GetQuestionList 问题列表
- func GetQuestionList(condition string, pars []interface{}, orderStr string, startSize, pageSize int) (total int, resp *response.CommunityQuestionListResp, err error) {
- resp = new(response.CommunityQuestionListResp)
- total, list, e := yb.GetCommunityQuestionList(condition, pars, orderStr, startSize, pageSize)
- if e != nil {
- err = errors.New("获取问题列表失败 Err:" + e.Error())
- return
- }
- if len(list) == 0 {
- return
- }
- // 判断是否存在已禁用的回复人, 需要重新分配回复人
- adminIdArr := make([]string, 0)
- questionLen := len(list)
- userIdArr := make([]string, 0)
- for i := 0; i < questionLen; i++ {
- if list[i].ReplierAdminId > 0 {
- adminIdArr = append(adminIdArr, strconv.Itoa(list[i].ReplierAdminId))
- }
- userIdArr = append(userIdArr, strconv.Itoa(list[i].UserId))
- }
- adminIds := strings.Join(adminIdArr, ",")
- adminList, e := system.GetSysAdminByIds(adminIds)
- adminLen := len(adminList)
- adminEnableMap := make(map[int]int, 0)
- if adminLen > 0 {
- for i := 0; i < adminLen; i++ {
- adminEnableMap[adminList[i].AdminId] = adminList[i].Enabled
- }
- }
- // 是否有提问人详情(可能存在提问人被删除的情况,无详情)
- userDetailMap := make(map[int]bool, 0)
- if len(userIdArr) > 0 {
- userIdStr := strings.Join(userIdArr, ",")
- userList, e := company.GetFiccCompanyUserByUserIds(userIdStr)
- if e != nil {
- err = errors.New("获取提问人列表信息失败, Err:" + e.Error())
- return
- }
- for i := range userList {
- userDetailMap[int(userList[i].UserId)] = true
- }
- }
- respList := make([]*response.CommunityQuestionItem, 0)
- for _, v := range list {
- // 根据回复人被禁用/待回答/已推送消息判断是否需要重新分配
- needReset := false
- adminEnable := 1
- if v.ReplierAdminId > 0 {
- adminEnable = adminEnableMap[v.ReplierAdminId]
- }
- if adminEnable == 0 && v.ReplyStatus == 2 && v.MsgSendStatus >= 1 {
- needReset = true
- }
- item := &response.CommunityQuestionItem{
- CommunityQuestionId: v.CommunityQuestionId,
- UserId: v.UserId,
- Mobile: v.Mobile,
- RealName: v.RealName,
- QuestionContent: v.QuestionContent,
- ReplierUserId: v.ReplierUserId,
- ReplierAdminId: v.ReplierAdminId,
- ReplierRealName: v.ReplierRealName,
- ReplierAvatar: v.ReplierAvatar,
- ResearchGroupFirstId: v.ResearchGroupFirstId,
- ResearchGroupSecondId: v.ResearchGroupSecondId,
- ResearchGroupFirstName: v.ResearchGroupFirstName,
- ResearchGroupSecondName: v.ResearchGroupSecondName,
- ReplyStatus: v.ReplyStatus,
- MsgSendStatus: v.MsgSendStatus,
- NeedRedistribute: needReset,
- CreateTime: v.CreateTime.Format(utils.FormatDateTime),
- ReplyTime: v.ReplyTime.Format(utils.FormatDateTime),
- ClickNum: v.ClickNum,
- UserQaCount: v.UserQaCount,
- UserHasDetail: userDetailMap[v.UserId],
- StopReason: v.StopReason,
- }
- respList = append(respList, item)
- }
- // 数量统计
- countList, e := yb.GetCommunityQuestionCount()
- if e != nil {
- err = errors.New("获取问题数量统计失败 Err:" + e.Error())
- return
- }
- respCount := new(response.CommunityQuestionCount)
- for _, v := range countList {
- if v.ReplyStatus == 1 {
- respCount.Free = v.Total
- continue
- }
- if v.ReplyStatus == 2 {
- respCount.Wait = v.Total
- continue
- }
- if v.ReplyStatus == 3 {
- respCount.Replied = v.Total
- continue
- }
- }
- respCount.Total = respCount.Free + respCount.Wait + respCount.Replied
- resp.List = respList
- resp.Count = respCount
- return
- }
- func GetQuestionClickLogList(questionId, startSize, pageSize int) (pageTotal int64, resp *response.QuestionClickLogListResp, err error) {
- questionInfo, e := yb.GetQuestionById(questionId)
- if e != nil {
- err = errors.New("提问信息有误 Err:" + e.Error())
- return
- }
- resp = new(response.QuestionClickLogListResp)
- list, e := yb.GetAudioLogListByQuestionId(questionId, startSize, pageSize)
- if e != nil {
- err = errors.New("获取问题列表失败 Err:" + e.Error())
- return
- }
- pageTotal, err = yb.GetAudioLogListTotalByQuestionId(questionId)
- if err != nil {
- err = errors.New("查询该提问列表总点击量失败 Err:" + err.Error())
- return
- }
- count, err := yb.GetAudioLogTotalByQuestionId(questionId)
- if err != nil {
- err = errors.New("查询该提问总点击量失败 Err:" + err.Error())
- return
- }
- resp.Count = int(count)
- resp.QuestionContent = questionInfo.QuestionContent
- if len(list) == 0 {
- return
- }
- userIds := ""
- for _, v := range list {
- userIds += ", " + (strconv.Itoa(v.UserId))
- }
- companyUsersMap := make(map[int]*company.CompanyUser)
- if userIds != "" {
- userIds = strings.Trim(userIds, ",")
- //查询用户相关的客户信息
- companyUserList, tErr := company.GetFiccCompanyUserByUserIds(userIds)
- if tErr != nil {
- err = errors.New("获取客户信息失败 Err:" + tErr.Error())
- return
- }
- for _, v := range companyUserList {
- companyUsersMap[int(v.UserId)] = v
- }
- }
- respList := make([]*response.QuestionClickLogListItem, 0)
- for _, v := range list {
- tmp := new(response.QuestionClickLogListItem)
- tmp.UserId = v.UserId
- tmp.ClickNum = v.ClickNum
- tmp.LastCreateTime = v.LastCreateTime
- tmp.SourceAgent = v.NewSourceAgent
- if u, ok := companyUsersMap[v.UserId]; ok {
- tmp.RealName = u.RealName
- tmp.CompanyName = u.CompanyName
- tmp.CompanyStatus = u.Status
- tmp.CompanyId = u.CompanyId
- }
- respList = append(respList, tmp)
- }
- resp.List = respList
- return
- }
- // GetQuestionCompanyUser 获取提问者详情
- func GetQuestionCompanyUser(questionId int) (ret *response.QuestionCompanyUser, err error) {
- questionInfo, e := yb.GetQuestionById(questionId)
- if e != nil {
- err = errors.New("提问信息有误 Err:" + e.Error())
- return
- }
- companyUserList, err := company.GetFiccCompanyUserByUserIds(strconv.Itoa(questionInfo.UserId))
- if err != nil {
- err = errors.New("获取客户信息失败 Err:" + err.Error())
- return
- }
- if len(companyUserList) > 0 {
- item := companyUserList[0]
- ret = &response.QuestionCompanyUser{
- UserId: int(item.UserId),
- CompanyStatus: item.Status,
- CompanyName: item.CompanyName,
- RealName: item.RealName,
- CompanyId: item.CompanyId,
- QuestionContent: questionInfo.QuestionContent,
- CommunityQuestionId: questionInfo.CommunityQuestionId,
- SellerName: item.SellerName,
- }
- } else {
- err = errors.New("用户不存在")
- return
- }
- return
- }
- // DistributeQuestion 分配回复人
- func DistributeQuestion(questionId, adminId, researchGroupFirstId, researchGroupSecondId, distributeId int) (errMsg string, err error) {
- errMsg = "操作成功"
- // 校验提问信息
- item, e := yb.GetQuestionById(questionId)
- if e != nil {
- errMsg = "分配失败, 提问信息有误"
- err = errors.New("提问信息有误 Err:" + e.Error())
- return
- }
- contentRune := []rune(item.QuestionContent)
- if len(contentRune) > 28 {
- errMsg = "问题字数不可超过28个字符"
- err = errors.New("问题字数不可超过28个字符")
- return
- }
- if item.ReplyStatus == 3 {
- errMsg = "分配失败, 回复状态有误"
- err = errors.New(fmt.Sprintf("分配失败, 回复状态有误, ReplyStatus:%d", item.ReplyStatus))
- return
- }
- // 获取研究员信息
- adminInfo, e := system.GetSysAdminById(adminId)
- if e != nil {
- errMsg = "分配失败, 研究员信息有误"
- err = errors.New("研究员信息有误 Err:" + e.Error())
- return
- }
- if adminInfo.Mobile == "" {
- errMsg = "分配失败, 研究员手机号有误"
- err = errors.New("研究员手机号为空")
- return
- }
- if adminInfo.OpenId == "" {
- errMsg = "该研究员未关注公众号,无法收到消息通知"
- err = errors.New("该研究员未关注公众号,无法收到消息通知")
- return
- }
- // 获取研究员关联的联系人信息
- companyId := 16
- userInfo, e := models.GetWxUserByCompanyIdAndMobile(companyId, adminInfo.Mobile)
- if e != nil {
- if e.Error() == utils.ErrNoRow() {
- errMsg = "分配失败, 未找到研究员手机号对应的联系人信息"
- err = errors.New("未获取到相关联系人信息")
- return
- }
- errMsg = "分配失败"
- err = errors.New("获取手机号所属联系人失败, Err:" + e.Error())
- return
- }
- // 回复人openid, 此处可能会出现取不到openid的情况, 可直接忽略掉
- replierUserId := int(userInfo.UserId)
- replierOpenid := ""
- // 研究员研究方向分组-研报10.0替换成标签库
- //firstGroup, e := system.GetResearchGroupById(researchGroupFirstId)
- firstGroup, e := models.GetVarietyClassifyById(researchGroupFirstId)
- if e != nil {
- errMsg = "分配失败, 一级分组信息有误"
- err = errors.New("获取一级分组信息失败, Err:" + e.Error())
- return
- }
- //secondGroup, e := system.GetResearchGroupById(researchGroupSecondId)
- secondGroup, e := models.GetVarietyTagById(researchGroupSecondId)
- if e != nil {
- errMsg = "分配失败, 二级分组信息有误"
- err = errors.New("获取二级分组信息失败, Err:" + e.Error())
- return
- }
- // 更新提问信息
- updateCols := make([]string, 0)
- updateCols = append(updateCols, "ReplierUserId", "ReplierOpenid", "ReplierAdminId", "ReplierRealName", "ReplierAvatar",
- "ResearchGroupFirstId", "ResearchGroupSecondId", "ResearchGroupFirstName", "ResearchGroupSecondName", "VarietyTagId", "VarietyTagName",
- "DistributeAdminId", "DistributeTime", "ReplyStatus", "ReplierIsRead", "MsgSendStatus", "ModifyTime")
- item.ReplierUserId = replierUserId
- item.ReplierOpenid = replierOpenid
- item.ReplierAdminId = adminId
- item.ReplierRealName = adminInfo.RealName
- item.ReplierAvatar = adminInfo.AdminAvatar
- item.ResearchGroupFirstId = researchGroupFirstId
- item.ResearchGroupSecondId = researchGroupSecondId
- item.ResearchGroupFirstName = firstGroup.ClassifyName
- item.ResearchGroupSecondName = secondGroup.TagName
- item.VarietyTagId = secondGroup.VarietyTagId
- item.VarietyTagName = secondGroup.TagName
- item.DistributeAdminId = distributeId
- item.DistributeTime = time.Now().Local()
- item.ReplyStatus = 2
- item.ReplierIsRead = 0
- item.MsgSendStatus = 0
- item.ModifyTime = time.Now().Local()
- if e := item.Update(updateCols); e != nil {
- errMsg = "分配失败,更新提问信息失败"
- err = errors.New("更新提问信息失败, Err:" + e.Error())
- }
- return
- }
- // SoftDeleteQuestion 删除问题
- func SoftDeleteQuestion(questionId int) (err error) {
- if _, e := yb.GetQuestionById(questionId); e != nil {
- err = errors.New("提问信息有误 Err:" + e.Error())
- return
- }
- if e := yb.DeleteQuestion(questionId); e != nil {
- err = errors.New("删除提问失败 Err:" + e.Error())
- }
- // 删除问答后的逻辑处理
- go afterDeleteQuestion(questionId)
- return
- }
- // SendMsgToReplier 推送消息给回复人
- func SendMsgToReplier(questionId int) (errMsg string, err error) {
- errMsg = "推送成功"
- item, e := yb.GetQuestionById(questionId)
- if e != nil {
- errMsg = "问答信息有误"
- err = errors.New("提问信息有误, Err:" + e.Error())
- return
- }
- if item.MsgSendStatus >= 1 {
- return
- }
- if item.ReplierUserId == 0 {
- errMsg = "请先分配回复人"
- err = errors.New("未分配回复人, 不可推送")
- return
- }
- // 回复人openid为空时查询当前是否已有openid
- updateCols := make([]string, 0)
- // 找到研究员的手机号,并查到管理员绑定的账号,找到对应的openid
- adminInfo, e := system.GetSysAdminById(item.ReplierAdminId)
- if e != nil {
- errMsg = "发送失败, 研究员账号查询失败"
- err = errors.New("发送失败, 研究员账号查询失败, Err:" + e.Error())
- return
- }
- if adminInfo.OpenId == "" {
- errMsg = "该研究员未关注公众号,无法发送消息通知"
- err = errors.New("回复人openid为空, 不可推送")
- return
- }
- // 推送消息
- if e := services.SendYbQuestionDistributeWxMsg(item.CommunityQuestionId, adminInfo.AdminId, adminInfo.OpenId, item.QuestionContent, ""); e != nil {
- err = errors.New("推送模板消息失败, Err:" + e.Error())
- return
- }
- // 更新问答信息
- updateCols = append(updateCols, "ModifyTime", "MsgSendStatus")
- item.ModifyTime = time.Now().Local()
- item.MsgSendStatus = 1
- if e := item.Update(updateCols); e != nil {
- err = errors.New("更新问答信息失败, Err:" + e.Error())
- }
- return
- }
- // EditQuestion 编辑问题
- func EditQuestion(questionId int, content string) (errMsg string, err error) {
- item, e := yb.GetQuestionById(questionId)
- if e != nil {
- errMsg = "提问信息有误"
- err = errors.New("提问信息有误 Err:" + e.Error())
- return
- }
- if item.MsgSendStatus >= 1 {
- errMsg = "问题状态有误,不可编辑"
- err = errors.New(fmt.Sprintf("问题状态不可编辑, MsgSendStatus:%d", item.MsgSendStatus))
- return
- }
- updateCols := make([]string, 0)
- updateCols = append(updateCols, "QuestionContent", "ModifyTime")
- item.QuestionContent = content
- item.ModifyTime = time.Now().Local()
- if e := item.Update(updateCols); e != nil {
- errMsg = "更新提问信息失败"
- err = errors.New("更新提问信息失败, Err:" + e.Error())
- }
- return
- }
- // CheckCommunityQuestionPermission 查询当前操作用户是否运营管理员权限
- func CheckCommunityQuestionPermission(adminId int) (errMsg string, err error) {
- roleInfo, e := system.GetSysRoleByRoleTypeCode("yb_question_admin")
- if e != nil {
- errMsg = "角色信息有误"
- if e.Error() == utils.ErrNoRow() {
- err = errors.New("角色不存在, Err: " + e.Error())
- return
- }
- err = errors.New("角色信息有误, Err: " + e.Error())
- return
- }
- _, e = system.GetRoleIdsByAdminIdRoleId(adminId, roleInfo.RoleId)
- if e != nil {
- errMsg = "无权操作"
- err = errors.New("无权操作, Err: " + e.Error())
- return
- }
- return
- }
- // afterDeleteQuestion 删除问答后的逻辑处理
- func afterDeleteQuestion(questionId int) {
- var err error
- defer func() {
- if err != nil {
- go alarm_msg.SendAlarmMsg("问答信息删除后,标记站内消息失败"+time.Now().Format(utils.FormatDateTime)+";Err:"+err.Error(), 3)
- }
- }()
- err = company.CancelCompanyApprovalMessage(questionId, services.CompanyApprovalMessageSourceTypeByQuestion)
- return
- }
- // TransferQuestion 转移问题并通知
- func TransferQuestion(questionId, adminId, researchGroupFirstId, researchGroupSecondId, distributeId int, distributeName string) (errMsg string, err error) {
- errMsg = "操作失败"
- // 校验提问信息
- item, e := yb.GetQuestionById(questionId)
- if e != nil {
- errMsg = "转移失败, 提问信息有误"
- err = errors.New("提问信息有误 Err:" + e.Error())
- return
- }
- if item.ReplyStatus != yb.ReplyStatusWait {
- errMsg = "当前状态不可转移"
- err = errors.New("回复状态有误")
- return
- }
- // 获取分类
- classifyItem, e := models.GetVarietyClassifyById(researchGroupFirstId)
- if e != nil {
- err = errors.New("获取问答标签分类失败 Err:" + e.Error())
- return
- }
- // 获取标签
- tagItem, e := models.GetVarietyTagById(researchGroupSecondId)
- if e != nil {
- err = errors.New("获取问答标签失败 Err:" + e.Error())
- return
- }
- // 获取研究员信息失败
- researcher, e := system.GetResearcherAdminAndWxUserByAdminId(adminId)
- if e != nil {
- errMsg = "该研究员未关注公众号或无法正确接收模板消息"
- err = errors.New("获取研究员信息失败 Err:" + e.Error())
- return
- }
- // 更新问答
- nowTime := time.Now().Local()
- updateCols := []string{
- "ReplierIsRead", "ReplierUserId", "ReplierAdminId", "ReplierRealName", "ResearchGroupFirstId", "ResearchGroupFirstName",
- "ResearchGroupSecondId", "ResearchGroupSecondName", "VarietyTagId", "VarietyTagName", "DistributeAdminId", "DistributeTime", "ModifyTime",
- }
- item.ReplierIsRead = 0
- item.ReplierUserId = researcher.UserId
- item.ReplierAdminId = researcher.AdminId
- item.ReplierRealName = researcher.AdminName
- item.ResearchGroupFirstId = classifyItem.VarietyClassifyId
- item.ResearchGroupFirstName = classifyItem.ClassifyName
- item.ResearchGroupSecondId = tagItem.VarietyTagId
- item.ResearchGroupSecondName = tagItem.TagName
- item.VarietyTagId = tagItem.VarietyTagId
- item.VarietyTagName = tagItem.TagName
- item.DistributeAdminId = distributeId
- item.DistributeTime = nowTime
- item.ModifyTime = nowTime
- if e = item.Update(updateCols); e != nil {
- err = errors.New("更新问答失败 Err:" + e.Error())
- return
- }
- // 新增问答流程
- go func() {
- pro := new(yb.CommunityQuestionProcess)
- pro.CommunityQuestionId = item.CommunityQuestionId
- pro.TransferUserId = 0
- pro.TransferAdminId = distributeId
- pro.TransferAdminName = distributeName
- pro.ReplierUserId = researcher.UserId
- pro.ReplierAdminId = researcher.AdminId
- pro.ReplierAdminName = researcher.AdminName
- pro.VarietyClassifyId = classifyItem.VarietyClassifyId
- pro.VarietyTagId = tagItem.VarietyTagId
- pro.Remark = fmt.Sprintf("管理员%s转至%s", distributeName, researcher.AdminName)
- pro.ProcessType = yb.ProcessTypeTransfer
- pro.CreateTime = nowTime
- if e = pro.Create(); e != nil {
- return
- }
- }()
- // 推送转移模板消息给研究员
- go func() {
- remark := fmt.Sprintf("管理员%s移交了新的问答给您, 请点击详情尽快处理", distributeName)
- _ = services.SendYbQuestionDistributeWxMsg(item.CommunityQuestionId, researcher.AdminId, researcher.OpenId, item.QuestionContent, remark)
- }()
- return
- }
|