plat_followup.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. package plat
  2. import (
  3. "context"
  4. "database/sql"
  5. "strconv"
  6. "strings"
  7. "dashoo.cn/opms_libary/myerrors"
  8. distDao "d
  9. distDao "dashoo.cn/opms_parent/app/dao/base"
  10. "dashoo.cn/opms_parent/app/dao/cust"
  11. "dashoo.cn/opms_libary/myerrors"
  12. "github.com/gogf/gf/container/garray"
  13. "github.com/gogf/gf/frame/g"
  14. "github.com/gogf/gf/os/gtime"
  15. "github.com/gogf/gf/util/gconv"
  16. "dashoo.cn/opms_parent/app/dao/plat"
  17. model "dashoo.cn/opms_parent/app/model/plat"
  18. "dashoo.cn/opms_parent/app/service"
  19. )
  20. type followupService struct {
  21. *service.ContextService
  22. Dao *plat.PlatFollowupDao
  23. }
  24. func NewFollowupService(ctx context.Context) (svc *followupService, err error) {
  25. svc = new(followupService)
  26. if svc.ContextService, err = svc.Init(ctx); err != nil {
  27. return nil, err
  28. }
  29. svc.Dao = plat.NewPlatFollowupDao(svc.Tenant)
  30. return svc, nil
  31. }
  32. // 跟进记录信息列表
  33. func (s *followupService) GetList(req *model.SearchPlatFollowupReq) (total int, followupList []*model.PlatFollowup, err error) {
  34. followupModel := s.Dao.DataScope(s.Ctx)
  35. if req.CustId != "" {
  36. followupModel = followupModel.Where("cust_id", req.CustId)
  37. }
  38. if req.CustName != "" {
  39. followupModel = followupModel.WhereLike("cust_name", "%"+req.CustName+"%")
  40. }
  41. if req.TargetId != "" {
  42. followupModel = followupModel.Where("target_id", req.TargetId)
  43. }
  44. if req.TargetType != "" {
  45. followupModel = followupModel.Where("target_type", req.TargetType)
  46. }
  47. if req.TargetName != "" {
  48. followupModel = followupModel.WhereLike("target_name", "%"+req.TargetName+"%")
  49. }
  50. // 负责人查询
  51. if req.ManagerId != "" {
  52. followupModel = followupModel.Where("created_by", req.ManagerId)
  53. }
  54. if req.IsMyself == "1" {
  55. followupModel = followupModel.Where("created_by", s.GetCxtUserId())
  56. }
  57. total, err = followupModel.Count()
  58. if err != nil {
  59. g.Log().Error(err)
  60. err = myerrors.DbError("获取总行数失败。")
  61. return
  62. }
  63. err = followupModel.Page(req.GetPage()).Order("follow_date DESC").Scan(&followupList)
  64. return
  65. }
  66. // 添加信息
  67. func (s *followupService) Create(req *model.AddPlatFollowupReq) (err error) {
  68. platFollowup := new(model.PlatFollowup)
  69. var files []*model.PlatFollowupFile
  70. if err = gconv.Struct(req, platFollowup); err != nil {
  71. return
  72. }
  73. // 填充创建信息
  74. service.SetCreatedInfo(platFollowup, s.GetCxtUserId(), s.GetCxtUserName())
  75. // 填充更新信息
  76. //service.SetUpdatedInfo(platFollowup, s.GetCxtUserId(), s.GetCxtUserName())
  77. res, err := s.Dao.Insert(platFollowup)
  78. if err != nil {
  79. return
  80. }
  81. // 更新附件数据
  82. id, _ := res.LastInsertId()
  83. for _, file := range req.Files {
  84. var fileData model.PlatFollowupFile
  85. if err = gconv.Struct(file, &fileData); err != nil {
  86. return
  87. }
  88. fileData.FollowId = strconv.Itoa(int(id))
  89. // 填充创建信息
  90. service.SetCreatedInfo(&fileData, s.GetCxtUserId(), s.GetCxtUserName())
  91. // 填充更新信息
  92. //service.SetUpdatedInfo(fileData, s.GetCxtUserId(), s.GetCxtUserName())
  93. files = append(files, &fileData)
  94. }
  95. // 保存附件信息
  96. if len(files) > 0 {
  97. _, err = s.Dao.DB.Insert(plat.PlatFollowupFile.Table, files)
  98. if err != nil {
  99. return
  100. }
  101. }
  102. // 更新客户 最后跟进时间 字段
  103. toUpdate := map[string]interface{}{
  104. "follow_up_date": req.FollowDate,
  105. "follow_up_man": s.GetCxtUserName(),
  106. }
  107. _, err = s.Dao.DB.Update("cust_customer", toUpdate, "id = ?", req.CustId)
  108. if platFollowup.TargetType == "20" {
  109. // 更新客户 最后跟进时间 字段
  110. toUpdate := map[string]interface{}{
  111. projDao.ProjBusiness.C.FinalFollowTime: req.FollowDate,
  112. projDao.ProjBusiness.C.FinalFollowId: s.GetCxtUserId(),
  113. projDao.ProjBusiness.C.FinalFollowName: s.GetCxtUserName(),
  114. }
  115. _, err = s.Dao.DB.Update(projDao.ProjBusiness.Table, toUpdate, "id = ?", req.TargetId)
  116. }
  117. return
  118. }
  119. // 跟进记录信息列表:按照日期显示,并附带评论
  120. func (s *followupService) GetListByDay(req *model.SearchPlatFollowupReq) (total int, followupList []*model.FollowupInfoResp, err error) {
  121. filter := map[string]interface{}{}
  122. if req.TargetType == "20" && req.TargetId != "" {
  123. filter = map[string]interface{}{
  124. "target_id": req.TargetId,
  125. "orcols": "target_id",
  126. }
  127. } else if req.CustId != "" {
  128. filter = map[string]interface{}{
  129. "cust_id": req.CustId,
  130. "orcols": "cust_id",
  131. }
  132. } else if garray.NewStrArrayFrom(s.CxtUser.Roles, true).Contains("ProductLineManager") {
  133. var orCols []string
  134. filter = map[string]interface{}{}
  135. busIds, _ := projDao.NewProjBusinessDao(s.Tenant).DataScope(s.Ctx, "sale_id").Fields("id").Array()
  136. custIds, _ := cust.NewCustCustomerDao(s.Tenant).DataScope(s.Ctx, "sales_id").Where("is_public", "20").Fields("id").Array()
  137. distributorIds, _ := distDao.NewBaseDistributorDao(s.Tenant).Fields("id").Array()
  138. if len(busIds) > 0 {
  139. filter["target_type='20' AND target_id"] = busIds
  140. orCols = append(orCols, "target_type='20' AND target_id")
  141. }
  142. if len(custIds) > 0 {
  143. filter["target_type='10' AND target_id"] = custIds
  144. orCols = append(orCols, "target_type='10' AND target_id")
  145. }
  146. if len(distributorIds) > 0 {
  147. filter["target_type='50' AND target_id"] = distributorIds
  148. orCols = append(orCols, "target_type='50' AND target_id")
  149. }
  150. filter["orcols"] = orCols
  151. } else {
  152. if s.DataScope["userIds"] != "-1" {
  153. var orCols []string
  154. filter = map[string]interface{}{}
  155. custIds, _ := cust.NewCustCustomerDao(s.Tenant).DataScope(s.Ctx, "sales_id").Where("is_public", "20").Fields("id").Array()
  156. distributorModel := &distDao.NewBaseDistributorDao(s.Tenant).BaseDistributorDao
  157. if garray.NewStrArrayFrom(s.CxtUser.Roles, true).Contains("SalesEngineer") {
  158. distributorModel = distributorModel.DataScope(s.Ctx, "belong_sale_id")
  159. }
  160. distributorIds, _ := distributorModel.Fields("id").Array()
  161. if len(custIds) > 0 {
  162. filter["cust_id"] = custIds
  163. orCols = append(orCols, "cust_id")
  164. }
  165. if len(distributorIds) > 0 {
  166. filter["target_type='50' AND target_id"] = distributorIds
  167. orCols = append(orCols, "target_type='50' AND target_id")
  168. }
  169. filter["orcols"] = orCols
  170. }
  171. }
  172. followupModel := s.Dao.As("plat_followup").DataScope(s.Ctx, filter)
  173. // 用户仅有销售工程师角色展示自己的数据,其他人可以看到所有数据
  174. //if garray.NewStrArrayFrom(s.CxtUser.Roles, true).Contains("SalesEngineer") {
  175. // followupModel = followupModel.WhereIn("created_by", s.DataScope["userIds"])
  176. //}
  177. if req.CustId != "" {
  178. followupModel = followupModel.Where("cust_id", req.CustId)
  179. }
  180. if req.DistId != "" {
  181. followupModel = followupModel.Where("dist_id", req.DistId)
  182. }
  183. if req.CustName != "" {
  184. followupModel = followupModel.WhereLike("cust_name", "%"+req.CustName+"%")
  185. }
  186. if req.TargetId != "" {
  187. followupModel = followupModel.Where("target_id", req.TargetId)
  188. }
  189. if req.TargetType != "" {
  190. followupModel = followupModel.Where("target_type", req.TargetType)
  191. }
  192. if req.TargetName != "" {
  193. followupModel = followupModel.WhereLike("target_name", "%"+req.TargetName+"%")
  194. }
  195. if req.CreatedName != "" {
  196. followupModel = followupModel.WhereLike("plat_followup.created_name", "%"+req.CreatedName+"%")
  197. }
  198. // 负责人查询
  199. if req.ManagerId != "" {
  200. followupModel = followupModel.Where("plat_followup.created_by", req.ManagerId)
  201. }
  202. if req.IsMyself == "1" {
  203. followupModel = followupModel.Where("plat_followup.created_by", s.GetCxtUserId())
  204. }
  205. // 日期条件
  206. if req.DaysBeforeToday > 0 { // 获取前N天的跟进记录
  207. now := gtime.Now()
  208. begin := now.AddDate(0, 0, -req.DaysBeforeToday).Format("Y-m-d 00:00:00")
  209. followupModel = followupModel.Where("follow_date>=?", begin)
  210. }
  211. // 获取日期区间范围内的记录
  212. if req.BeginTime != "" && req.EndTime != "" {
  213. begin := strings.Split(req.BeginTime, " ")[0] + " 00:00:00"
  214. end := strings.Split(req.EndTime, " ")[0] + " 23:59:59"
  215. followupModel = followupModel.Where("follow_date>=? AND follow_date<=?", begin, end)
  216. }
  217. if req.FollowType != "" {
  218. followupModel = followupModel.Where("follow_type", req.FollowType)
  219. }
  220. //跟进记录销售 添加销售人权限
  221. arr := garray.NewStrArrayFrom(s.CxtUser.Roles, true)
  222. if arr.Len() == 1 && arr.Contains("SalesEngineer") && req.Sell != "" {
  223. followupModel = followupModel.Where("plat_followup.created_by", s.CxtUser.Id)
  224. }
  225. //total, err = followupModel.Count()
  226. //if err != nil {
  227. // g.Log().Error(err)
  228. // err = gerror.New("获取总行数失败")
  229. // return
  230. //}
  231. // 查询原始记录
  232. var originalFollowupList []model.FollowupInfo
  233. err = followupModel.Order("follow_date DESC").Scan(&originalFollowupList)
  234. if err != nil && err != sql.ErrNoRows {
  235. return
  236. }
  237. var followupIdArr = []int{-1}
  238. for _, followup := range originalFollowupList {
  239. followupIdArr = append(followupIdArr, followup.Id)
  240. }
  241. // 全部评论
  242. var allComments []*model.FollowupCommentEx
  243. commentMap := make(map[int]*model.FollowupCommentEx, 0)
  244. // 一级评论
  245. var comments []*model.FollowupCommentEx
  246. // 回复评论
  247. var replyComments []*model.FollowupCommentEx
  248. err = followupModel.InnerJoin(plat.PlatFollowupComment.Table, "plat_followup.id=plat_followup_comment.follow_id").Fields("plat_followup_comment.*").Structs(&allComments)
  249. if err != nil && err != sql.ErrNoRows {
  250. return
  251. }
  252. // 挑拣数据
  253. for index, comment := range allComments {
  254. commentMap[comment.Id] = allComments[index]
  255. if comment.Pid == 0 {
  256. comments = append(comments, allComments[index])
  257. } else {
  258. replyComments = append(replyComments, allComments[index])
  259. }
  260. }
  261. // 构造回复评论
  262. for _, replyComment := range replyComments {
  263. if _, ok := commentMap[replyComment.Pid]; ok {
  264. if commentMap[replyComment.Pid].ReplyComments == nil {
  265. commentMap[replyComment.Pid].ReplyComments = make([]*model.FollowupCommentEx, 0)
  266. }
  267. commentMap[replyComment.Pid].ReplyComments = append(commentMap[replyComment.Pid].ReplyComments, replyComment)
  268. }
  269. }
  270. // 构造数据
  271. var days []string
  272. followupMap := make(map[string][]*model.FollowupInfo, 0)
  273. followupCommentMap := make(map[int][]*model.FollowupCommentEx, 0)
  274. // 评论数据map
  275. for index, comment := range comments {
  276. if _, ok := followupCommentMap[comment.FollowId]; !ok {
  277. followupCommentMap[comment.FollowId] = make([]*model.FollowupCommentEx, 0)
  278. }
  279. followupCommentMap[comment.FollowId] = append(followupCommentMap[comment.FollowId], comments[index])
  280. }
  281. // 跟进记录map
  282. for index, followup := range originalFollowupList {
  283. if _, ok := followupMap[followup.FollowDate.Format("Y-m-d")]; !ok {
  284. days = append(days, followup.FollowDate.Format("Y-m-d"))
  285. followupMap[followup.FollowDate.Format("Y-m-d")] = make([]*model.FollowupInfo, 0)
  286. }
  287. if followup.Comments == nil {
  288. originalFollowupList[index].Comments = make([]*model.FollowupCommentEx, 0)
  289. }
  290. // 为跟进记录填充评论数据
  291. if _, ok := followupCommentMap[followup.Id]; ok {
  292. originalFollowupList[index].Comments = append(originalFollowupList[index].Comments, followupCommentMap[followup.Id]...)
  293. }
  294. originalFollowupList[index].CommentNumber = len(originalFollowupList[index].Comments)
  295. followupMap[followup.FollowDate.Format("Y-m-d")] = append(followupMap[followup.FollowDate.Format("Y-m-d")], &originalFollowupList[index])
  296. }
  297. for _, day := range days {
  298. var followup model.FollowupInfoResp
  299. followup.FollowDay = day
  300. followup.FollowupList = followupMap[day]
  301. followupList = append(followupList, &followup)
  302. }
  303. return
  304. }