|
|
@@ -0,0 +1,339 @@
|
|
|
+package proj
|
|
|
+
|
|
|
+import (
|
|
|
+ projDao "dashoo.cn/micro/app/dao/proj"
|
|
|
+ "dashoo.cn/micro/app/service"
|
|
|
+ "database/sql"
|
|
|
+ "fmt"
|
|
|
+ "github.com/gogf/gf/container/gset"
|
|
|
+ "github.com/gogf/gf/frame/g"
|
|
|
+ "github.com/gogf/gf/os/gcron"
|
|
|
+ "github.com/gogf/gf/os/glog"
|
|
|
+ "github.com/gogf/gf/os/gtime"
|
|
|
+ "github.com/gogf/gf/text/gstr"
|
|
|
+ "github.com/gogf/gf/util/gconv"
|
|
|
+ "strings"
|
|
|
+)
|
|
|
+
|
|
|
+// 初始化,创建每10分钟执行一次的定时任务
|
|
|
+func init() {
|
|
|
+ // 定时任务
|
|
|
+ spec := "0 0 9 * * *" // 每天凌晨9点执行
|
|
|
+ gcron.AddSingleton(spec, businessFollowRun)
|
|
|
+}
|
|
|
+
|
|
|
+// businessFollowRun 项目跟进超时任务逻辑
|
|
|
+func businessFollowRun() {
|
|
|
+ tenant := g.Config().GetString("micro_srv.tenant")
|
|
|
+ if tenant == "" {
|
|
|
+ glog.Error("定时任务租户码未设置,请前往配置")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 从配置中获取消息提醒设置
|
|
|
+ configs, err := g.DB(tenant).Model("sys_config").Where("config_key IN ('SalesDirector','SalesAssociate')").FindAll()
|
|
|
+ if err != nil && err != sql.ErrNoRows {
|
|
|
+ glog.Error(err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 销售总监用户Id
|
|
|
+ salesDirector := []string{}
|
|
|
+ // 销售助理用户Id
|
|
|
+ salesAssociate := []string{}
|
|
|
+ for _, config := range configs {
|
|
|
+ if config["config_key"].String() == "SalesDirector" {
|
|
|
+ salesDirector = strings.Split(config["config_value"].String(), ",")
|
|
|
+ } else if config["config_key"].String() == "SalesAssociate" {
|
|
|
+ salesAssociate = strings.Split(config["config_value"].String(), ",")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ businessFollowOverdueSalesAssociate(tenant, []string{"13"})
|
|
|
+ if len(salesDirector) > 0 {
|
|
|
+ go businessFollowOverdueSalesDirector(tenant, salesDirector)
|
|
|
+ }
|
|
|
+ if len(salesAssociate) > 0 {
|
|
|
+ go businessFollowOverdueSalesDirector(tenant, salesAssociate)
|
|
|
+ }
|
|
|
+ go businessFollowOverdueSalesEngineer(tenant)
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+// 超期3天提醒销售总监
|
|
|
+func businessFollowOverdueSalesDirector(tenant string, userIds []string) {
|
|
|
+ now := gtime.Now().StartOfDay()
|
|
|
+ LastWeekDay := now.AddDate(0, 0, -10)
|
|
|
+ LastTwoWeekDay := now.AddDate(0, 0, -17)
|
|
|
+ LastMonthDay := now.AddDate(0, -1, -3)
|
|
|
+
|
|
|
+ businessACount, err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekDay).Count()
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取A类超期3天未跟进项目", err)
|
|
|
+ }
|
|
|
+ businessBCount, err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekDay).Count()
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取B类超期3天未跟进项目", err)
|
|
|
+ }
|
|
|
+ businessCCount, err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthDay).Count()
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取C类超期3天未跟进项目", err)
|
|
|
+ }
|
|
|
+ var msg string
|
|
|
+ if businessACount > 0 {
|
|
|
+ msg += fmt.Sprintf("您有超期3天未跟进A类项目%v个,", businessACount)
|
|
|
+ }
|
|
|
+ if businessBCount > 0 {
|
|
|
+ msg += fmt.Sprintf("您有超期3天未跟进B类项目%v个,", businessBCount)
|
|
|
+ }
|
|
|
+ if businessCCount > 0 {
|
|
|
+ msg += fmt.Sprintf("您有超期3天未跟进C类项目%v个,", businessCCount)
|
|
|
+ }
|
|
|
+ if msg != "" {
|
|
|
+ businessNotifyMessage(userIds, gstr.TrimRightStr(msg, ","))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 超期1天后,超期3天 提醒销售助理
|
|
|
+func businessFollowOverdueSalesAssociate(tenant string, userIds []string) {
|
|
|
+ now := gtime.Now().StartOfDay()
|
|
|
+ LastWeekDay := now.AddDate(0, 0, -8)
|
|
|
+ LastTwoWeekDay := now.AddDate(0, 0, -15)
|
|
|
+ LastMonthDay := now.AddDate(0, -1, -1)
|
|
|
+
|
|
|
+ LastWeekTridDay := now.AddDate(0, 0, -10)
|
|
|
+ LastTwoWeekTridDay := now.AddDate(0, 0, -17)
|
|
|
+ LastMonthTridDay := now.AddDate(0, -1, -3)
|
|
|
+
|
|
|
+ businessATridCount, err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekDay).Count()
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取A类超期3天未跟进项目", err)
|
|
|
+ }
|
|
|
+ businessBTridCount, err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekDay).Count()
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取B类超期3天未跟进项目", err)
|
|
|
+ }
|
|
|
+ businessCTridCount, err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthDay).Count()
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取C类超期3天未跟进项目", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ businessACount, err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekDay).WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekTridDay).
|
|
|
+ Count()
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取A类超期1天未跟进项目", err)
|
|
|
+ }
|
|
|
+ businessBCount, err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekDay).WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekTridDay).
|
|
|
+ Count()
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取B类超期1天未跟进项目", err)
|
|
|
+ }
|
|
|
+ businessCCount, err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthDay).WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthTridDay).
|
|
|
+ Count()
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取C类超期1天未跟进项目", err)
|
|
|
+ }
|
|
|
+ var msg string
|
|
|
+ if businessATridCount > 0 {
|
|
|
+ msg += fmt.Sprintf("您有超期3天未跟进A类项目%v个,", businessATridCount)
|
|
|
+ }
|
|
|
+ if businessBTridCount > 0 {
|
|
|
+ msg += fmt.Sprintf("您有超期3天未跟进B类项目%v个,", businessBTridCount)
|
|
|
+ }
|
|
|
+ if businessCTridCount > 0 {
|
|
|
+ msg += fmt.Sprintf("您有超期3天未跟进C类项目%v个,", businessCTridCount)
|
|
|
+ }
|
|
|
+ if businessACount > 0 {
|
|
|
+ msg += fmt.Sprintf("您有超期1天未跟进A类项目%v个,", businessACount)
|
|
|
+ }
|
|
|
+ if businessBCount > 0 {
|
|
|
+ msg += fmt.Sprintf("您有超期1天未跟进B类项目%v个,", businessBCount)
|
|
|
+ }
|
|
|
+ if businessCCount > 0 {
|
|
|
+ msg += fmt.Sprintf("您有超期1天未跟进C类项目%v个,", businessCCount)
|
|
|
+ }
|
|
|
+ if msg != "" {
|
|
|
+ businessNotifyMessage(userIds, gstr.TrimRightStr(msg, ","))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+type FollowOverdue struct {
|
|
|
+ SaleId int64 `json:"saleId"`
|
|
|
+ Count int64 `json:"count"`
|
|
|
+}
|
|
|
+
|
|
|
+// 在到达超期时间前3天进行提醒、当天进行提醒,这两次提醒只提醒销售工程师, 超期1天后提醒
|
|
|
+func businessFollowOverdueSalesEngineer(tenant string) {
|
|
|
+ now := gtime.Now().StartOfDay()
|
|
|
+ // 超期一天
|
|
|
+ LastWeekOneDay := now.AddDate(0, 0, -8)
|
|
|
+ LastTwoWeekOneDay := now.AddDate(0, 0, -15)
|
|
|
+ LastMonthOneDay := now.AddDate(0, -1, -1)
|
|
|
+ // 超期当天
|
|
|
+ LastWeekCurrentDay := now.AddDate(0, 0, -7)
|
|
|
+ LastTwoWeekCurrentDay := now.AddDate(0, 0, -14)
|
|
|
+ LastMonthCurrentDay := now.AddDate(0, -1, 0)
|
|
|
+ // 在到达超期时间前3天进行提醒
|
|
|
+ LastWeekBeforeTridDay := now.AddDate(0, 0, -4)
|
|
|
+ LastTwoWeekBeforeTridDay := now.AddDate(0, 0, -11)
|
|
|
+ LastMonthBeforeTridDay := now.AddDate(0, -1, 3)
|
|
|
+
|
|
|
+ LastWeekOneCount, LastTwoWeekOneCount, LastMonthOneCount := make([]FollowOverdue, 0), make([]FollowOverdue, 0), make([]FollowOverdue, 0)
|
|
|
+ LastWeekCurrentCount, LastTwoWeekCurrentCount, LastMonthCurrentCount := make([]FollowOverdue, 0), make([]FollowOverdue, 0), make([]FollowOverdue, 0)
|
|
|
+ LastWeekBeforeTridCount, LastTwoWeekBeforeTridCount, LastMonthBeforeTridCount := make([]FollowOverdue, 0), make([]FollowOverdue, 0), make([]FollowOverdue, 0)
|
|
|
+ err := projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekOneDay).
|
|
|
+ Fields("sale_id, count(id) as count").Group("sale_id").OrderAsc("sale_id").Scan(&LastWeekOneCount)
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取A类超期一天未跟进项目", err)
|
|
|
+ }
|
|
|
+ err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekOneDay).
|
|
|
+ Fields("sale_id, count(id) as count").Group("sale_id").OrderAsc("sale_id").Scan(&LastTwoWeekOneCount)
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取B类超期一天未跟进项目", err)
|
|
|
+ }
|
|
|
+ err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthOneDay).
|
|
|
+ Fields("sale_id, count(id) as count").Group("sale_id").OrderAsc("sale_id").Scan(&LastMonthOneCount)
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取C类超期一天未跟进项目", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekCurrentDay).
|
|
|
+ WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekOneDay).
|
|
|
+ Fields("sale_id, count(id) as count").Group("sale_id").OrderAsc("sale_id").Scan(&LastWeekCurrentCount)
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取A类超期当天未跟进项目", err)
|
|
|
+ }
|
|
|
+ err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekCurrentDay).
|
|
|
+ WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekOneDay).
|
|
|
+ Fields("sale_id, count(id) as count").Group("sale_id").OrderAsc("sale_id").Scan(&LastTwoWeekCurrentCount)
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取B类超期当天未跟进项目", err)
|
|
|
+ }
|
|
|
+ err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthCurrentDay).
|
|
|
+ WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthOneDay).
|
|
|
+ Fields("sale_id, count(id) as count").Group("sale_id").OrderAsc("sale_id").Scan(&LastMonthCurrentCount)
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取C类超期当天未跟进项目", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusA).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekBeforeTridDay).
|
|
|
+ WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastWeekCurrentDay).
|
|
|
+ Fields("sale_id, count(id) as count").Group("sale_id").OrderAsc("sale_id").Scan(&LastWeekBeforeTridCount)
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取A类超期当天未跟进项目", err)
|
|
|
+ }
|
|
|
+ err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusB).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekBeforeTridDay).
|
|
|
+ WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastTwoWeekCurrentDay).
|
|
|
+ Fields("sale_id, count(id) as count").Group("sale_id").OrderAsc("sale_id").Scan(&LastTwoWeekBeforeTridCount)
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取B类超期当天未跟进项目", err)
|
|
|
+ }
|
|
|
+ err = projDao.NewProjBusinessDao(tenant).Where(projDao.ProjBusiness.C.NboType, StatusC).
|
|
|
+ WhereLTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthBeforeTridDay).
|
|
|
+ WhereGTE(projDao.ProjBusiness.C.FinalFollowTime, LastMonthCurrentDay).
|
|
|
+ Fields("sale_id, count(id) as count").Group("sale_id").OrderAsc("sale_id").Scan(&LastMonthBeforeTridCount)
|
|
|
+ if err != nil {
|
|
|
+ g.Log().Error("获取C类超期当天未跟进项目", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ allSaleIds := gset.NewStrSet(true)
|
|
|
+ saleIds, lastWeekOneCountMap := handleSalesEngineerData(LastWeekOneCount)
|
|
|
+ allSaleIds = allSaleIds.Union(saleIds)
|
|
|
+ saleIds, LastTwoWeekOneCountMap := handleSalesEngineerData(LastTwoWeekOneCount)
|
|
|
+ allSaleIds = allSaleIds.Union(saleIds)
|
|
|
+ saleIds, LastMonthOneCountMap := handleSalesEngineerData(LastMonthOneCount)
|
|
|
+ allSaleIds = allSaleIds.Union(saleIds)
|
|
|
+ saleIds, LastWeekCurrentCountMap := handleSalesEngineerData(LastWeekCurrentCount)
|
|
|
+ allSaleIds = allSaleIds.Union(saleIds)
|
|
|
+ saleIds, LastTwoWeekCurrentCountMap := handleSalesEngineerData(LastTwoWeekCurrentCount)
|
|
|
+ allSaleIds = allSaleIds.Union(saleIds)
|
|
|
+ saleIds, LastMonthCurrentCountMap := handleSalesEngineerData(LastMonthCurrentCount)
|
|
|
+ allSaleIds = allSaleIds.Union(saleIds)
|
|
|
+ saleIds, LastWeekBeforeTridCountMap := handleSalesEngineerData(LastWeekBeforeTridCount)
|
|
|
+ allSaleIds = allSaleIds.Union(saleIds)
|
|
|
+ saleIds, LastTwoWeekBeforeTridCountMap := handleSalesEngineerData(LastTwoWeekBeforeTridCount)
|
|
|
+ allSaleIds = allSaleIds.Union(saleIds)
|
|
|
+ saleIds, LastMonthBeforeTridCountMap := handleSalesEngineerData(LastMonthBeforeTridCount)
|
|
|
+ allSaleIds = allSaleIds.Union(saleIds)
|
|
|
+ for _, saleId := range allSaleIds.Slice() {
|
|
|
+ var msg string
|
|
|
+ if lastWeekOneCountMap[saleId] != "" {
|
|
|
+ msg += fmt.Sprintf("您有超期1天未跟进A类项目%v个,", lastWeekOneCountMap[saleId])
|
|
|
+ }
|
|
|
+ if LastTwoWeekOneCountMap[saleId] != "" {
|
|
|
+ msg += fmt.Sprintf("您有超期1天未跟进B类项目%v个,", LastTwoWeekOneCountMap[saleId])
|
|
|
+ }
|
|
|
+ if LastMonthOneCountMap[saleId] != "" {
|
|
|
+ msg += fmt.Sprintf("您有超期1天未跟进C类项目%v个,", LastMonthOneCountMap[saleId])
|
|
|
+ }
|
|
|
+ if LastWeekCurrentCountMap[saleId] != "" {
|
|
|
+ msg += fmt.Sprintf("您今天有超期未跟进A类项目%v个,", LastWeekCurrentCountMap[saleId])
|
|
|
+ }
|
|
|
+ if LastTwoWeekCurrentCountMap[saleId] != "" {
|
|
|
+ msg += fmt.Sprintf("您今天有超期未跟进B类项目%v个,", LastTwoWeekCurrentCountMap[saleId])
|
|
|
+ }
|
|
|
+ if LastMonthCurrentCountMap[saleId] != "" {
|
|
|
+ msg += fmt.Sprintf("您今天有超期未跟进C类项目%v个,", LastMonthCurrentCountMap[saleId])
|
|
|
+ }
|
|
|
+ if LastWeekBeforeTridCountMap[saleId] != "" {
|
|
|
+ msg += fmt.Sprintf("您3天后有超期未跟进A类项目%v个,", LastWeekBeforeTridCountMap[saleId])
|
|
|
+ }
|
|
|
+ if LastTwoWeekBeforeTridCountMap[saleId] != "" {
|
|
|
+ msg += fmt.Sprintf("您3天后有超期未跟进B类项目%v个,", LastTwoWeekBeforeTridCountMap[saleId])
|
|
|
+ }
|
|
|
+ if LastMonthBeforeTridCountMap[saleId] != "" {
|
|
|
+ msg += fmt.Sprintf("您3天后有超期未跟进C类项目%v个,", LastMonthBeforeTridCountMap[saleId])
|
|
|
+ }
|
|
|
+ if msg != "" {
|
|
|
+ businessNotifyMessage([]string{saleId}, gstr.TrimRightStr(msg, ","))
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func handleSalesEngineerData(countData []FollowOverdue) (saleIds *gset.StrSet, data g.MapStrStr) {
|
|
|
+ saleIds = gset.NewStrSet(true)
|
|
|
+ data = make(g.MapStrStr)
|
|
|
+ for _, v := range countData {
|
|
|
+ saleId := gconv.String(v.SaleId)
|
|
|
+ saleIds.Add(saleId)
|
|
|
+ data[saleId] = gconv.String(v.Count)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// 项目跟进的消息通知
|
|
|
+func businessNotifyMessage(userIds []string, message string) {
|
|
|
+ ids := strings.Join(userIds, ",")
|
|
|
+ // 调用统一的消息通知方式
|
|
|
+ notifyMessage(ids, message)
|
|
|
+}
|
|
|
+
|
|
|
+// notifyMessage 发送消息通知
|
|
|
+func notifyMessage(ids, message string) {
|
|
|
+ msg := g.MapStrStr{
|
|
|
+ "msgTitle": "项目跟进超期提醒",
|
|
|
+ "msgContent": message,
|
|
|
+ "msgType": "20",
|
|
|
+ "recvUserIds": ids,
|
|
|
+ "msgStatus": "10",
|
|
|
+ "sendType": "10,20,30,40",
|
|
|
+ }
|
|
|
+ if err := service.CreateSystemMessage(msg); err != nil {
|
|
|
+ glog.Error("消息提醒异常:", err)
|
|
|
+ }
|
|
|
+}
|