瀏覽代碼

Merge branch 'dev1.1' of http://192.168.3.207:8080/dataservice/datatools into dev1.1

xuzhiheng 2 年之前
父節點
當前提交
5636146a5f

+ 21 - 3
telemarketingEtl/config.yaml

@@ -81,10 +81,28 @@ searchInfoTask: '0 0 * * * *'
 #定时任务 每日访问
 visitInfoTask: '0 0 * * * *'
 #定时任务
-TaskOpenSea: '0 0 0 * * *'
+openSeaTask: '0 0 0 * * *'
 #退出公海
 deleteOpenSeaTask: '0 0 0 * * *'
 #自动退回公海
 returnOpenSeaTask: '0 0 0 * * *'
-#
-openSeaTask: '0 0 0 * * *'
+#查看
+eventInfoTime: 5
+#搜索
+searchInfoTime: 5
+#每日
+visitInfoTime: 5
+#定时
+openSeaTime: 5
+#退出
+deleteOpenSeaTime: 5
+#自动退出
+returnOpenSeaTime: 5
+#高意向客户
+highIntentionCustomer: 30
+#意向客户
+intentionCustomer: 30
+#潜在客户
+latentCustomer: 60
+#沉睡客户
+sleepCustomer: 90

+ 144 - 109
telemarketingEtl/entity/dwd_f_crm_open_sea.go

@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"log"
 	"strings"
-	"sync"
 	"telemarketingEtl/config"
 	"telemarketingEtl/util"
 	"time"
@@ -48,17 +47,6 @@ B.3个自然日内有过“已接听”的通话记录且仍处于“商机线
 
 */
 
-var (
-	oPool chan bool
-	oWait = &sync.WaitGroup{}
-)
-
-func init() {
-	ctx := gctx.New()
-	poolSize := g.Cfg().MustGet(ctx, "poolSize").Int()
-	oPool = make(chan bool, poolSize)
-}
-
 func GetOpenSea() {
 	ctx := gctx.New()
 	//
@@ -131,40 +119,34 @@ func GetOpenSea() {
 	log.Println("一级公海开始.")
 	//一级公海
 	for thisData := map[string]interface{}{}; iter.Next(&thisData); {
-		oPool <- true
-		oWait.Add(1)
-		go func(thisData map[string]interface{}) {
-			defer func() {
-				<-oPool
-				oWait.Done()
-			}()
-			userid := gconv.String(thisData["userid"])
-			if userid == "" {
-				return
-			}
-			if !mongodb.IsObjectIdHex(userid) {
-				userid = GetUserIdByPositionId(userid)
-			}
-			if userid == "" {
-				return
-			}
-			//根据userid获取线索id
-			if oneClassA[userid] {
-				return
-			}
-			uuid := GetClueIdByUserId(userid)
-			if uuid == "" {
-				return
-			}
-			oneClassA[uuid] = true
-		}(thisData)
+
+		userid := gconv.String(thisData["userid"])
+		if userid == "" {
+			continue
+		}
+		if !mongodb.IsObjectIdHex(userid) {
+			userid = GetUserIdByPositionId(userid)
+		}
+		if userid == "" {
+			continue
+		}
+		//根据userid获取线索id
+		if oneClassA[userid] {
+			continue
+		}
+		uuid := GetClueIdByUserId(userid)
+		if uuid == "" {
+			continue
+		}
+		oneClassA[uuid] = true
+
 		count++
 		if count%10 == 0 {
 			log.Printf("已完成%d条数据\n", count)
 		}
 		thisData = map[string]interface{}{}
 	}
-	oWait.Wait()
+
 	log.Println("一级公海 pc  结束")
 	queryOneClassApp := map[string]interface{}{
 		"date": map[string]interface{}{
@@ -193,40 +175,33 @@ func GetOpenSea() {
 	count = 0
 	//一级公海
 	for thisData := map[string]interface{}{}; iter2.Next(&thisData); {
-		oPool <- true
-		oWait.Add(1)
-		go func(thisData map[string]interface{}) {
-			defer func() {
-				<-oPool
-				oWait.Done()
-			}()
-			userid := gconv.String(thisData["userid"])
-			if userid == "" {
-				return
-			}
-			if !mongodb.IsObjectIdHex(userid) {
-				userid = GetUserIdByPositionId(userid)
-			}
-			if userid == "" {
-				return
-			}
-			//根据userid获取线索id
-			if oneClassA[userid] {
-				return
-			}
-			uuid := GetClueIdByUserId(userid)
-			if uuid == "" {
-				return
-			}
-			oneClassA[uuid] = true
-		}(thisData)
+
+		userid := gconv.String(thisData["userid"])
+		if userid == "" {
+			continue
+		}
+		if !mongodb.IsObjectIdHex(userid) {
+			userid = GetUserIdByPositionId(userid)
+		}
+		if userid == "" {
+			continue
+		}
+		//根据userid获取线索id
+		if oneClassA[userid] {
+			continue
+		}
+		clubId := GetClueIdByUserId(userid)
+		if clubId == "" {
+			continue
+		}
+		oneClassA[clubId] = true
+
 		count++
 		if count%10 == 0 {
 			log.Printf("已完成%d条数据\n", count)
 		}
 		thisData = map[string]interface{}{}
 	}
-	oWait.Wait()
 	//更新公海
 	AddOpenSea(oneClassA, 1, "A")
 	log.Println("一级公海 更新结束。")
@@ -247,8 +222,8 @@ func GetOpenSea() {
 			if oneClassA[userid] {
 				continue
 			}
-			uuid := GetClueIdByUserId(userid)
-			oneClassB[uuid] = true
+			clubId := GetClueIdByUserId(userid)
+			oneClassB[clubId] = true
 		}
 	}
 	AddOpenSea(oneClassB, 1, "B")
@@ -261,7 +236,7 @@ func GetOpenSea() {
 	AddOpenSea(twoC, 2, "C")
 	AddOpenSea(twoD, 2, "D")
 	//三级公海
-	ThreeOpenSea()
+	ThreeOpenSea(oneClassA, oneClassB, oneClassC, twoA, twoB, twoC, twoD)
 	//
 	log.Println("end")
 }
@@ -307,21 +282,21 @@ func TwoOpenSea(oneClassA, oneClassB, oneClassC map[string]bool) (aMap, bMap, cM
 		if err != nil {
 			log.Println("row scan err:", err)
 		}
-		uuid := GetClueIdByUserId(userid)
-		if oneClassA[uuid] || oneClassB[uuid] || oneClassC[uuid] {
+		clubId := GetClueIdByUserId(userid)
+		if oneClassA[clubId] || oneClassB[clubId] || oneClassC[clubId] {
 			continue
 		}
 		if ct >= 15 {
-			aMap[uuid] = true
+			aMap[clubId] = true
 		}
 		if ct < 15 && ct >= 10 {
-			bMap[uuid] = true
+			bMap[clubId] = true
 		}
 		if ct < 10 && ct >= 5 {
-			cMap[uuid] = true
+			cMap[clubId] = true
 		}
 		if ct < 5 && ct >= 1 {
-			dMap[uuid] = true
+			dMap[clubId] = true
 		}
 	}
 	// Check for errors during iteration
@@ -334,14 +309,14 @@ func TwoOpenSea(oneClassA, oneClassB, oneClassC map[string]bool) (aMap, bMap, cM
 
 // 三级公海:
 // 最近30天内活跃天数=0天的客户。
-func ThreeOpenSea() {
+func ThreeOpenSea(oneA, oneB, oneC, twoA, twoB, twoC, twoD map[string]bool) {
 	ctx := gctx.New()
 	t := time.Now()
 	t = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local)
 	day := g.Cfg().MustGet(ctx, "classThreeHighSeaslastDay").Int()
-	t.AddDate(0, 0, day)
+	t = t.AddDate(0, 0, -day)
 	start := util.GetObjectId(t.Unix())
-	createtime := time.Now().Format(date.Date_Full_Layout)
+	log.Println(t.Format(date.Date_Full_Layout), "~~")
 
 	config.JianyuSubjectdb.SelectByBath(500, func(l *[]map[string]interface{}) bool {
 		for _, v := range *l {
@@ -352,13 +327,16 @@ func ThreeOpenSea() {
 					"$gte": start,
 				},
 			}
-			// uuid := gconv.String(v["uid"])
 			id := gconv.Int64(v["id"])
+			clubId := gconv.String(v["id"])
 			if r, ok := config.MgoLog.Find("subscribepay_logs", query, nil, `{"_id":1}`, false, 0, 1); ok && r != nil && len(*r) == 0 {
-				config.JianyuSubjectdb.ExecBySql(`INSERT INTO dwd_f_crm_open_sea (comeintime,comeinsource,LEVEL,clue_level,clue_id) 
-												VALUES(?,?,?,?,?)
-												ON DUPLICATE KEY UPDATE comeintime=?,comeinsource=?,LEVEL=?,clue_level=?`, createtime, 1, 3, "D", id, createtime, 1, 3, "D")
-
+				if oneA[clubId] || oneB[clubId] || oneC[clubId] || twoA[clubId] || twoB[clubId] || twoC[clubId] || twoD[clubId] {
+					continue
+				}
+				config.JianyuSubjectdb.Update("dwd_f_crm_open_sea", map[string]interface{}{"clue_id": id}, map[string]interface{}{
+					"LEVEL":      3,
+					"clue_level": "D",
+				})
 			}
 		}
 		return true
@@ -381,18 +359,20 @@ func GetClueIdByUserId(userid string) (uuid string) {
 // level 公海级别
 // clue_level线索级别
 func AddOpenSea(m map[string]bool, level int, clue_level string) {
-	createtime := time.Now().Format(date.Date_Full_Layout)
+	// createtime := time.Now().Format(date.Date_Full_Layout)
 	if len(m) > 0 {
 		for _, v := range m {
-			config.JianyuSubjectdb.ExecBySql(`INSERT INTO dwd_f_crm_open_sea (comeintime,comeinsource,LEVEL,clue_level,clue_id) 
-												VALUES(?,?,?,?,?)
-												ON DUPLICATE KEY UPDATE comeintime=?,comeinsource=?,LEVEL=?,clue_level=?`, createtime, 1, level, clue_level, v, createtime, 1, level, clue_level)
+			config.JianyuSubjectdb.Update("dwd_f_crm_open_sea", map[string]interface{}{"clue_id": v}, map[string]interface{}{
+				"clue_level": clue_level,
+				"LEVEL":      level,
+			})
 		}
 	}
 }
 
 // 自动退出公海
 // 线索状态为“空号停机”自动从线索池删除。
+// 空号停机 删除私海, 线索表分配状态改成 -1
 func DeleteOpenSea() {
 	config.JianyuSubjectdb.SelectByBath(500, func(l *[]map[string]interface{}) bool {
 		ids := []interface{}{}
@@ -405,12 +385,12 @@ func DeleteOpenSea() {
 			whs = append(whs, "?")
 		}
 		wh := strings.Join(whs, ",")
-		count := config.JianyuSubjectdb.UpdateOrDeleteBySql(`delete from dwd_f_crm_clue_info where id in (`+wh+`)`, ids...)
+		count := config.JianyuSubjectdb.UpdateOrDeleteBySql(`UPDATE dwd_f_crm_clue_info SET is_assign = -1 WHERE id in (`+wh+`)`, ids...)
 		if count > 0 {
 			return true
 		}
 		return true
-	}, `select id from dwd_f_crm_clue_info where trailstatus = ?`, "00")
+	}, `select id from dwd_f_crm_clue_info where trailstatus = ?`, "02")
 }
 
 //自动退回公海
@@ -428,36 +408,62 @@ func ReturnOpenSea() {
 	t := time.Now()
 	t = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local)
 	//高意向客户
-	highIntentionCustomer := g.Cfg().MustGet(ctx, "highIntentionCustomer").Int()
+	highIntentionCustomer := g.Cfg().MustGet(ctx, "highIntentionCustomer").Int() //30
 	//意向客户
-	intentionCustomer := g.Cfg().MustGet(ctx, "intentionCustomer").Int()
+	intentionCustomer := g.Cfg().MustGet(ctx, "intentionCustomer").Int() //30
 	//潜在客户
-	latentCustomer := g.Cfg().MustGet(ctx, "latentCustomer").Int()
+	latentCustomer := g.Cfg().MustGet(ctx, "latentCustomer").Int() //60
 	//沉睡客户
-	sleepCustomer := g.Cfg().MustGet(ctx, "sleepCustomer").Int()
+	sleepCustomer := g.Cfg().MustGet(ctx, "sleepCustomer").Int() //90
 	//商机线索
-	businessLeads := g.Cfg().MustGet(ctx, "businessLeads").Int()
+	businessLeads := g.Cfg().MustGet(ctx, "businessLeads").Int() //2
 	//无意向客户
-	noIdeaCustomer := g.Cfg().MustGet(ctx, "noIdeaCustomer").Int()
+	// noIdeaCustomer := g.Cfg().MustGet(ctx, "noIdeaCustomer").Int() //
+
+	codeMap := dwd_d_crm_trailstatus_code()
+
+	now := time.Now().Format(date.Date_Full_Layout)
+
 	//2.“高意向客户”超过30天未更新跟进记录自动退回公海;
 	for trailstatus, nexttime := range map[string]interface{}{
-		"04": t.AddDate(0, 0, -highIntentionCustomer),
+		"06": t.AddDate(0, 0, -highIntentionCustomer),
 		"05": t.AddDate(0, 0, -intentionCustomer),
-		"06": t.AddDate(0, 0, -latentCustomer),
-		"07": t.AddDate(0, 0, -sleepCustomer),
+		"04": t.AddDate(0, 0, -latentCustomer),
+		"03": t.AddDate(0, 0, -sleepCustomer),
 		"01": t.AddDate(0, 0, -businessLeads),
-		"08": t.AddDate(0, 0, -noIdeaCustomer),
+		"00": t,
 	} {
+		sql := `SELECT MAX(c.next_time) nexttime, b.id FROM dwd_f_crm_private_sea a 
+				LEFT JOIN dwd_f_crm_clue_info b ON a.clue_id=b.id 
+				LEFT JOIN  dwd_f_crm_trail_content c ON b.id =c.clue_id 
+				WHERE b.trailstatus =?`
+		argsSelect := []interface{}{trailstatus}
+		if trailstatus != "00" {
+			sql += " AND c.createtime <? "
+			argsSelect = append(argsSelect, nexttime)
+		}
+		sql += " GROUP BY  b.id"
 		config.JianyuSubjectdb.SelectByBath(500, func(l *[]map[string]interface{}) bool {
 			//1新增 2私海手动退回 3私海高意向客户自动退回 4私海意向客户退回 5私海潜在客户退回 6私海沉睡客户退回 7私海商机线索退回 8私海无意向客户退回
 			comeinsource := GetComeSource()[trailstatus]
 			ids := []interface{}{}
 			args := []interface{}{}
+			changeArgs1 := []interface{}{}
+			changeArgs2 := []interface{}{}
+			changeArgs3 := []interface{}{}
+			changeArgs4 := []interface{}{}
 			for _, v := range *l {
 				id := v["id"]
+				position_id := v["position_id"]
+				seatNumber := gconv.String(v["seatNumber"])
 				ids = append(ids, id)
 				//
-				args = append(args, id, time.Now().Format(date.Date_Full_Layout), comeinsource)
+				args = append(args, id, now, comeinsource)
+				changeArgs1 = append(changeArgs1, id, position_id, "trailstatus", "线索状态变更", codeMap[trailstatus], "流失", now, -1)
+				changeArgs2 = append(changeArgs2, id, position_id, "position_id", "所属人变更", GetPositionName(seatNumber), "/", now, -1)
+				changeArgs3 = append(changeArgs3, id, position_id, "退出任务车", "未更新跟进记录自动退回公海", now, -1)
+				changeArgs3 = append(changeArgs3, id, position_id, "退回公海", "未更新跟进记录自动退回公海", now, -1)
+
 			}
 			whs := []string{}
 			for i := 0; i < len(ids); i++ {
@@ -468,24 +474,34 @@ func ReturnOpenSea() {
 			count := config.JianyuSubjectdb.UpdateOrDeleteBySql(`delete from dwd_f_crm_private_sea  where clue_id in (`+wh+`)`, ids...)
 			//进入公海
 			config.JianyuSubjectdb.InsertIgnoreBatch("dwd_f_crm_open_sea", []string{"clue_id", "comeintime", "comeinsource"}, args)
-			//
+			//改线索表 职位id  坐席号 弄成空 分配状态改成未分配
+			config.JianyuSubjectdb.UpdateOrDeleteBySql(`UPDATE dwd_f_crm_clue_info SET seatNumber ='',position_id=0,is_assign=0  WHERE id in (`+wh+`)`, ids...)
+
+			// 添加线索修改记录
+
+			//线索状态变更记录
+			config.JianyuSubjectdb.InsertBatch("dwd_f_crm_clue_change_record", []string{"clue_id", "position_id", "change_field", "change_type", "old_value", "new_value", "createtime", "operator_id"}, changeArgs1)
+			config.JianyuSubjectdb.InsertBatch("dwd_f_crm_clue_change_record", []string{"clue_id", "position_id", "change_field", "change_type", "old_value", "new_value", "createtime", "operator_id"}, changeArgs2)
+			config.JianyuSubjectdb.InsertBatch("dwd_f_crm_clue_change_record", []string{"clue_id", "position_id", "change_type", "new_value", "createtime", "operator_id"}, changeArgs3)
+			config.JianyuSubjectdb.InsertBatch("dwd_f_crm_clue_change_record", []string{"clue_id", "position_id", "change_type", "new_value", "createtime", "operator_id"}, changeArgs4)
 			if count > 0 {
 				return true
 			}
 			return true
-		}, `SELECT MAX(c.next_time) nexttime, b.id FROM dwd_f_crm_private_sea a 
-				LEFT JOIN dwd_f_crm_clue_info b ON a.clue_id=b.id 
-				LEFT JOIN  dwd_f_crm_trail_content c ON b.id =c.clue_id 
-				WHERE b.trailstatus =? AND c.next_time >?  GROUP BY  b.id`, trailstatus, nexttime)
+		}, sql, argsSelect...)
 	}
 	log.Println("return sea end")
 }
 
+//2私海手动退回 3私海高意向客户自动退回 4私海意向客户退回 5私海潜在客户退回 6私海沉睡客户退回 7私海商机线索退回 8私海无意向客户退回
 func GetComeSource() map[string]int {
 	return map[string]int{
-		"04": 2,
-		"05": 4,
 		"06": 3,
+		"05": 4,
+		"04": 5,
+		"03": 6,
+		"01": 7,
+		"00": 8,
 	}
 }
 
@@ -499,3 +515,22 @@ func GetOneSeaC() map[string]bool {
 	}, `select clue_id from dwd_f_crm_open_sea where comeinsource in(2,3,4)`)
 	return m
 }
+
+func dwd_d_crm_trailstatus_code() map[string]string {
+	m := map[string]string{}
+	data := config.JianyuSubjectdb.SelectBySql(`SELECT CODE,NAME FROM dwd_d_crm_trailstatus_code;`)
+	for _, v := range *data {
+		code := gconv.String(v["CODE"])
+		name := gconv.String(v["NAME"])
+		m[code] = name
+	}
+	return m
+}
+
+func GetPositionName(seatNumber string) string {
+	data := config.JianyuSubjectdb.SelectBySql(`select name from jy_salesperson_info where status = 0 and position != 0 and seatNumber = ? limit 1`, seatNumber)
+	if data != nil && len(*data) > 0 {
+		return gconv.String((*data)[0]["name"])
+	}
+	return ""
+}

+ 0 - 1
telemarketingEtl/entity/dwd_f_userbase_event_info.go

@@ -226,7 +226,6 @@ func EventInfoAdd(start, end int64) {
 								<-Pool
 								Wait.Done()
 							}()
-							//插入推送记录表
 							if len(values) > 0 {
 								id1, _ := config.JianyuSubjectdb.InsertBatch(DWD_F_USERBASE_EVENT_INFO, fields, values) //id1:数量  id2:开始id索引
 								if id1 <= 0 {

+ 2 - 2
telemarketingEtl/entity/dwd_f_userbase_visit_info.go

@@ -93,9 +93,9 @@ func VisitInfoAdd(start, end int64) {
 					defer lock(userid).Unlock()
 					if config.JianyuSubjectdb.CountBySql(`select count(1) from dwd_f_userbase_visit_info where userid = ? and createtime>= ? and createtime <?`, userid, starttime, endtime) > 0 {
 						if contentnum == 0 {
-							config.JianyuSubjectdb.UpdateOrDeleteBySql(`update dwd_f_userbase_visit_info set number = number+1,date =? where userid = ? and createtime>= ? and createtime <?`, craetetimeStr, userid, starttime, endtime)
+							config.JianyuSubjectdb.UpdateOrDeleteBySql(`update dwd_f_userbase_visit_info set number = number+1,date =?,platform=? where userid = ? and createtime>= ? and createtime <?`, craetetimeStr, platform, userid, starttime, endtime)
 						} else {
-							config.JianyuSubjectdb.UpdateOrDeleteBySql(`update dwd_f_userbase_visit_info set number = number+1,contentnum = contentnum + 1,date =? where userid = ? and createtime>= ? and createtime <?`, craetetimeStr, userid, starttime, endtime)
+							config.JianyuSubjectdb.UpdateOrDeleteBySql(`update dwd_f_userbase_visit_info set number = number+1,contentnum = contentnum + 1,date =?,platform=? where userid = ? and createtime>= ? and createtime <?`, craetetimeStr, platform, userid, starttime, endtime)
 						}
 					} else {
 						config.JianyuSubjectdb.InsertBySql(`INSERT INTO dwd_f_userbase_visit_info

+ 1 - 2
telemarketingEtl/entity/entity.go

@@ -8,7 +8,7 @@ import (
 
 // 平台
 const (
-	APP = iota
+	APP = iota + 1
 	PC
 	WX
 	//
@@ -20,7 +20,6 @@ const (
 	ENTPORTRAIT = "企业画像"
 	LOGIN       = "登录"
 	COLLECTION  = "标讯收藏"
-	//TODO
 )
 
 // 根据职位id获取mongodb userid

+ 20 - 6
telemarketingEtl/timetask/task.go

@@ -12,12 +12,26 @@ import (
 	"github.com/gogf/gf/v2/os/gctx"
 )
 
+/*
+#查看
+eventInfoTime: 5
+#搜索
+searchInfoTime: 5
+#每日
+visitInfoTime: 5
+#定时
+openSeaTime: 5
+#退出
+deleteOpenSeaTime: 5
+#自动退出
+returnOpenSeaTime: 5
+*/
 func TaskEventInfo() {
 	log.Println("开始TaskEventInfo")
 	now := time.Now()
 	end := now.Unix()
-	// start := now.Add(-time.Hour * 1).Unix()
-	start := now.Add(-time.Minute * 5).Unix()
+	min := gcfg.Instance().MustGet(gctx.New(), "eventInfoTime", "").Int()
+	start := now.Add(-time.Minute * time.Duration(min)).Unix()
 	//查看事件
 	entity.EventInfoAdd(start, end)
 	log.Println("结束TaskEventInfo")
@@ -27,8 +41,8 @@ func TaskSearchInfo() {
 	log.Println("开始TaskSearchInfo")
 	now := time.Now()
 	end := now.Unix()
-	// start := now.Add(-time.Hour * 1).Unix()
-	start := now.Add(-time.Minute * 5).Unix()
+	min := gcfg.Instance().MustGet(gctx.New(), "searchInfoTime", "").Int()
+	start := now.Add(-time.Minute * time.Duration(min)).Unix()
 	//搜索事件
 	entity.SearchInfoAdd(start, end)
 }
@@ -37,8 +51,8 @@ func TaskVisitInfo() {
 	log.Println("开始TaskVisitInfo")
 	now := time.Now()
 	end := now.Unix()
-	// start := now.Add(-time.Hour * 1).Unix()
-	start := now.Add(-time.Minute * 5).Unix()
+	min := gcfg.Instance().MustGet(gctx.New(), "visitInfoTime", "").Int()
+	start := now.Add(-time.Minute * time.Duration(min)).Unix()
 	entity.VisitInfoAdd(start, end)
 	log.Println("结束TaskVisitInfo")
 }