business_cron.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. package proj
  2. import (
  3. "context"
  4. projDao "dashoo.cn/micro/app/dao/proj"
  5. model "dashoo.cn/micro/app/model/proj"
  6. "dashoo.cn/micro/app/service"
  7. "database/sql"
  8. "fmt"
  9. "github.com/360EntSecGroup-Skylar/excelize"
  10. "github.com/gogf/gf/container/gset"
  11. "github.com/gogf/gf/frame/g"
  12. "github.com/gogf/gf/os/gcron"
  13. "github.com/gogf/gf/os/glog"
  14. "github.com/gogf/gf/os/gtime"
  15. "github.com/gogf/gf/text/gstr"
  16. "github.com/gogf/gf/util/gconv"
  17. "github.com/smallnest/rpcx/share"
  18. "strings"
  19. "time"
  20. )
  21. // 初始化,创建每10分钟执行一次的定时任务
  22. func init() {
  23. // 定时任务
  24. spec := "0 0 9 * * *" // 每天凌晨9点执行
  25. gcron.AddSingleton(spec, businessFollowRun)
  26. //定时任务
  27. specs := "0 0 0 * * 1 *" //每周一一点
  28. gcron.AddSingleton(specs, businesspeopleUpReminder)
  29. }
  30. // businessFollowRun 项目跟进超时任务逻辑
  31. func businessFollowRun() {
  32. tenant := g.Config().GetString("micro_srv.tenant")
  33. if tenant == "" {
  34. glog.Error("定时任务租户码未设置,请前往配置")
  35. return
  36. }
  37. // 从配置中获取消息提醒设置
  38. configs, err := g.DB(tenant).Model("sys_config").Where("config_key IN ('SalesDirector','SalesAssociate', 'ProductLineManager')").FindAll()
  39. if err != nil && err != sql.ErrNoRows {
  40. glog.Error(err)
  41. return
  42. }
  43. // 销售总监用户Id,销售助理用户Id,产品线经理用户Id
  44. salesDirector, salesAssociate, productLineManager := []string{}, []string{}, []string{}
  45. for _, config := range configs {
  46. if config["config_key"].String() == "SalesDirector" {
  47. salesDirector = strings.Split(config["config_value"].String(), ",")
  48. } else if config["config_key"].String() == "SalesAssociate" {
  49. salesAssociate = strings.Split(config["config_value"].String(), ",")
  50. } else if config["config_key"].String() == "ProductLineManager" {
  51. productLineManager = strings.Split(config["config_value"].String(), ",")
  52. }
  53. }
  54. if len(salesDirector) > 0 {
  55. go businessFollowOverdueSalesDirector(tenant, salesDirector)
  56. }
  57. if len(salesAssociate) > 0 {
  58. go businessFollowOverdueSalesAssociate(tenant, salesAssociate)
  59. }
  60. if len(productLineManager) > 0 {
  61. businessFollowOverdueProductLineManager(tenant, productLineManager)
  62. }
  63. go businessFollowOverdueSalesEngineer(tenant)
  64. }
  65. type FollowOverdue struct {
  66. SaleId int64 `json:"saleId"`
  67. Count int64 `json:"count"`
  68. BusNames string `json:"busNames"`
  69. }
  70. // 超期3天提醒销售总监
  71. func businessFollowOverdueSalesDirector(tenant string, userIds []string) {
  72. now := gtime.Now().StartOfDay()
  73. LastWeekDay := now.AddDate(0, 0, -10)
  74. LastTwoWeekDay := now.AddDate(0, 0, -17)
  75. LastMonthDay := now.AddDate(0, -1, -3)
  76. businessA, businessB, businessC := new(FollowOverdue), new(FollowOverdue), new(FollowOverdue)
  77. err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
  78. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekDay).
  79. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&businessA)
  80. if err != nil {
  81. g.Log().Error("获取A类超期3天未跟进项目", err)
  82. }
  83. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
  84. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekDay).
  85. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&businessB)
  86. if err != nil {
  87. g.Log().Error("获取B类超期3天未跟进项目", err)
  88. }
  89. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
  90. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthDay).
  91. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&businessC)
  92. if err != nil {
  93. g.Log().Error("获取C类超期3天未跟进项目", err)
  94. }
  95. var msg string
  96. if businessA.Count > 0 {
  97. msg += fmt.Sprintf("您有超期3天未跟进A类项目%v个,项目名称分别为 %v,", businessA.Count, businessA.BusNames)
  98. }
  99. if businessB.Count > 0 {
  100. msg += fmt.Sprintf("您有超期3天未跟进B类项目%v个,项目名称分别为 %v,", businessB.Count, businessB.BusNames)
  101. }
  102. if businessC.Count > 0 {
  103. msg += fmt.Sprintf("您有超期3天未跟进C类项目%v个,项目名称分别为 %v,", businessC.Count, businessC.BusNames)
  104. }
  105. if msg != "" {
  106. businessNotifyMessage(userIds, gstr.TrimRightStr(msg, ","))
  107. }
  108. }
  109. // 超期1天后,超期3天 提醒销售助理
  110. func businessFollowOverdueSalesAssociate(tenant string, userIds []string) {
  111. now := gtime.Now().StartOfDay()
  112. LastWeekDay := now.AddDate(0, 0, -8)
  113. LastTwoWeekDay := now.AddDate(0, 0, -15)
  114. LastMonthDay := now.AddDate(0, -1, -1)
  115. LastWeekTridDay := now.AddDate(0, 0, -10)
  116. LastTwoWeekTridDay := now.AddDate(0, 0, -17)
  117. LastMonthTridDay := now.AddDate(0, -1, -3)
  118. businessATrid, businessBTrid, businessCTrid := new(FollowOverdue), new(FollowOverdue), new(FollowOverdue)
  119. businessA, businessB, businessC := new(FollowOverdue), new(FollowOverdue), new(FollowOverdue)
  120. err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
  121. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekDay).
  122. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&businessATrid)
  123. if err != nil {
  124. g.Log().Error("获取A类超期3天未跟进项目", err)
  125. }
  126. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
  127. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekDay).
  128. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(businessBTrid)
  129. if err != nil {
  130. g.Log().Error("获取B类超期3天未跟进项目", err)
  131. }
  132. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
  133. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthDay).
  134. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(businessCTrid)
  135. if err != nil {
  136. g.Log().Error("获取C类超期3天未跟进项目", err)
  137. }
  138. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
  139. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekDay).WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekTridDay).
  140. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(businessA)
  141. if err != nil {
  142. g.Log().Error("获取A类超期1天未跟进项目", err)
  143. }
  144. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
  145. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekDay).WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekTridDay).
  146. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(businessB)
  147. if err != nil {
  148. g.Log().Error("获取B类超期1天未跟进项目", err)
  149. }
  150. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
  151. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthDay).WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthTridDay).
  152. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(businessC)
  153. if err != nil {
  154. g.Log().Error("获取C类超期1天未跟进项目", err)
  155. }
  156. var msg string
  157. if businessATrid.Count > 0 {
  158. msg += fmt.Sprintf("您有超期3天未跟进A类项目%v个,项目名称分别为 %v,", businessATrid.Count, businessATrid.BusNames)
  159. }
  160. if businessBTrid.Count > 0 {
  161. msg += fmt.Sprintf("您有超期3天未跟进B类项目%v个,项目名称分别为 %v,", businessBTrid.Count, businessBTrid.BusNames)
  162. }
  163. if businessCTrid.Count > 0 {
  164. msg += fmt.Sprintf("您有超期3天未跟进C类项目%v个,项目名称分别为 %v,", businessCTrid.Count, businessCTrid.BusNames)
  165. }
  166. if businessA.Count > 0 {
  167. msg += fmt.Sprintf("您有超期1天未跟进A类项目%v个,项目名称分别为 %v,", businessA.Count, businessA.BusNames)
  168. }
  169. if businessB.Count > 0 {
  170. msg += fmt.Sprintf("您有超期1天未跟进B类项目%v个,项目名称分别为 %v,", businessB.Count, businessB.BusNames)
  171. }
  172. if businessC.Count > 0 {
  173. msg += fmt.Sprintf("您有超期1天未跟进C类项目%v个,项目名称分别为 %v,", businessC.Count, businessC.BusNames)
  174. }
  175. if msg != "" {
  176. businessNotifyMessage(userIds, gstr.TrimRightStr(msg, ","))
  177. }
  178. }
  179. // 在到达超期时间前3天进行提醒、当天进行提醒,这两次提醒只提醒销售工程师, 超期1天后提醒
  180. func businessFollowOverdueProductLineManager(tenant string, userIds []string) {
  181. now := gtime.Now().StartOfDay()
  182. // 超期一天
  183. LastWeekOneDay := now.AddDate(0, 0, -8)
  184. LastTwoWeekOneDay := now.AddDate(0, 0, -15)
  185. LastMonthOneDay := now.AddDate(0, -1, -1)
  186. // 超期当天
  187. LastWeekCurrentDay := now.AddDate(0, 0, -7)
  188. LastTwoWeekCurrentDay := now.AddDate(0, 0, -14)
  189. LastMonthCurrentDay := now.AddDate(0, -1, 0)
  190. // 在到达超期时间前3天进行提醒
  191. LastWeekBeforeTridDay := now.AddDate(0, 0, -4)
  192. LastTwoWeekBeforeTridDay := now.AddDate(0, 0, -11)
  193. LastMonthBeforeTridDay := now.AddDate(0, -1, 3)
  194. for _, userId := range userIds {
  195. LastWeekOne, LastTwoWeekOne, LastMonthOne := new(FollowOverdue), new(FollowOverdue), new(FollowOverdue)
  196. LastWeekCurrent, LastTwoWeekCurrent, LastMonthCurrent := new(FollowOverdue), new(FollowOverdue), new(FollowOverdue)
  197. LastWeekBeforeTrid, LastTwoWeekBeforeTrid, LastMonthBeforeTrid := new(FollowOverdue), new(FollowOverdue), new(FollowOverdue)
  198. dataScope, err := service.GetUserDataScope(gconv.Int(userId))
  199. if err != nil {
  200. g.Log().Error(fmt.Sprintf("定时任务项目超期提醒用户数据权限查询失败:userId-%v,", userId), err)
  201. continue
  202. }
  203. ctx := context.WithValue(context.TODO(), "contextService", g.Map{"dataScope": dataScope})
  204. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
  205. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekOneDay).DataScope(ctx, "sale_id").
  206. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastWeekOne)
  207. if err != nil {
  208. g.Log().Error("获取A类超期一天未跟进项目", err)
  209. }
  210. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
  211. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekOneDay).DataScope(ctx, "sale_id").
  212. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastTwoWeekOne)
  213. if err != nil {
  214. g.Log().Error("获取B类超期一天未跟进项目", err)
  215. }
  216. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
  217. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthOneDay).DataScope(ctx, "sale_id").
  218. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastMonthOne)
  219. if err != nil {
  220. g.Log().Error("获取C类超期一天未跟进项目", err)
  221. }
  222. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
  223. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekCurrentDay).
  224. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekOneDay).DataScope(ctx, "sale_id").
  225. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastWeekCurrent)
  226. if err != nil {
  227. g.Log().Error("获取A类超期当天未跟进项目", err)
  228. }
  229. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
  230. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekCurrentDay).
  231. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekOneDay).DataScope(ctx, "sale_id").
  232. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastTwoWeekCurrent)
  233. if err != nil {
  234. g.Log().Error("获取B类超期当天未跟进项目", err)
  235. }
  236. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
  237. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthCurrentDay).
  238. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthOneDay).DataScope(ctx, "sale_id").
  239. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastMonthCurrent)
  240. if err != nil {
  241. g.Log().Error("获取C类超期当天未跟进项目", err)
  242. }
  243. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
  244. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekBeforeTridDay).
  245. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekCurrentDay).DataScope(ctx, "sale_id").
  246. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastWeekBeforeTrid)
  247. if err != nil {
  248. g.Log().Error("获取A类超期当天未跟进项目", err)
  249. }
  250. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
  251. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekBeforeTridDay).
  252. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekCurrentDay).DataScope(ctx, "sale_id").
  253. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastTwoWeekBeforeTrid)
  254. if err != nil {
  255. g.Log().Error("获取B类超期当天未跟进项目", err)
  256. }
  257. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
  258. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthBeforeTridDay).
  259. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthCurrentDay).DataScope(ctx, "sale_id").
  260. Fields("count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastMonthBeforeTrid)
  261. if err != nil {
  262. g.Log().Error("获取C类超期当天未跟进项目", err)
  263. }
  264. var msg string
  265. if LastWeekOne.Count != 0 {
  266. msg += fmt.Sprintf("您有超期1天未跟进A类项目%v个,项目名称分别为 %v,", LastWeekOne.Count, LastWeekOne.BusNames)
  267. }
  268. if LastTwoWeekOne.Count != 0 {
  269. msg += fmt.Sprintf("您有超期1天未跟进B类项目%v个,项目名称分别为 %v,", LastTwoWeekOne.Count, LastTwoWeekOne.BusNames)
  270. }
  271. if LastMonthOne.Count != 0 {
  272. msg += fmt.Sprintf("您有超期1天未跟进C类项目%v个,项目名称分别为 %v,", LastMonthOne.Count, LastMonthOne.BusNames)
  273. }
  274. if LastWeekCurrent.Count != 0 {
  275. msg += fmt.Sprintf("您今天有超期未跟进A类项目%v个,项目名称分别为 %v,", LastWeekCurrent.Count, LastWeekCurrent.BusNames)
  276. }
  277. if LastTwoWeekCurrent.Count != 0 {
  278. msg += fmt.Sprintf("您今天有超期未跟进B类项目%v个,项目名称分别为 %v,", LastTwoWeekCurrent.Count, LastTwoWeekCurrent.BusNames)
  279. }
  280. if LastMonthCurrent.Count != 0 {
  281. msg += fmt.Sprintf("您今天有超期未跟进C类项目%v个,项目名称分别为 %v,", LastMonthCurrent.Count, LastMonthCurrent.BusNames)
  282. }
  283. if LastWeekBeforeTrid.Count != 0 {
  284. msg += fmt.Sprintf("您3天后有超期未跟进A类项目%v个,项目名称分别为 %v,", LastWeekBeforeTrid.Count, LastWeekBeforeTrid.BusNames)
  285. }
  286. if LastTwoWeekBeforeTrid.Count != 0 {
  287. msg += fmt.Sprintf("您3天后有超期未跟进B类项目%v个,项目名称分别为 %v,", LastTwoWeekBeforeTrid.Count, LastTwoWeekBeforeTrid.BusNames)
  288. }
  289. if LastMonthBeforeTrid.Count != 0 {
  290. msg += fmt.Sprintf("您3天后有超期未跟进C类项目%v个,项目名称分别为 %v,", LastMonthBeforeTrid.Count, LastMonthBeforeTrid.BusNames)
  291. }
  292. if msg != "" {
  293. businessNotifyMessage([]string{userId}, gstr.TrimRightStr(msg, ","))
  294. }
  295. }
  296. }
  297. // 在到达超期时间前3天进行提醒、当天进行提醒,这两次提醒只提醒销售工程师, 超期1天后提醒
  298. func businessFollowOverdueSalesEngineer(tenant string) {
  299. now := gtime.Now().StartOfDay()
  300. // 超期一天
  301. LastWeekOneDay := now.AddDate(0, 0, -8)
  302. LastTwoWeekOneDay := now.AddDate(0, 0, -15)
  303. LastMonthOneDay := now.AddDate(0, -1, -1)
  304. // 超期当天
  305. LastWeekCurrentDay := now.AddDate(0, 0, -7)
  306. LastTwoWeekCurrentDay := now.AddDate(0, 0, -14)
  307. LastMonthCurrentDay := now.AddDate(0, -1, 0)
  308. // 在到达超期时间前3天进行提醒
  309. LastWeekBeforeTridDay := now.AddDate(0, 0, -4)
  310. LastTwoWeekBeforeTridDay := now.AddDate(0, 0, -11)
  311. LastMonthBeforeTridDay := now.AddDate(0, -1, 3)
  312. LastWeekOneCount, LastTwoWeekOneCount, LastMonthOneCount := make([]FollowOverdue, 0), make([]FollowOverdue, 0), make([]FollowOverdue, 0)
  313. LastWeekCurrentCount, LastTwoWeekCurrentCount, LastMonthCurrentCount := make([]FollowOverdue, 0), make([]FollowOverdue, 0), make([]FollowOverdue, 0)
  314. LastWeekBeforeTridCount, LastTwoWeekBeforeTridCount, LastMonthBeforeTridCount := make([]FollowOverdue, 0), make([]FollowOverdue, 0), make([]FollowOverdue, 0)
  315. err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
  316. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekOneDay).Group("sale_id").OrderAsc("sale_id").
  317. Fields("sale_id, count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastWeekOneCount)
  318. if err != nil {
  319. g.Log().Error("获取A类超期一天未跟进项目", err)
  320. }
  321. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
  322. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekOneDay).Group("sale_id").OrderAsc("sale_id").
  323. Fields("sale_id, count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastTwoWeekOneCount)
  324. if err != nil {
  325. g.Log().Error("获取B类超期一天未跟进项目", err)
  326. }
  327. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
  328. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthOneDay).Group("sale_id").OrderAsc("sale_id").
  329. Fields("sale_id, count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastMonthOneCount)
  330. if err != nil {
  331. g.Log().Error("获取C类超期一天未跟进项目", err)
  332. }
  333. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
  334. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekCurrentDay).
  335. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekOneDay).Group("sale_id").OrderAsc("sale_id").
  336. Fields("sale_id, count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastWeekCurrentCount)
  337. if err != nil {
  338. g.Log().Error("获取A类超期当天未跟进项目", err)
  339. }
  340. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
  341. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekCurrentDay).
  342. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekOneDay).Group("sale_id").OrderAsc("sale_id").
  343. Fields("sale_id, count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastTwoWeekCurrentCount)
  344. if err != nil {
  345. g.Log().Error("获取B类超期当天未跟进项目", err)
  346. }
  347. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
  348. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthCurrentDay).
  349. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthOneDay).Group("sale_id").OrderAsc("sale_id").
  350. Fields("sale_id, count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastMonthCurrentCount)
  351. if err != nil {
  352. g.Log().Error("获取C类超期当天未跟进项目", err)
  353. }
  354. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
  355. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekBeforeTridDay).
  356. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekCurrentDay).Group("sale_id").OrderAsc("sale_id").
  357. Fields("sale_id, count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastWeekBeforeTridCount)
  358. if err != nil {
  359. g.Log().Error("获取A类超期当天未跟进项目", err)
  360. }
  361. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
  362. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekBeforeTridDay).
  363. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekCurrentDay).Group("sale_id").OrderAsc("sale_id").
  364. Fields("sale_id, count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastTwoWeekBeforeTridCount)
  365. if err != nil {
  366. g.Log().Error("获取B类超期当天未跟进项目", err)
  367. }
  368. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
  369. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthBeforeTridDay).
  370. WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthCurrentDay).Group("sale_id").OrderAsc("sale_id").
  371. Fields("sale_id, count(id) as count, group_concat(nbo_name) as busNames").Scan(&LastMonthBeforeTridCount)
  372. if err != nil {
  373. g.Log().Error("获取C类超期当天未跟进项目", err)
  374. }
  375. allSaleIds := gset.NewIntSet(true)
  376. saleIds, LastWeekOneCountMap := handleSalesEngineerData(LastWeekOneCount)
  377. allSaleIds = allSaleIds.Union(saleIds)
  378. saleIds, LastTwoWeekOneCountMap := handleSalesEngineerData(LastTwoWeekOneCount)
  379. allSaleIds = allSaleIds.Union(saleIds)
  380. saleIds, LastMonthOneCountMap := handleSalesEngineerData(LastMonthOneCount)
  381. allSaleIds = allSaleIds.Union(saleIds)
  382. saleIds, LastWeekCurrentCountMap := handleSalesEngineerData(LastWeekCurrentCount)
  383. allSaleIds = allSaleIds.Union(saleIds)
  384. saleIds, LastTwoWeekCurrentCountMap := handleSalesEngineerData(LastTwoWeekCurrentCount)
  385. allSaleIds = allSaleIds.Union(saleIds)
  386. saleIds, LastMonthCurrentCountMap := handleSalesEngineerData(LastMonthCurrentCount)
  387. allSaleIds = allSaleIds.Union(saleIds)
  388. saleIds, LastWeekBeforeTridCountMap := handleSalesEngineerData(LastWeekBeforeTridCount)
  389. allSaleIds = allSaleIds.Union(saleIds)
  390. saleIds, LastTwoWeekBeforeTridCountMap := handleSalesEngineerData(LastTwoWeekBeforeTridCount)
  391. allSaleIds = allSaleIds.Union(saleIds)
  392. saleIds, LastMonthBeforeTridCountMap := handleSalesEngineerData(LastMonthBeforeTridCount)
  393. allSaleIds = allSaleIds.Union(saleIds)
  394. for _, saleId := range allSaleIds.Slice() {
  395. var msg string
  396. if LastWeekOneCountMap[saleId].Count != 0 {
  397. msg += fmt.Sprintf("您有超期1天未跟进A类项目%v个,项目名称分别为 %v,", LastWeekOneCountMap[saleId].Count, LastWeekOneCountMap[saleId].BusNames)
  398. }
  399. if LastTwoWeekOneCountMap[saleId].Count != 0 {
  400. msg += fmt.Sprintf("您有超期1天未跟进B类项目%v个,项目名称分别为 %v,", LastTwoWeekOneCountMap[saleId].Count, LastTwoWeekOneCountMap[saleId].BusNames)
  401. }
  402. if LastMonthOneCountMap[saleId].Count != 0 {
  403. msg += fmt.Sprintf("您有超期1天未跟进C类项目%v个,项目名称分别为 %v,", LastMonthOneCountMap[saleId].Count, LastMonthOneCountMap[saleId].BusNames)
  404. }
  405. if LastWeekCurrentCountMap[saleId].Count != 0 {
  406. msg += fmt.Sprintf("您今天有超期未跟进A类项目%v个,项目名称分别为 %v,", LastWeekCurrentCountMap[saleId].Count, LastWeekCurrentCountMap[saleId].BusNames)
  407. }
  408. if LastTwoWeekCurrentCountMap[saleId].Count != 0 {
  409. msg += fmt.Sprintf("您今天有超期未跟进B类项目%v个,项目名称分别为 %v,", LastTwoWeekCurrentCountMap[saleId].Count, LastTwoWeekCurrentCountMap[saleId].BusNames)
  410. }
  411. if LastMonthCurrentCountMap[saleId].Count != 0 {
  412. msg += fmt.Sprintf("您今天有超期未跟进C类项目%v个,项目名称分别为 %v,", LastMonthCurrentCountMap[saleId].Count, LastMonthCurrentCountMap[saleId].BusNames)
  413. }
  414. if LastWeekBeforeTridCountMap[saleId].Count != 0 {
  415. msg += fmt.Sprintf("您3天后有超期未跟进A类项目%v个,项目名称分别为 %v,", LastWeekBeforeTridCountMap[saleId].Count, LastWeekBeforeTridCountMap[saleId].BusNames)
  416. }
  417. if LastTwoWeekBeforeTridCountMap[saleId].Count != 0 {
  418. msg += fmt.Sprintf("您3天后有超期未跟进B类项目%v个,项目名称分别为 %v,", LastTwoWeekBeforeTridCountMap[saleId].Count, LastTwoWeekBeforeTridCountMap[saleId].BusNames)
  419. }
  420. if LastMonthBeforeTridCountMap[saleId].Count != 0 {
  421. msg += fmt.Sprintf("您3天后有超期未跟进C类项目%v个,项目名称分别为 %v,", LastMonthBeforeTridCountMap[saleId].Count, LastMonthBeforeTridCountMap[saleId].BusNames)
  422. }
  423. if msg != "" {
  424. businessNotifyMessage([]string{gconv.String(saleId)}, gstr.TrimRightStr(msg, ","))
  425. }
  426. }
  427. }
  428. func handleSalesEngineerData(countData []FollowOverdue) (saleIds *gset.IntSet, data map[int]FollowOverdue) {
  429. saleIds = gset.NewIntSet(true)
  430. data = make(map[int]FollowOverdue)
  431. for _, v := range countData {
  432. saleId := gconv.Int(v.SaleId)
  433. saleIds.Add(saleId)
  434. data[saleId] = v
  435. }
  436. return
  437. }
  438. // 项目跟进的消息通知
  439. func businessNotifyMessage(userIds []string, message string) {
  440. ids := strings.Join(userIds, ",")
  441. // 调用统一的消息通知方式
  442. notifyMessage(ids, message)
  443. }
  444. // notifyMessage 发送消息通知
  445. func notifyMessage(ids, message string) {
  446. msg := g.MapStrStr{
  447. "msgTitle": "项目跟进超期提醒",
  448. "msgContent": message,
  449. "msgType": "20",
  450. "recvUserIds": ids,
  451. "msgStatus": "10",
  452. "sendType": "10,30",
  453. }
  454. if err := service.CreateSystemMessage(msg); err != nil {
  455. glog.Error("消息提醒异常:", err)
  456. }
  457. }
  458. // 项目每周进行一次超期三天未跟进统计表,每周给销售助理发一次邮件
  459. func businesspeopleUpReminder() {
  460. tenant := g.Config().GetString("micro_srv.tenant")
  461. if tenant == "" {
  462. glog.Error("定时任务租户码未设置,请前往配置")
  463. return
  464. }
  465. // 从配置中获取消息提醒设置
  466. configs, err := g.DB(tenant).Model("sys_config").Where("config_key IN ('SalesDirector','SalesAssociate')").FindAll()
  467. if err != nil && err != sql.ErrNoRows {
  468. glog.Error(err)
  469. return
  470. }
  471. // 销售助理用户Id
  472. salesAssociate := []string{}
  473. for _, config := range configs {
  474. if config["config_key"].String() == "SalesAssociate" {
  475. salesAssociate = strings.Split(config["config_value"].String(), ",")
  476. }
  477. }
  478. var list []*model.ProjBusinessRes
  479. var listA []*model.ProjBusinessRes
  480. var listB []*model.ProjBusinessRes
  481. var listC []*model.ProjBusinessRes
  482. now := gtime.Now().StartOfDay()
  483. LastWeekDay := now.AddDate(0, 0, -8)
  484. LastTwoWeekDay := now.AddDate(0, 0, -15)
  485. LastMonthDay := now.AddDate(0, -1, -1)
  486. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
  487. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekDay).OrderDesc("id").Scan(&listA)
  488. if err != nil {
  489. g.Log().Error("获取A类超期3天未跟进项目", err)
  490. }
  491. if len(listA) > 0 {
  492. list = append(list, listA...)
  493. }
  494. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
  495. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekDay).OrderDesc("id").Scan(&listB)
  496. if err != nil {
  497. g.Log().Error("获取B类超期3天未跟进项目", err)
  498. }
  499. if len(listB) > 0 {
  500. list = append(list, listB...)
  501. }
  502. err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
  503. WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthDay).OrderDesc("id").Scan(&listC)
  504. if err != nil {
  505. g.Log().Error("获取C类超期3天未跟进项目", err)
  506. }
  507. if len(listC) > 0 {
  508. list = append(list, listC...)
  509. }
  510. if err != nil {
  511. g.Log().Error("获取未跟进项目", err)
  512. }
  513. ctx := context.WithValue(context.TODO(), share.ReqMetaDataKey, map[string]string{"tenant": tenant})
  514. rsp, err := service.GetDictDataByType(ctx, "proj_nbo_type")
  515. if err != nil {
  516. g.Log().Error("项目类别数据字典", err)
  517. }
  518. if err != nil {
  519. g.Log().Error("获取未跟进项目", err)
  520. return
  521. }
  522. var msg string
  523. if len(list) > 0 {
  524. msg += fmt.Sprintf("您有超期3天未跟进项目%v个,请登录系统查看", len(list))
  525. }
  526. f := excelize.NewFile()
  527. f.MergeCell("Sheet1", "A1", "D1")
  528. style, _ := f.NewStyle(`{"alignment":{"horizontal":"center"}}`)
  529. f.SetCellValue("Sheet1", "A1", "超期三天未跟进项目")
  530. f.SetCellStyle("sheet1", "A1", "D1", style)
  531. f.SetColWidth("Sheet1", "A", "K", 20)
  532. f.SetCellValue("Sheet1", "A2", "序号")
  533. f.SetCellValue("Sheet1", "B2", "项目名称")
  534. f.SetCellValue("Sheet1", "C2", "项目类别")
  535. f.SetCellValue("Sheet1", "D2", "最新跟进时间")
  536. line := 2
  537. if len(list) > 0 {
  538. for _, v := range list {
  539. line++
  540. f.SetCellValue("Sheet1", fmt.Sprintf("A%d", line), gconv.String(line-2))
  541. f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), v.NboName)
  542. if len(rsp) > 0 {
  543. f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), rsp[v.NboType])
  544. } else {
  545. f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), v.NboType)
  546. }
  547. f.SetCellValue("Sheet1", fmt.Sprintf("D%d", line), v.FinalFollowTime)
  548. }
  549. }
  550. dir := g.Config().GetString("file.cronstatic")
  551. filename := "项目跟进" + gconv.String(time.Now().UnixNano()) + ".xlsx"
  552. path := dir + filename
  553. if err = f.SaveAs(path); err != nil {
  554. g.Log().Error("Excel保存失败", err)
  555. }
  556. if len(salesAssociate) > 0 {
  557. for _, val := range salesAssociate {
  558. if val == "" {
  559. continue
  560. }
  561. msgs := g.MapStrStr{
  562. "msgTitle": "超期3天未跟进项目提醒",
  563. "msgContent": msg,
  564. "recvUserIds": "1",
  565. "recvUser": "系统管理员",
  566. "opnUrl": path,
  567. }
  568. if err = service.GSendMail(msgs); err != nil {
  569. g.Log().Error("SendMail() error = %v", err)
  570. }
  571. }
  572. }
  573. }