Эх сурвалжийг харах

Merge branch 'feature/v1.5.27' of jianyu/datatools into hotfix/v1.5.27.3

王浩 5 сар өмнө
parent
commit
c6f052b31f

+ 5 - 1
clueSync/config.go

@@ -32,6 +32,7 @@ type (
 		RebindTime              string  `json:"rebindTime"`
 		InviteTime              string  `json:"inviteTime"`
 		ActivityTime            string  `json:"activityTime"`
+		LastKcChangeTime        string  `json:"lastKcChangeTime"`
 	}
 	DB struct {
 		CornExp1      int64  `json:"cornexp1"`
@@ -206,8 +207,11 @@ type (
 			Message            string `json:"message"`
 			MessageServiceList string `json:"messageServiceList"`
 			MessageReturnMoney string `json:"messageReturnMoney"`
+			Admin              string `json:"admin"`
 		} `json:"keCheng"`
-		Mail GmailAuth `json:"mail"` //邮箱配置
+		EntId int       `json:"entId"`
+		Mail  GmailAuth `json:"mail"` //邮箱配置
+
 	}
 )
 type GmailAuth struct {

+ 1 - 26
clueSync/config.json

@@ -1,26 +1 @@
-{
-  "lastOrderId": 260273,
-  "lastOrderClueId": "2024-09-19 11:51:37",
-  "lastUserId": "2024-05-20 15:40:02",
-  "lastXcxUserId": "2024-07-09 14:59:37",
-  "lastId": "66cd4d3ae83797f8bf5e7ca2",
-  "lastOrderTime": "2023-04-25 00:00:00",
-  "lastUserTime": "2024-07-09 11:54:02",
-  "lastSubscribeId": "6459d89a8edef707156e9cc6",
-  "lastMessageTime": "2024-07-16 14:26:26",
-  "lastkcTime": "2025-01-08 11:18:00",
-  "lastEverythingTime": "",
-  "lastEventRegTime": "",
-  "lastReadClueTime": "",
-  "bigSaleTime": 1718241923,
-  "bigOrderTime": "2024-06-12 17:01:39",
-  "marketSaleTime": 1708160200,
-  "advisoryCommitteeTime": 1724136683,
-  "selectionDepartmentTime": 0,
-  "allocationTime": "2024-07-01 14:59:37",
-  "allocationRatio": 2,
-  "activeTime": "2024-07-01 14:59:37",
-  "rebindTime": "2024-08-27 16:10:27",
-  "inviteTime": "2024-11-20 14:42:11",
-  "activityTime": "2025-01-15 14:29:30"
-}
+{"lastOrderId":260273,"lastOrderClueId":"2024-09-19 11:51:37","lastUserId":"2024-05-20 15:40:02","lastXcxUserId":"2024-07-09 14:59:37","lastId":"66cd4d3ae83797f8bf5e7ca2","lastOrderTime":"2023-04-25 00:00:00","lastUserTime":"2024-07-09 11:54:02","lastSubscribeId":"6459d89a8edef707156e9cc6","lastMessageTime":"2024-07-16 14:26:26","lastkcTime":"2025-01-08 11:18:00","lastEverythingTime":"","lastEventRegTime":"","lastReadClueTime":"","bigSaleTime":1718241923,"bigOrderTime":"2024-06-12 17:01:39","marketSaleTime":1708160200,"advisoryCommitteeTime":1724136683,"selectionDepartmentTime":0,"allocationTime":"2024-07-01 14:59:37","allocationRatio":2,"activeTime":"2024-07-01 14:59:37","rebindTime":"2024-08-27 16:10:27","inviteTime":"2024-11-20 14:42:11","lastKcChangeTime":"2025-01-22 15:22:05"}

+ 4 - 2
clueSync/db.json

@@ -182,6 +182,8 @@
     },
     "message":"该订单用户已经完成支付,烦请对接后续售后服务事项,谢谢!\n产品名称:%s 公司名称:%s 联系方式:%s 联系人姓名:%s 订单编号:%s 合同金额:%.2f 使用起止时间:%s 分配客成:%s 签署销售:%s%s",
     "messageServiceList":" 服务列表:%s",
-    "messageReturnMoney":" 回款金额:%.2f"
-  }
+    "messageReturnMoney":" 回款金额:%.2f",
+    "admin": "郑慧慧"
+  },
+  "entId": 25917
 }

+ 2 - 7
clueSync/everything.go

@@ -613,13 +613,8 @@ func bigCustomer() {
 			if err != nil {
 				log.Println("xls error", err, dir)
 			} else {
-				gmail := &mail.GmailAuth{
-					SmtpHost: db.Mail.SmtpHost,
-					SmtpPort: db.Mail.SmtpPort,
-					User:     db.Mail.User,
-					Pwd:      db.Mail.Pwd,
-				}
-				status := mail.GSendMail_q("剑鱼标讯", email, "", "", fileName, detailName, dir, fileName+".xlsx", gmail)
+
+				status := mail.GSendMail_q("剑鱼标讯", email, "", "", fileName, detailName, dir, fileName+".xlsx", &Gmail)
 				if status {
 					log.Println("send mail success", fileName, email)
 				}

+ 1 - 2
clueSync/jobutil.go

@@ -76,7 +76,6 @@ func WorkDataHandle(company, phone, demand, name, product string, acceptanceData
 	if cluename == "" {
 		cluename = phone //没有线索名,手机号代替
 	}
-
 	ok, data, saleData := false, map[string]interface{}{}, []map[string]interface{}{}
 	isGroup, isCommerce := GetCompanyType(cluename, uId)
 	uCount, _ := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"uid": uId}, "", ""), true //查当前线索是否已存在
@@ -1321,7 +1320,7 @@ func getPositionId(phone string) (positionId int64) {
 	userData, ok := Mgo.FindOne("user", map[string]interface{}{"s_phone": phone})
 	if ok && userData != nil && len(*userData) > 0 {
 		userId := common.Int64All((*userData)["base_user_id"])
-		positionData := Base.FindOne("base_position", map[string]interface{}{"type": 1, "ent_id": 25917, "user_id": userId}, "", "") //TODO ent_id
+		positionData := Base.FindOne("base_position", map[string]interface{}{"type": 1, "ent_id": db.EntId, "user_id": userId}, "", "") //TODO ent_id
 		if positionData != nil && len(*positionData) > 0 {
 			positionId = common.Int64All((*positionData)["id"])
 		}

+ 534 - 5
clueSync/kc.go

@@ -42,7 +42,6 @@ func kcSync() {
 		}
 		log.Println(strings.Join(arr, "`,`"))
 	}
-
 	common.WriteSysConfig(&cfg)
 	log.Println("客户成功系统移交定时任务结束")
 }
@@ -259,6 +258,13 @@ func kcJob(data map[string]interface{}) int {
 					"operator_id": -1,
 				})
 			}
+			if is_transfer == 1 {
+				if customerName == db.KeCheng.Admin {
+					TiDb.UpdateOrDeleteBySql(`update dwd_f_csm_customer_autodraw_record set count = count + 2 where name = ?`, customerName)
+				} else {
+					TiDb.UpdateOrDeleteBySql(`update dwd_f_csm_customer_autodraw_record set count = count + 1 where name = ?`, customerName)
+				}
+			}
 			KcSend(orderCode, customerName)
 			TiDb.Update("dwd_f_crm_clue_info", map[string]interface{}{"id": clueId}, map[string]interface{}{"is_transfer": 1, "updatetime": nowTime, "name": userName})
 		}
@@ -307,6 +313,11 @@ func kcJob(data map[string]interface{}) int {
 			return cId > -1 && ok && updateId1 > -1 && updateId2 > -1 && updateId3 > -1
 		}) {
 			//TiDb.UpdateOrDeleteBySql(`update dwd_f_csm_customer_autodraw_record set count = count + 1 where name = ?`, name)
+			if customerName == db.KeCheng.Admin {
+				TiDb.UpdateOrDeleteBySql(`update dwd_f_csm_customer_autodraw_record set count = count + 2 where name = ?`, customerName)
+			} else {
+				TiDb.UpdateOrDeleteBySql(`update dwd_f_csm_customer_autodraw_record set count = count + 1 where name = ?`, customerName)
+			}
 			log.Println("保存客户成功")
 		} else {
 			log.Println("保存客户失败!!!", clueId, cId, ok, updateId1, updateId2, updateId3, " 用户信息 ", customerName, customerPositionId, uId)
@@ -316,11 +327,18 @@ func kcJob(data map[string]interface{}) int {
 }
 
 func cAutoDraw(entId int, orderPositionId int64, salesperson, saleDep string, isExist bool, csmdata *map[string]interface{}) (positionId int64, name string) {
-	query := `SELECT name,position_id FROM dwd_d_crm_department_level_succbi WHERE bi_pcode = (SELECT bi_code FROM dwd_d_crm_department_level_succbi WHERE name = "客户成功部" and resign=0) and resign = 0 `
-	data := TiDb.SelectBySql(query)
+	query := `SELECT name,position_id FROM dwd_d_crm_department_level_succbi WHERE bi_pcode = (SELECT bi_code FROM dwd_d_crm_department_level_succbi WHERE name = "客户成功部" and resign=0 and  ent_id=?) and resign = 0 `
+	data := TiDb.SelectBySql(query, db.EntId)
 	if data == nil || len(*data) == 0 {
 		return
 	}
+	positionId, name = findKcOldPerson(entId, orderPositionId, salesperson, saleDep, isExist, csmdata, data)
+	if positionId == 0 {
+		positionId, name = findKcNewPerson(entId, data)
+	}
+	return
+}
+func findKcOldPerson(entId int, orderPositionId int64, salesperson, saleDep string, isExist bool, csmdata *map[string]interface{}, data *[]map[string]interface{}) (positionId int64, name string) {
 	//判断是否需要新增客成数据
 	if isExist {
 		//用户存在客成数据
@@ -378,7 +396,66 @@ func cAutoDraw(entId int, orderPositionId int64, salesperson, saleDep string, is
 		return
 	}
 }
+func findKcNewPerson(entId int, data *[]map[string]interface{}) (positionId int64, name string) {
+	if entId > 0 {
+		entdata := TiDb.FindOne("dwd_f_csm_customer_info", map[string]interface{}{"ent_id": entId}, "", "")
+		if entdata != nil && len(*entdata) > 0 {
+			positionId = common.Int64All((*entdata)["position_id"])
+			name = common.ObjToString((*entdata)["name"])
+			return
+		}
+	}
+	sql := `select a.name,a.count from dwd_f_csm_customer_autodraw_record a INNER JOIN dwd_d_crm_department_level_succbi b on b.ent_id=? and  (a.name = b.name)  and  b.resign = 0`
+	countData := TiDb.SelectBySql(sql, db.EntId)
+	if countData != nil && len(*countData) > 0 {
+		for _, v := range *data {
+			//判断是否有新员工
+			isOk := false
+			for _, vv := range *countData {
+				if common.ObjToString(v["name"]) == common.ObjToString(vv["name"]) {
+					isOk = true
+				}
+			}
+			//有新员工直接分给新员工
+			if !isOk {
+				name = common.ObjToString(v["name"])
+				rData := TiDb.FindOne("dwd_f_csm_customer_autodraw_record", map[string]interface{}{}, "", "count desc")
+				TiDb.Insert("dwd_f_csm_customer_autodraw_record", map[string]interface{}{
+					"name":  name,
+					"count": common.Int64All((*rData)["count"]),
+				})
+				break
+			}
+		}
+		res := int64(0)
+		countres := 0
+		for _, v := range *countData {
+			if countres == 0 {
+				res = common.Int64All(v["count"])
+				name = common.ObjToString(v["name"])
+			} else {
+				if common.Int64All(v["count"]) <= res {
+					res = common.Int64All(v["count"])
+					name = common.ObjToString(v["name"])
+				}
+			}
+			countres++
+		}
+	}
+
+	for _, v := range *data {
+
+		if name == common.ObjToString(v["name"]) {
+
+			positionId = common.Int64All(v["position_id"])
 
+		}
+
+	}
+
+	return
+
+}
 func kcAuto() {
 	log.Println("客户成功系统自动进入任务车定时任务开始")
 	nowTime := time.Now().Format(date.Date_Full_Layout)
@@ -612,6 +689,7 @@ func refundAuto() {
 	findNowTime := time.Now().AddDate(0, 0, -db.ExpirationPeriod).Format(date.Date_Full_Layout)
 	nowTime := time.Now().Format(date.Date_Full_Layout)
 	mailData := map[string][]map[string]interface{}{}
+	salesEmailData := map[int64][]map[string]interface{}{}
 	TiDb.SelectByBath(100, func(l *[]map[string]interface{}) bool {
 		for _, v := range *l {
 			saleId, cluename, company_nature, company_verification, uid, phone, userName := int64(0), "", 0, 0, "", "", ""
@@ -636,7 +714,9 @@ func refundAuto() {
 				if orderData != nil && len(*orderData) > 0 {
 					endDate := time.Now().AddDate(0, 0, -db.ExpirationPeriod+1).Unix()
 					startDate := time.Now().AddDate(0, 0, -db.ExpirationPeriod).Unix()
-					vipEndDate, _ := time.Parse(time.DateTime, gconv.String((*orderData)[0]["vip_endtime"]))
+					vipEndDate, _ := time.ParseInLocation(time.DateTime, gconv.String((*orderData)[0]["vip_endtime"]), time.Local)
+					log.Println(vipEndDate.Unix() > startDate, vipEndDate.Unix() < endDate)
+					log.Println(vipEndDate.Unix(), startDate, endDate)
 					if vipEndDate.Unix() > startDate && vipEndDate.Unix() < endDate {
 						//即将到期
 						mailData[name] = append(mailData[name], map[string]interface{}{
@@ -646,6 +726,14 @@ func refundAuto() {
 							"remrk":        "1天后即将移交",
 							"reason":       "成交客户续费失败",
 						})
+						salesEmailData[saleId] = append(salesEmailData[saleId], map[string]interface{}{
+							"company_name": company_name,
+							"phone":        phone,
+							"userName":     userName,
+							"remrk":        "1天后即将移交",
+							"reason":       "成交客户续费失败",
+							"cluename":     cluename,
+						})
 						continue
 					}
 				}
@@ -754,6 +842,15 @@ func refundAuto() {
 									"remrk":        "1天后即将移交",
 									"reason":       "成交客户续费失败",
 								})
+								salesEmailData[saleId] = append(salesEmailData[saleId], map[string]interface{}{
+									"company_name": company_name,
+									"phone":        phone,
+									"userName":     userName,
+									"remrk":        "1天后即将移交",
+									"reason":       "成交客户续费失败",
+									"cluename":     cluename,
+								})
+								isOk = true
 							} else if time.Now().Unix()-vip_endtimes.Unix() < db.HandoverCycle*86400 {
 								isOk = true
 							}
@@ -831,6 +928,16 @@ func refundAuto() {
 								"reason":       "成交客户续费失败",
 							})
 						}
+						if saleId > 0 {
+							salesEmailData[saleId] = append(salesEmailData[saleId], map[string]interface{}{
+								"company_name": company_name,
+								"phone":        phone,
+								"userName":     userName,
+								"remrk":        "已移交",
+								"reason":       "成交客户续费失败",
+								"cluename":     cluename,
+							})
+						}
 						TiDb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
 							"clue_id":      clueId,
 							"position_id":  common.If(kcposition_id > 0, kcposition_id, -1),
@@ -906,15 +1013,429 @@ func refundAuto() {
 		}
 		return true
 	}, `select ent_id,clue_id,position_id,name,is_renewal_protection,company_name from dwd_f_csm_customer_info where is_transfer = 0`)
-	//}, `select ent_id,clue_id,position_id,name,is_renewal_protection,company_name from dwd_f_csm_customer_info where clue_id =1471384`)
+	//}, `select ent_id,clue_id,position_id,name,is_renewal_protection,company_name from dwd_f_csm_customer_info where clue_id =1590274`)
 
 	//移交电销提醒
 	for i, v := range mailData {
 		ExitKcSend(i, v)
 	}
+	//移交电销销售提醒
+	for i, v := range salesEmailData {
+		ExitKcSaleSend(i, v)
+	}
 	log.Println("自动移交销售定时任务结束")
 }
 
+// 查找一部三部人员信息 返回人员信息 以及管理员信息
+func FindDeptAdmin(positionId int64) (map[string]interface{}, map[string]interface{}, map[string]interface{}) {
+	//先判断那个部门的
+	userData1 := TiDb.SelectBySql(`SELECT
+	a.position_id,
+	a.name,
+	b.seat_number,
+	b.role_id,
+	a.bi_pcode,
+	a.dept_name,
+	a.resign
+FROM
+			(SELECT *
+		FROM dwd_d_crm_department_level_succbi u1
+		WHERE id = (
+			SELECT MAX(id)
+			FROM dwd_d_crm_department_level_succbi u2
+			WHERE  u1.position_id = u2.position_id		
+		)
+		ORDER BY id desc) a
+		INNER JOIN (SELECT *
+			FROM dwd_f_crm_personnel_management u1
+			WHERE id = (
+				SELECT MAX(id)
+				FROM dwd_f_crm_personnel_management u2
+				WHERE u1.position_id = u2.position_id		
+			)
+			ORDER BY id desc) b ON  a.dept_name LIKE "%电销部%"
+	AND a.position_id = b.position_id`)
+	userData3 := TiDb.SelectBySql(`SELECT
+	a.position_id,
+	a.name,
+	b.seat_number,
+	b.role_id,
+	a.bi_pcode,
+	a.dept_name,
+	a.resign
+FROM
+			(SELECT *
+		FROM dwd_d_crm_department_level_succbi u1
+		WHERE id = (
+			SELECT MAX(id)
+			FROM dwd_d_crm_department_level_succbi u2
+			WHERE  u1.position_id = u2.position_id		
+		)
+		ORDER BY id desc) a
+			INNER JOIN (SELECT *
+		FROM dwd_f_crm_personnel_management u1
+		WHERE id = (
+			SELECT MAX(id)
+			FROM dwd_f_crm_personnel_management u2
+			WHERE u1.position_id = u2.position_id		
+		)
+		ORDER BY id desc) b ON 
+	a.dept_name LIKE "%销售三部"
+	AND a.position_id = b.position_id`)
+	if userData3 == nil || len(*userData3) == 0 || userData1 == nil || len(*userData1) == 0 {
+		log.Println("找不到一部三部员工信息")
+		return nil, nil, nil
+	}
+	//一部高级管理员信息
+	seniorAdmin1 := map[string]interface{}{}
+	//三部高级管理员信息
+	seniorAdmin3 := map[string]interface{}{}
+	//一部管理员信息
+	admin1 := map[string]map[string]interface{}{}
+
+	//返回当前人信息
+	admin := map[string]interface{}{}
+	for _, v := range *userData3 {
+		v["type"] = 3
+		id := gconv.Int64(v["position_id"])
+		roleId := gconv.Int64(v["role_id"])
+		resign := gconv.Int64(v["resign"])
+		if id == positionId && resign == 0 {
+			admin = v
+		}
+		if roleId == 8 {
+			v["orderStatus"] = 2
+			seniorAdmin3 = v
+		}
+	}
+	for _, v := range *userData1 {
+		v["type"] = 1
+		id := gconv.Int64(v["position_id"])
+		roleId := gconv.Int64(v["role_id"])
+		dept_name := gconv.String(v["dept_name"])
+		resign := gconv.Int64(v["resign"])
+		if id == positionId && resign == 0 {
+			admin = v
+		}
+		if roleId == 8 {
+			v["orderStatus"] = 2
+			seniorAdmin1 = v
+		} else if roleId == 3 {
+			admin1[dept_name] = v
+		}
+	}
+	//查看当前人属于哪个部门
+	if admin == nil {
+		//当前人不属于电销部的
+		admin = *(TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{
+			"position_id": positionId,
+			"resign":      1,
+		}, "name", ""))
+	}
+	positiontype := gconv.Int64(admin["type"])
+	deptName := gconv.String(admin["dept_name"])
+	switch positiontype {
+	case 1:
+		roleId := gconv.Int64(admin["role_id"])
+		if roleId == 3 {
+			return admin, nil, seniorAdmin1
+		}
+		return admin, admin1[deptName], seniorAdmin1
+	case 3:
+		return admin, nil, seniorAdmin3
+	default:
+		return admin, nil, nil
+	}
+}
+
+// 邮箱获取
+func GetMail(personName string) (string, string) {
+	data := Mysql.SelectBySql(`select  name,mail,img from   entniche_user  where  ent_id =?`, db.EntId)
+	if data == nil || len(*data) == 0 {
+		return "", ""
+	}
+	for _, m := range *data {
+		name := gconv.String(m["name"])
+		if name == personName {
+			//
+			return gconv.String(m["mail"]), gconv.String(m["img"])
+		}
+	}
+	return "", ""
+}
+
+// 退客成进销售 销售收邮件
+func ExitKcSaleSend(positionId int64, infoList []map[string]interface{}) {
+	person, admin, seniorAdmin := FindDeptAdmin(positionId)
+	personMail := ""
+	adminMail := ""
+	seniorAdminMail := ""
+	if person != nil {
+		personMail, _ = GetMail(gconv.String(person["name"]))
+	}
+	if admin != nil {
+		adminMail, _ = GetMail(gconv.String(admin["name"]))
+	}
+	if seniorAdmin != nil {
+		seniorAdminMail, _ = GetMail(gconv.String(seniorAdmin["name"]))
+	}
+	//退出客成 即将退出客成信息  销售信息编辑
+	gmail := &mail.GmailAuth{
+		SmtpHost: db.Mail.SmtpHost,
+		SmtpPort: db.Mail.SmtpPort,
+		User:     db.Mail.User,
+		Pwd:      db.Mail.Pwd,
+	}
+	//正文拼接
+	startStr := `<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, initial-scale=1.0">
+	<style>table{width:100%;border-collapse:collapse}th,td{border:1px solid#000;padding:8px;text-align:left}th{background-color:#f2f2f2}</style></head>
+	<body><p>以下客户已从或即将从客成系统退出,并移交销售跟进,请收悉,客户明细如下:</p>
+	<table><thead><tr><th>序号</th><th>线索名称</th><th>联系人</th><th>姓名</th><th>移交状态</th></tr></thead><tbody>`
+	for i, v := range infoList {
+		startStr += fmt.Sprintf(`<tr><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>`, i+1, gconv.String(v["cluename"]), gconv.String(v["phone"]), gconv.String(v["userName"]), gconv.String(v["remrk"]))
+	}
+	endStr := `</tbody></table><p></body></html>`
+	startStr += endStr
+	to := ""
+	cc := ""
+	if personMail != "" {
+		to = personMail
+		if adminMail != "" && seniorAdminMail != "" {
+			if adminMail != seniorAdminMail {
+				cc = fmt.Sprintf("%s,%s", adminMail, seniorAdminMail)
+			} else {
+				cc = adminMail
+			}
+		} else if adminMail != "" {
+			cc = adminMail
+		} else if seniorAdminMail != "" {
+			cc = seniorAdminMail
+		}
+	} else {
+		if adminMail != "" {
+			to = adminMail
+			if seniorAdminMail != "" {
+				cc = seniorAdminMail
+			}
+		} else {
+			cc = seniorAdminMail
+
+		}
+	}
+	if to != "" {
+		if cc != "" {
+			to = fmt.Sprintf("%s|%s", to, cc)
+		}
+		status := mail.GSendMail_q("剑鱼标讯", to, "", "", "成交客户续费失败移交销售通知", startStr, "", "", gmail)
+		if status {
+			log.Println("客成发邮件 send mail success", startStr, to, cc)
+		}
+	}
+}
+
+// 客成人员变更发邮件
+func CustomerChange() {
+	personMap := map[int64]string{}
+	personData := TiDb.SelectBySql(`select  name,position_id  from  dwd_d_crm_department_level_succbi where  ent_id=? and  resign=0   and  position_id>0`, db.EntId)
+	if personData != nil && len(*personData) > 0 {
+		for _, v := range *personData {
+			personMap[gconv.Int64(v["position_id"])] = gconv.String(v["name"])
+		}
+	}
+	startTime := cfg.LastKcChangeTime
+	if startTime == "" {
+		startTime = time.Now().Format(time.DateTime)
+	}
+	customMap1 := map[string][]map[string]interface{}{}
+	customMap2 := map[string][]map[string]interface{}{}
+	saleMap := map[int64][]map[string]interface{}{}
+	saleNobodyCustomMapMap := map[int64][]map[string]interface{}{}
+	TiDb.SelectByBath(100, func(l *[]map[string]interface{}) bool {
+		for _, v := range *l {
+			startTime = gconv.String(v["createtime"])
+			data := CustomerChangeHandle(v)
+			oldPerson := gconv.String(data["oldPerson"])
+			newPerson := gconv.String(data["newPerson"])
+			positionId := gconv.Int64(data["positionId"])
+			operatorId := gconv.Int64(data["operatorId"])
+			if oldPerson == "/" {
+				data["oldPerson"] = "-"
+			}
+			if positionId > 0 {
+				data["positionName"] = personMap[positionId]
+			}
+			if operatorId > 0 {
+				data["operatorName"] = personMap[operatorId]
+			}
+			if (oldPerson == "" || oldPerson == "/") && newPerson != "" && newPerson != "/" && positionId > 0 {
+				//之前没有可成人员
+				saleNobodyCustomMapMap[positionId] = append(saleNobodyCustomMapMap[positionId], data)
+
+			} else if newPerson != "" && newPerson != "/" && oldPerson != "" && oldPerson != "/" && positionId > 0 {
+				//之前有客成
+				saleMap[positionId] = append(saleMap[positionId], data)
+			}
+			if newPerson != "" && newPerson != "/" {
+				customMap2[newPerson] = append(customMap2[newPerson], data)
+			}
+			if oldPerson != "" && oldPerson != "/" {
+				customMap1[oldPerson] = append(customMap1[oldPerson], data)
+			}
+		}
+		return true
+	}, `select operator_id, clue_id,position_id,old_value,new_value,createtime from   dwd_f_crm_clue_change_record  where    createtime>?  and change_type="客户成功经理"  and  operator_id>0  order by  createtime`, startTime)
+	if len(customMap1) > 0 {
+		ChangeSendKc(customMap1, 1)
+	}
+	if len(customMap2) > 0 {
+		ChangeSendKc(customMap2, 2)
+	}
+	if len(saleMap) > 0 {
+		ChangeSendSale(saleMap, 2)
+	}
+	if len(saleNobodyCustomMapMap) > 0 {
+		ChangeSendSale(saleNobodyCustomMapMap, 1)
+	}
+	log.Println("11111", startTime)
+	cfg.LastKcChangeTime = startTime
+	common.WriteSysConfig(&cfg)
+}
+
+// 客户成功经理变更邮件提醒客成人员
+func ChangeSendKc(data map[string][]map[string]interface{}, personType int64) {
+	for name, v := range data {
+		to, _ := GetMail(name)
+		//正文拼接
+		startStr := `<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, initial-scale=1.0"><style>table{width:100%;border-collapse:collapse}th,td{border:1px solid#000;padding:8px;text-align:left}th{background-color:#f2f2f2}</style></head><body><p></p>
+		<table><thead><tr><th>序号</th><th>公司名称</th><th>联系人</th><th>姓名</th><th>变更前客户经理</th><th>变更后客户经理</th><th>操作人</th></tr></thead><tbody>`
+		for i, v := range v {
+			startStr += fmt.Sprintf(`<tr><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>`, i+1, gconv.String(v["companyName"]), gconv.String(v["phone"]), gconv.String(v["userName"]), gconv.String(v["oldPerson"]), gconv.String(v["newPerson"]), gconv.String(v["operatorName"]))
+		}
+		endStr := `</tbody></table><p></body></html>`
+		startStr += endStr
+		if to != "" {
+			status := mail.GSendMail_q("剑鱼标讯", to, "", "", gconv.String(common.If(personType == 2, "您有新的客户,请及时跟进处理", "您的客户已转至其他客户成功经理负责")), startStr, "", "", &Gmail)
+			if status {
+				log.Println("客成发邮件 send mail success", startStr, to, "")
+			}
+		}
+	}
+}
+
+func ChangeSendSale(data map[int64][]map[string]interface{}, personType int64) {
+	if personType == 1 {
+		//客户成功经理从空变成有人
+		for _, v := range data {
+			for _, v1 := range v {
+				_, img := GetMail(gconv.String(v1["newPerson"]))
+				to, _ := GetMail(gconv.String(v1["positionName"]))
+				startStr := `<style> *,body,html{margin:10px;font-family:tahoma,arial,'Hiragino Sans GB','Microsoft YaHei',宋体,ans-serif;font-size:16px;}p{margin:15px;font-size:18px;}table{background-color: rgb(244, 244, 249);padding:5px 15px;border:solid 1px #ddd;margin: 20px 0px 20px 50px;vertical-align:top;display:inline-block;}.tit{width:120px;}td{padding: 5px;}.clear{clear: both;}</style>
+				<p>销售人员"%s"成交的客户已成功移交至客成,线索名称:%s,姓名:%s,手机号:%s,负责客户成功经理:%s</p>
+				<p>请引导客户添加客户成功经理企业微信:</p><div class='clear'>%s</div>`
+				endStr := fmt.Sprintf(startStr, gconv.String(v1["positionName"]), gconv.String(v1["clueName"]), gconv.String(v1["userName"]), gconv.String(v1["phone"]), gconv.String(v1["newPerson"]), common.If(img != "", fmt.Sprintf(`<img width="300" height="450" src="%s">`, img), ""))
+				if to != "" {
+					status := mail.GSendMail_q("剑鱼标讯", to, "", "", "成交客户已成功移交客成", endStr, "", "", &Gmail)
+					if status {
+						log.Println("客成发邮件 send mail success", endStr, to, "")
+					}
+				}
+			}
+		}
+		return
+	}
+	//客户成功经理从A变成了B
+	for positionId, v := range data {
+		person, admin, seniorAdmin := FindDeptAdmin(positionId)
+		personMail := ""
+		adminMail := ""
+		seniorAdminMail := ""
+		if person != nil {
+			personMail, _ = GetMail(gconv.String(person["name"]))
+		}
+		if admin != nil {
+			adminMail, _ = GetMail(gconv.String(admin["name"]))
+		}
+		if seniorAdmin != nil {
+			seniorAdminMail, _ = GetMail(gconv.String(seniorAdmin["name"]))
+		}
+		to := ""
+		cc := ""
+		if personMail != "" {
+			to = personMail
+			if adminMail != "" && seniorAdminMail != "" {
+				cc = adminMail
+			} else if seniorAdminMail != "" {
+				cc = seniorAdminMail
+			}
+		} else {
+			if adminMail != "" {
+				to = adminMail
+				if seniorAdminMail != "" {
+					cc = seniorAdminMail
+				}
+			} else {
+				cc = seniorAdminMail
+
+			}
+		}
+		//正文拼接
+		startStr := `<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, initial-scale=1.0"><style>table{width:100%;border-collapse:collapse}th,td{border:1px solid#000;padding:8px;text-align:left}th{background-color:#f2f2f2}</style></head><body><p>客户明细如下:
+		</p><table><thead><tr><th>序号</th><th>线索名称</th><th>联系人</th><th>姓名</th><th>变更前客户经理</th><th>变更后客户经理</th><th>销售人员</th></tr></thead><tbody>`
+		for i, v := range v {
+			startStr += fmt.Sprintf(`<tr><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>`,
+				i+1, gconv.String(v["clueName"]), gconv.String(v["phone"]), gconv.String(v["userName"]), gconv.String(v["oldPerson"]), gconv.String(v["newPerson"]), gconv.String(v["positionName"]))
+		}
+		endStr := `</tbody></table><p></body></html>`
+		startStr += endStr
+		if to != "" {
+			if cc != "" {
+				to = fmt.Sprintf("%s|%s", to, cc)
+			}
+			status := mail.GSendMail_q("剑鱼标讯", to, "", "", "成交客户负责客户成功经理变更", startStr, "", "", &Gmail)
+			if status {
+				log.Println("客成发邮件 send mail success", startStr, to, "")
+			}
+		}
+	}
+}
+
+// 客成人员变更基本信息获取
+func CustomerChangeHandle(data map[string]interface{}) map[string]interface{} {
+	clueId := gconv.Int64(data["clue_id"])
+	oldPerson := gconv.String(data["old_value"])
+	newPerson := gconv.String(data["new_value"])
+	operatorId := gconv.Int64(data["operator_id"])
+	companyName := ""
+	phone := ""
+	userName := ""
+	clueName := ""
+	clueData := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{
+		"id": clueId,
+	}, "", "")
+	if clueData == nil || len(*clueData) == 0 {
+		return nil
+	}
+	phone = common.ObjToString((*clueData)["phone"])
+	userName = gconv.String((*clueData)["name"])
+	positionId := gconv.Int64((*clueData)["position_id"])
+	clueName = gconv.String((*clueData)["cluename"])
+	customData := TiDb.FindOne("dwd_f_csm_customer_info", map[string]interface{}{
+		"clue_id": clueId,
+	}, "", "")
+	if customData != nil || len(*customData) != 0 {
+		companyName = gconv.String((*customData)["company_name"])
+	}
+	return map[string]interface{}{
+		"oldPerson":   oldPerson,
+		"newPerson":   newPerson,
+		"operatorId":  operatorId,
+		"phone":       phone,
+		"userName":    userName,
+		"positionId":  positionId,
+		"clueName":    clueName,
+		"companyName": companyName,
+	}
+}
 func refundAutoHistory() {
 	data := TiDb.Find("dwd_f_crm_clue_autodraw_record", nil, "", "", -1, -1)
 	if data != nil {
@@ -1178,6 +1699,9 @@ func KcSend(orderCode, personName string) {
 		if deptData != nil && len(*deptData) > 0 {
 			mailStr := gconv.String((*deptData)[0]["mail"])
 			if mailStr != "" || adminMailStr != "" {
+				if mailStr == adminMailStr {
+					adminMailStr = ""
+				}
 				gmail := &mail.GmailAuth{
 					SmtpHost: db.Mail.SmtpHost,
 					SmtpPort: db.Mail.SmtpPort,
@@ -1235,6 +1759,9 @@ func ExitKcSend(personName string, infoList []map[string]interface{}) {
 			adminMailStr = gconv.String((*adminData)[0]["mail"])
 		}
 		if mailStr != "" || adminMailStr != "" {
+			if mailStr == adminMailStr {
+				adminMailStr = ""
+			}
 			gmail := &mail.GmailAuth{
 				SmtpHost: db.Mail.SmtpHost,
 				SmtpPort: db.Mail.SmtpPort,
@@ -1260,6 +1787,8 @@ func ExitKcSend(personName string, infoList []map[string]interface{}) {
 		}
 	}
 }
+
+// 客成邮件   订单信息初始化
 func KcOrderFormat(orderCode string, bigmemberService, combo map[int64]string) *OrderInfo {
 	orderData := Mysql.SelectBySql(`SELECT a.id,a.order_code,a.pay_money,a.user_phone,a.vip_starttime,a.vip_endtime,a.product_type,a.filter,a.user_id,a.ent_id,a.company_name,a.create_person,SUM(b.return_money) AS return_money 
 		FROM jianyu.dataexport_order a

+ 9 - 0
clueSync/main.go

@@ -3,6 +3,7 @@ package main
 import (
 	"app.yhyue.com/moapp/jybase/common"
 	elastic "app.yhyue.com/moapp/jybase/es"
+	"app.yhyue.com/moapp/jybase/mail"
 	"app.yhyue.com/moapp/jybase/mongodb"
 	"app.yhyue.com/moapp/jybase/mysql"
 	"app.yhyue.com/moapp/jybase/redis"
@@ -33,6 +34,7 @@ var (
 	MgoQyxy             *mongodb.MongodbSim
 	mode                = flag.Int("m", 1, "")
 	startTime, endTime  = "00:00", "23:59"
+	Gmail               mail.GmailAuth
 )
 
 func main() {
@@ -41,6 +43,12 @@ func main() {
 	log.Println("cfg ", cfg)
 	common.ReadConfig("./db.json", &db)
 	log.Println("db ", db)
+	Gmail = mail.GmailAuth{
+		SmtpHost: db.Mail.SmtpHost,
+		SmtpPort: db.Mail.SmtpPort,
+		User:     db.Mail.User,
+		Pwd:      db.Mail.Pwd,
+	}
 	TiDb = &mysql.Mysql{
 		Address:      db.TiDb.Host + ":" + fmt.Sprint(db.TiDb.Port),
 		UserName:     db.TiDb.User,
@@ -198,6 +206,7 @@ func main() {
 			autoExitSea()      //自动退海
 			Thaw()             //自动解冻处理
 			subscribeAddSync() //订阅增量
+			CustomerChange()
 		})
 		//5分钟一次
 		go p.VarTimeTask.RunInTimeLoop("5分钟定时任务3", "", "", db.CornExp6, true, true, nil, func() {