wkyuer před 2 měsíci
rodič
revize
064393565d

+ 4 - 3
userSign/config.yaml

@@ -4,13 +4,14 @@ database:
     link: "clickhouse:jianyu_appl:Cli3#fkh4ouSe@tcp(127.0.0.1:9420)/pub_tags?dial_timeout=2000ms&max_execution_time=60"
     #debug: true
   jianyu:
-    link: "mysql:root:=PDT49#80Z!RVv52_z@tcp(192.168.3.14:4000)/jianyu"
+    link: "mysql:jianyu:Topnet123@tcp(172.20.45.129:4000)/jianyu"
     debug: true
   ckLogs:
     link: "clickhouse:jytop:pwdTopJy123@tcp(172.20.45.129:19000)/data_analysis?dial_timeout=2000ms&max_execution_time=60"
     debug: false
-
-
+  subjectdb:
+    link: "mysql:jianyu:Topnet123@tcp(172.20.45.129:4000)/jianyu_subjectdb_test"
+    debug: true
 
 mongodb:
   default:

+ 33 - 31
userSign/main.go

@@ -2,7 +2,6 @@ package main
 
 import (
 	"context"
-	"fmt"
 	_ "github.com/gogf/gf/contrib/drivers/clickhouse/v2"
 	_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
 	"github.com/gogf/gf/v2/frame/g"
@@ -13,6 +12,16 @@ import (
 	"workTasks/userSign/userTag"
 )
 
+func main1() {
+	ctx := gctx.New()
+	t := time.Unix(1738857600, 0)
+	list, err := g.DB("subjectdb").Query(ctx, "SELECT position_id FROM dwd_f_crm_clue_change_record WHERE position_id!=-1 AND change_type='基本信息变更' AND new_value in ('意向客户','高意向客户','待签署客户') AND createtime>?", t.Format("2006-01-02 15:04:05"))
+	if err != nil {
+		panic(err)
+	}
+	g.Dump(list.Size())
+}
+
 func main() {
 	ctx := gctx.New()
 	runOnce(context.TODO())
@@ -56,40 +65,33 @@ func runOnce(ctx context.Context) {
 		allRes = append(allRes, res...)
 	}
 	var (
-		sourceArr    = []string{"pc", "wx", "app"}
-		nowTime      = time.Now()
-		unActiveTime = []int{30, 90}
+		nowTime = time.Now()
 	)
-	//活跃用户分析
-	for _, day := range unActiveTime {
-		if day == 30 { //30天活跃用户各端
-			for _, source := range sourceArr {
-				if res, err := manager.ActiveUserLoad(ctx, nowTime.AddDate(0, 0, -day), source); err == nil && len(res) > 0 {
-					allRes = append(allRes, &userAnalysis.AnalysisRes{Name: fmt.Sprintf("30天%s活跃用户", source), Code: fmt.Sprintf("active_%s_%d", source, 30), Data: res})
-				}
-			}
-		}
-		if res, err := manager.ActiveUserLoad(ctx, nowTime.AddDate(0, 0, -day), ""); err == nil && len(res) > 0 {
-			allRes = append(allRes, &userAnalysis.AnalysisRes{Name: fmt.Sprintf("%d天活跃用户", day), Code: fmt.Sprintf("active_%d", day), Data: res})
-		}
+	// 日志标签
+	logRes, logErr := manager.GetLogRes(ctx, nowTime)
+	if logErr != nil {
+		g.Log().Errorf(ctx, "日志标签异常%v", logErr)
 	}
-	// 近7天访问详情页次数大于5
-	var (
-		dayLimit     = 7
-		articleLimit = 5
-	)
-	if res, err := manager.ArticleVisit(ctx, nowTime.AddDate(0, 0, -dayLimit), articleLimit); err == nil && len(res) > 0 {
-		allRes = append(allRes, &userAnalysis.AnalysisRes{Name: fmt.Sprintf("%d天内访问详情页次数大于%d次", dayLimit, articleLimit), Code: fmt.Sprintf("%dday_article_gt_%d", dayLimit, articleLimit), Data: res})
+	for _, re := range logRes {
+		allRes = append(allRes, re)
 	}
-	// 已访问过
-	if res, err := manager.Visited(ctx, nowTime.AddDate(0, 0, -7)); err == nil && len(res) > 0 {
-		allRes = append(allRes, &userAnalysis.AnalysisRes{Name: "访问过剑鱼产品", Code: "visited", Data: res, SaveOldData: true})
+
+	// 电销标签
+	telemarketingRes, telemarketingErr := manager.GetTelemarketingRes(ctx, nowTime)
+	if telemarketingErr != nil {
+		g.Log().Errorf(ctx, "电销标签异常%v", telemarketingErr)
 	}
-	// 访问过指定页面
-	if res, err := manager.GetVisitUserAnalysis(ctx, nowTime.AddDate(0, 0, -45)); err == nil && len(res) > 0 {
-		for _, t := range res {
-			allRes = append(allRes, t)
-		}
+	for _, re := range telemarketingRes {
+		allRes = append(allRes, re)
+	}
+
+	// 埋点数据分析
+	buryPointRes, buryPointErr := manager.GetBuryPointRes(ctx, nowTime)
+	if buryPointErr != nil {
+		g.Log().Errorf(ctx, "埋点数据分析%v", buryPointErr)
+	}
+	for _, re := range buryPointRes {
+		allRes = append(allRes, re)
 	}
 
 	for _, re := range allRes {

+ 30 - 0
userSign/userAnalysis/buryPoint.go

@@ -0,0 +1,30 @@
+package userAnalysis
+
+import (
+	"context"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/util/gconv"
+	"github.com/pkg/errors"
+	"time"
+)
+
+// GetBuryPointRes 分析埋点数据
+func (ua *UserAnalysis) GetBuryPointRes(ctx context.Context, runTime time.Time) ([]*AnalysisRes, error) {
+	//分析点击分享 近7天点击标讯分享按钮>=2
+	rData := map[BaseUserId]bool{}
+	res, err := g.DB("ckLogs").Query(ctx, "SELECT position_id FROM dwd_f_personnel_behavior WHERE page_id ='article_content' AND  breaker_name in ('QQ','朋友圈','微信') AND `date` > ? ", runTime.AddDate(0, 0, -7).Format(time.DateTime))
+	if err != nil {
+		return nil, errors.Wrap(err, "查询超级订阅购买页访问数据异常")
+	}
+	for _, m := range res.List() {
+		var (
+			position_id = gconv.String(m["position_id"])
+		)
+		if baseUserId, ok := ua.UserMapping[position_id]; !ok {
+			rData[baseUserId] = true
+		}
+	}
+	return []*AnalysisRes{
+		{"近30天电销意向客户", "buryPoint_share_7_day_gte2", rData, false},
+	}, nil
+}

+ 63 - 12
userSign/userAnalysis/jobLogsAnalysis.go

@@ -2,18 +2,48 @@ package userAnalysis
 
 import (
 	"context"
+	"fmt"
 	"github.com/gogf/gf/v2/frame/g"
 	"github.com/gogf/gf/v2/util/gconv"
 	"time"
 )
 
-var (
-	ctx           = context.TODO()
-	ActiveCodeMap map[string]interface{}
-)
+func (ua *UserAnalysis) GetLogRes(ctx context.Context, runTime time.Time) ([]*AnalysisRes, error) {
+	var (
+		sourceArr    = []string{"pc", "wx", "app"}
+		unActiveTime = []int{30, 90}
+		returnData   = []*AnalysisRes{}
+	)
+	//活跃用户分析
+	for _, day := range unActiveTime {
+		if day == 30 { //30天活跃用户各端
+			for _, source := range sourceArr {
+				if res, err := ua.ActiveUserLoad(ctx, runTime.AddDate(0, 0, -day), source); err == nil && len(res) > 0 {
+					returnData = append(returnData, &AnalysisRes{Name: fmt.Sprintf("30天%s活跃用户", source), Code: fmt.Sprintf("active_%s_%d", source, 30), Data: res})
+				}
+			}
+		}
+		if res, err := ua.ActiveUserLoad(ctx, runTime.AddDate(0, 0, -day), ""); err == nil && len(res) > 0 {
+			returnData = append(returnData, &AnalysisRes{Name: fmt.Sprintf("%d天活跃用户", day), Code: fmt.Sprintf("active_%d", day), Data: res})
+		}
+	}
+	//标讯详情页访问
+	if res, err := ua.ArticleVisit(ctx, runTime.AddDate(0, 0, -7)); err == nil && len(res) > 0 {
+		returnData = append(returnData, res...)
+		//returnData = append(returnData, &AnalysisRes{Name: fmt.Sprintf("%d天内访问详情页次数%s", param.Day, param.Compare), Code: fmt.Sprintf("%dday_article_gt_%d", param.Day, param.Compare), Data: res})
+	}
 
-func init() {
-	ActiveCodeMap = g.Cfg().MustGet(ctx, "activeCode.pcCode").Map()
+	// 已访问过
+	if res, err := ua.Visited(ctx, runTime.AddDate(0, 0, -7)); err == nil && len(res) > 0 {
+		returnData = append(returnData, &AnalysisRes{Name: "访问过剑鱼产品", Code: "visited", Data: res, SaveOldData: true})
+	}
+	// 访问过指定页面
+	if res, err := ua.GetVisitUserAnalysis(ctx, runTime.AddDate(0, 0, -45)); err == nil && len(res) > 0 {
+		for _, t := range res {
+			returnData = append(returnData, t)
+		}
+	}
+	return returnData, nil
 }
 
 // ActiveUserLoad 活跃用户
@@ -57,17 +87,38 @@ func (ua *UserAnalysis) UnActiveUserLoad(ctx context.Context, start time.Time) (
 }
 
 // ArticleVisit 指定时间内访问详情页数量大于num次的用户
-func (ua *UserAnalysis) ArticleVisit(ctx context.Context, start time.Time, num int) (map[BaseUserId]bool, error) {
-	rPc, err := g.DB().Query(ctx, `SELECT sum(article) as articleCount,baseUserId FROM pub_tags.user_log_byHour WHERE create_time > ? GROUP BY  baseUserId HAVING articleCount>?`, start.Format(time.DateTime), num)
+func (ua *UserAnalysis) ArticleVisit(ctx context.Context, start time.Time) ([]*AnalysisRes, error) {
+	var (
+		d1, d2, d3 = map[BaseUserId]bool{}, map[BaseUserId]bool{}, map[BaseUserId]bool{}
+	)
+
+	rPc, err := g.DB().Query(ctx, `SELECT sum(article) as articleCount,baseUserId FROM pub_tags.user_log_byHour WHERE create_time > ? GROUP BY  baseUserId HAVING articleCount >5 `, start.Format(time.DateTime))
 	if err != nil {
 		return nil, err
 	}
-	articleUser := map[BaseUserId]bool{}
 	for _, m := range rPc.List() {
-		// 插入pc30天活跃用户
-		articleUser[BaseUserId(gconv.Int64(m["baseUserId"]))] = true
+		var (
+			baseUserId = BaseUserId(gconv.Int64(m["baseUserId"]))
+			count      = gconv.Int64(m["articleCount"])
+		)
+		if baseUserId <= 0 {
+			continue
+		}
+		if count > 5 {
+			d1[baseUserId] = true
+		}
+		if count >= 7 {
+			d2[baseUserId] = true
+		}
+		if count >= 10 {
+			d3[baseUserId] = true
+		}
 	}
-	return articleUser, nil
+	return []*AnalysisRes{
+		{"7天内访问详情页次数>5", "7day_article_gt_5", d1, false},
+		{"7天内访问详情页次数>=7", "7day_article_gte_7", d2, false},
+		{"7天内访问详情页次数>=10", "7day_article_gte_10", d3, false},
+	}, nil
 }
 
 // Visited 指定日期内访问过剑鱼

+ 130 - 0
userSign/userAnalysis/telemarketing.go

@@ -0,0 +1,130 @@
+package userAnalysis
+
+import (
+	"context"
+	"github.com/gogf/gf/v2/errors/gerror"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/util/gconv"
+	"time"
+)
+
+type jyTelemarketing struct {
+	Intended30Day          map[BaseUserId]bool // 近30天电销意向客户
+	HighIntended30Day      map[BaseUserId]bool // 近30天电销高意向客户
+	BeSigned30Day          map[BaseUserId]bool // 近30天电销待签署客户
+	Follow7Day, Listen7Day map[BaseUserId]bool
+	HasEffectiveCall30Day  map[BaseUserId]bool // 30天有效通话时长
+}
+
+func (ua *UserAnalysis) GetTelemarketingRes(ctx context.Context, t time.Time) ([]*AnalysisRes, error) {
+	jyT := &jyTelemarketing{
+		Intended30Day:     map[BaseUserId]bool{}, // 近30天电销意向客户
+		HighIntended30Day: map[BaseUserId]bool{}, // 近30天电销高意向客户
+		BeSigned30Day:     map[BaseUserId]bool{}, // 近30天电销待签署客户
+		Follow7Day:        map[BaseUserId]bool{}, // 近7天内有销售人员创建跟进记录
+		Listen7Day:        map[BaseUserId]bool{}, // 近7天内无销售人员接听记录
+		//近30天电销有效通话大于60秒
+		HasEffectiveCall30Day: map[BaseUserId]bool{}, // 30天有效通话时长
+	}
+	if err := ua.initTelemarketingIntended(ctx, jyT, t.AddDate(0, -30, 0)); err != nil {
+		g.Log().Error(ctx, "init telemarketing intended failed", err)
+	}
+	if err := ua.initFollowListen(ctx, jyT, t.AddDate(0, -7, 0)); err != nil {
+		g.Log().Errorf(ctx, "init follow listen err:%v", err)
+	}
+	//有效通话时长
+	if err := ua.initHasEffectiveCall(ctx, jyT, t.AddDate(0, -30, 0)); err != nil {
+		g.Log().Errorf(ctx, "init hasEffectiveCall err:%v", err)
+	}
+	return []*AnalysisRes{
+		{"近30天电销意向客户", "telemarketing_intended_30_day", jyT.Intended30Day, false},
+		{"近30天电销高意向客户", "telemarketing_highIntended_30_day", jyT.HighIntended30Day, false},
+		{"近30天电销待签署客户", "telemarketing_beSigned_30_day", jyT.BeSigned30Day, false},
+		{"近7天内有销售人员创建跟进记录", "telemarketing_follow_7_day", jyT.Follow7Day, false},
+		{"近7天内无销售人员接听记录", "telemarketing_listen_7_day", jyT.Listen7Day, false},
+		{"近30天电销有效通话", "telemarketing_hasCall_30_day", jyT.HasEffectiveCall30Day, false},
+	}, nil
+}
+
+func (ua *UserAnalysis) initTelemarketingIntended(ctx context.Context, jyT *jyTelemarketing, t time.Time) (err error) {
+	res, err := g.DB("subjectdb").Query(ctx, "SELECT position_id,new_value FROM dwd_f_crm_clue_change_record WHERE position_id!=-1 AND change_type='基本信息变更' AND new_value in ('意向客户','高意向客户','待签署客户') AND createtime >? ", t.Format(time.DateTime))
+	if err != nil {
+		return err
+	}
+	for _, m := range res.List() {
+		var (
+			position_id = gconv.String(m["position_id"])
+			new_value   = gconv.String(m["new_value"])
+		)
+		if baseUserId, ok := ua.UserMapping[position_id]; !ok {
+			switch new_value {
+			case "意向客户":
+				jyT.Intended30Day[baseUserId] = true
+			case "高意向客户":
+				jyT.HighIntended30Day[baseUserId] = true
+			case "待签署客户":
+				jyT.BeSigned30Day[baseUserId] = true
+			}
+		}
+	}
+	return
+}
+
+func (ua *UserAnalysis) initFollowListen(ctx context.Context, jyT *jyTelemarketing, t time.Time) (err error) {
+	res, err := g.DB("subjectdb").Query(ctx, "SELECT userid FROM dwd_f_crm_clue_info WHERE trail_time >? ", t.Format(time.DateTime))
+	if err == nil {
+		for _, m := range res.List() {
+			var (
+				userId = gconv.String(m["userid"])
+			)
+			if baseUserId, ok := ua.UserMapping[userId]; !ok {
+				jyT.Follow7Day[baseUserId] = true
+			}
+		}
+	}
+
+	res2, err2 := g.DB("subjectdb").Query(ctx, "SELECT userid FROM dwd_f_crm_clue_info WHERE trail_timelast_begin_time >? ", t.Format(time.DateTime))
+	if err2 == nil {
+		for _, m := range res2.List() {
+			var (
+				userId = gconv.String(m["userid"])
+			)
+			if baseUserId, ok := ua.UserMapping[userId]; !ok {
+				jyT.Listen7Day[baseUserId] = true
+			}
+		}
+	}
+	var errMsg string
+	if err != nil {
+		errMsg = err.Error()
+	}
+	if err2 != nil {
+		errMsg += err2.Error()
+	}
+	return gerror.New(errMsg)
+}
+
+func (ua *UserAnalysis) initHasEffectiveCall(ctx context.Context, jyT *jyTelemarketing, t time.Time) (err error) {
+	res, err := g.DB("subjectdb").Query(ctx, `SELECT userid FROM dwd_f_crm_clue_info WHERE phone in (
+	SELECT phone
+	FROM (
+	  SELECT DISTINCT(CallNo) AS phone FROM Call_Accounting.voice_record WHERE CallTimeLength>60 AND  createTime>?
+	  UNION ALL
+	  SELECT DISTINCT(CalledNo) AS phone FROM Call_Accounting.voice_record WHERE  CallTimeLength>60  AND  createTime>?
+	) AS temp
+	WHERE phone IS NOT NULL  -- 如需保留 NULL,删除此条件
+	GROUP BY phone
+	)`, t.Format(time.DateTime), t.Format(time.DateTime))
+	if err != nil {
+		return err
+	}
+	for _, m := range res.List() {
+		var (
+			userId = gconv.String(m["userid"])
+		)
+		if baseUserId, ok := ua.UserMapping[userId]; !ok {
+			jyT.HasEffectiveCall30Day[baseUserId] = true
+		}
+	}
+	return
+}