package service import ( "database/sql" "fmt" "log" "math" "regexp" "sync" "time" "app.yhyue.com/moapp/jybase/date" common "app.yhyue.com/moapp/jybase/common" . "bp.jydev.jianyu360.cn/BaseService/biService/entity" "bp.jydev.jianyu360.cn/BaseService/biService/rpc/biservice" ) func DistributeClue(this *biservice.DistributeClueReq) *biservice.AddProjectResp { count, status := DistributeClueSync(this) log.Println("分配数量 ", count) return &biservice.AddProjectResp{ ErrorCode: 0, Data: &biservice.AddProject{ Status: int64(status), Count: int64(count), }, } } func DistributeClueSync(this *biservice.DistributeClueReq) (int, int) { if DistributeLock.TryLock() { defer DistributeLock.Unlock() saleMap, count := map[string]map[string]interface{}{}, 0 saleData := JyBiTidb.SelectBySql("select * from jy_salesperson_info where is_complete = 1 or is_complete = 0") if saleData != nil && len(*saleData) > 0 { for _, v := range *saleData { name := common.ObjToString(v["name"]) saleMap[name] = v } } for _, data := range this.Datas { seatNumber := common.ObjToString(saleMap[data.Name]["seatNumber"]) distributedCount := int(data.DistributedCount) if distributedCount > 0 { distributedArr := this.ClueIdList[count : count+distributedCount] count += distributedCount DistributeClueMore(saleMap, distributedArr, seatNumber, data.Name, data.PositionId, this.PositionId, this.IsTask) } } return count, 1 } else { return 0, 2 } } func DistributeClueMore(saleMap map[string]map[string]interface{}, distributedArr []int64, seatNumber, name string, positionId, thispositionId, isTask int64) { wg := new(sync.WaitGroup) ch := make(chan bool, 20) for _, v := range distributedArr { wg.Add(1) ch <- true go func(v int64) { defer func() { wg.Done() <-ch }() clueData := JyBiTidb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"id": v}, "", "") nowTime := time.Now().Format(date.Date_Full_Layout) if clueData != nil && len(*clueData) > 0 { isAssign := common.IntAll((*clueData)["is_assign"]) clueSeatNumber := common.ObjToString((*clueData)["seatNumber"]) oldName := "" trailstatus := common.ObjToString((*clueData)["trailstatus"]) if clueSeatNumber != "" { for _, s := range saleMap { if common.ObjToString(s["seatNumber"]) == clueSeatNumber { oldName = common.ObjToString(s["name"]) } } } if isAssign == 1 { oldpositionId := common.Int64All((*clueData)["position_id"]) updateClue := map[string]interface{}{ "position_id": positionId, "seatNumber": seatNumber, "is_assign": 1, "updatetime": nowTime, "comeintime": nowTime, "comeinsource_private": 4, "level_open": nil, "clue_level": nil, "out_task_time": nil, "out_task_status": nil, "trail_time": nil, // "comeinsource_open": nil, } if isTask == int64(1) { updateClue["is_task"] = 1 updateClue["task_time"] = nowTime updateClue["tasktime"] = nowTime updateClue["taskstatus"] = 0 updateClue["tasksource"] = "主动分配客户" } ok := JyBiTidb.Update("dwd_f_crm_clue_info", map[string]interface{}{"id": v}, updateClue) // ok := JyBiTidb.Update("dwd_f_crm_private_sea", map[string]interface{}{"clue_id": v}, map[string]interface{}{ // "position_id": positionId, // "seatNumber": seatNumber, // "comeinsource": 4, // "comeintime": nowTime, // }) if ok { JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": v, "position_id": positionId, "change_field": "position_id", "change_type": "所属人变更", "old_value": oldName, "new_value": name, "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": thispositionId, }) JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": v, "position_id": oldpositionId, "change_field": "trailstatus", "change_type": "基本信息变更", "old_value": CodeTrail[trailstatus], "new_value": "流失", "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": thispositionId, }) JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": v, "position_id": positionId, "change_field": "trailstatus", "change_type": "基本信息变更", "old_value": CodeTrail[trailstatus], "new_value": "新增", "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": thispositionId, }) } else { log.Println("私海修改失败 ", v, positionId, seatNumber) } } else { updateClue := map[string]interface{}{ "position_id": positionId, "seatNumber": seatNumber, "is_assign": 1, "updatetime": nowTime, "comeintime": nowTime, "comeinsource_private": 4, "is_task": 0, "taskstatus": 0, "level_open": nil, "clue_level": nil, "out_task_time": nil, "out_task_status": nil, "trail_time": nil, "next_trail_time": nil, // "comeinsource_open": nil, } if trailstatus != "08" { updateClue["trailstatus"] = "01" } if isTask == int64(1) { updateClue["is_task"] = 1 updateClue["task_time"] = nowTime updateClue["tasktime"] = nowTime updateClue["taskstatus"] = 0 updateClue["tasksource"] = "主动分配客户" } ok := JyBiTidb.Update("dwd_f_crm_clue_info", map[string]interface{}{"id": v}, updateClue) // seaId := JyBiTidb.Insert("dwd_f_crm_private_sea", map[string]interface{}{ // "clue_id": v, // "position_id": positionId, // "seatNumber": seatNumber, // "comeinsource": 4, // "comeintime": nowTime, // "is_task": 0, // // "task_time": nowTime, // // "tasktime": nowTime, // "taskstatus": 0, // // "tasksource": "线索批量分配", // }) if ok { // JyBiTidb.Delete("dwd_f_crm_open_sea", map[string]interface{}{"clue_id": v}) JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": v, "position_id": positionId, "change_field": "position_id", "change_type": "所属人变更", "old_value": "/", "new_value": name, "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": thispositionId, }) if trailstatus != "08" { JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": v, "position_id": positionId, "change_field": "trailstatus", "change_type": "基本信息变更", "old_value": "商机线索", "new_value": "新增", "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": thispositionId, }) JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": v, "position_id": positionId, "change_field": "trailstatus", "change_type": "基本信息变更", "old_value": CodeTrail[trailstatus], "new_value": "商机线索", "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": thispositionId, }) } } else { log.Println("私海插入失败 ", v, positionId, seatNumber) } } } }(v) } wg.Wait() } func DrawClue(this *biservice.DrawClueReq) *biservice.AddProjectResp { count, status := DrawClueSync(this) log.Println("领取数量 ", count) return &biservice.AddProjectResp{ ErrorCode: 0, Data: &biservice.AddProject{ Status: int64(status), Count: int64(count), }, } } func DrawClueSync(this *biservice.DrawClueReq) (int, int) { if DataLock.TryLock() { defer DataLock.Unlock() count1 := JyBiTidb.Count("dwd_f_crm_clue_info", map[string]interface{}{"level_open": 1, "is_assign": 0}) count2 := JyBiTidb.Count("dwd_f_crm_clue_info", map[string]interface{}{"level_open": 2, "is_assign": 0}) counts1, counts2, counts3 := int64(0), int64(0), int64(0) counts1 = int64(math.Ceil(float64(this.Count) / float64(10) * 5)) if this.Count-counts1 == 0 { counts2 = 0 counts3 = 0 } else { counts2 = int64(math.Ceil(float64(this.Count) / float64(10) * 4)) if this.Count-counts1-counts2 == 0 { counts3 = 0 } else { counts3 = this.Count - counts1 - counts2 } } if counts1 > count1 { counts2 += counts1 - count1 counts1 = count1 } if counts2 > count2 { counts3 += counts2 - count2 counts2 = count2 } log.Println(count1, count2) log.Println(counts1, counts2, counts3) return DrawClues(this.PositionId, counts1, counts2, counts3), 1 } else { return 0, 2 } } func DrawClues(positionId, count1, count2, count3 int64) int { data1, data2, data3, drawCount := &[]map[string]interface{}{}, &[]map[string]interface{}{}, &[]map[string]interface{}{}, 0 if count1 > 0 { // data1 = JyBiTidb.Find("dwd_f_crm_clue_info", map[string]interface{}{"level_open": 1, "is_assign": 0}, "", "", 0, int(count1)) data1 = JyBiTidb.SelectBySql(`SELECT max(c.createTime) as ctime,a.id,a.trailstatus FROM dwd_f_crm_clue_info a LEFT JOIN Call_Accounting.voice_record c ON c.CalledNo = a.phone WHERE a.level_open = ? AND a.is_assign = 0 AND a.uid !="" GROUP BY a.id ORDER BY ctime asc limit ?`, 1, count1) } if count2 > 0 { // data2 = JyBiTidb.Find("dwd_f_crm_clue_info", map[string]interface{}{"level_open": 2, "is_assign": 0}, "", "", 0, int(count2)) data2 = JyBiTidb.SelectBySql(`SELECT max(c.createTime) as ctime,a.id,a.trailstatus FROM dwd_f_crm_clue_info a LEFT JOIN Call_Accounting.voice_record c ON c.CalledNo = a.phone WHERE a.level_open = ? AND a.is_assign = 0 AND a.uid !="" GROUP BY a.id ORDER BY ctime asc limit ?`, 2, count2) } if count3 > 0 { // data3 = JyBiTidb.Find("dwd_f_crm_clue_info", map[string]interface{}{"level_open": 3, "is_assign": 0}, "", "", 0, int(count3)) data3 = JyBiTidb.SelectBySql(`SELECT max(c.createTime) as ctime,a.id,a.trailstatus FROM dwd_f_crm_clue_info a LEFT JOIN Call_Accounting.voice_record c ON c.CalledNo = a.phone WHERE a.level_open = ? AND a.is_assign = 0 AND a.uid !="" GROUP BY a.id ORDER BY ctime asc limit ?`, 3, count3) } nowTime := time.Now().Format("2006-01-02 15:04:05") seatNumber, name := getSeatNumber(positionId) if data1 != nil && len(*data1) > 0 { batchDraw(*data1, nowTime, seatNumber, name, positionId) drawCount += len(*data1) } if data2 != nil && len(*data2) > 0 { batchDraw(*data2, nowTime, seatNumber, name, positionId) drawCount += len(*data2) } if data3 != nil && len(*data3) > 0 { batchDraw(*data3, nowTime, seatNumber, name, positionId) drawCount += len(*data3) } return drawCount } func batchDraw(data []map[string]interface{}, nowTime, seatNumber, name string, positionId int64) { wg := new(sync.WaitGroup) ch := make(chan bool, 20) for _, v := range data { wg.Add(1) ch <- true go func(v map[string]interface{}) { defer func() { wg.Done() <-ch }() clueId := common.Int64All(v["id"]) trailstatus := common.ObjToString(v["trailstatus"]) if JyBiMysql.ExecTx("领取线索等", func(tx *sql.Tx) bool { updateClue := map[string]interface{}{ "position_id": positionId, "seatNumber": seatNumber, "is_assign": 1, "updatetime": nowTime, "comeintime": nowTime, "comeinsource_private": 3, "is_task": 1, "task_time": nowTime, "tasktime": nowTime, "taskstatus": 0, "tasksource": "领取公海线索", "level_open": nil, "clue_level": nil, // "comeinsource_open": nil, } if trailstatus != "08" { updateClue["trailstatus"] = "01" } ok1 := JyBiTidb.UpdateByTx(tx, "dwd_f_crm_clue_info", map[string]interface{}{"id": clueId}, updateClue) // ok2 := JyBiTidb.DeleteByTx(tx, "dwd_f_crm_open_sea", map[string]interface{}{"clue_id": clueId}) // seaId := JyBiTidb.InsertByTx(tx, "dwd_f_crm_private_sea", map[string]interface{}{ // "clue_id": clueId, // "seatNumber": seatNumber, // "position_id": positionId, // "comeintime": nowTime, // "comeinsource": 3, // "is_task": 1, // "task_time": nowTime, // "tasktime": nowTime, // "taskstatus": 0, // "tasksource": "领取公海线索", // }) recordId := JyBiTidb.InsertByTx(tx, "dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": positionId, "change_field": "position_id", "change_type": "所属人变更", "old_value": "/", "new_value": name, "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": positionId, }) recordId1 := JyBiTidb.InsertByTx(tx, "dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": positionId, "change_type": "领取公海线索", "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": positionId, }) recordId2 := JyBiTidb.InsertByTx(tx, "dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": positionId, "change_type": "加入任务车", "new_value": "领取公海线索", "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": positionId, }) recordId3, recordId4 := int64(0), int64(0) if trailstatus != "08" { recordId3 = JyBiTidb.InsertByTx(tx, "dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": positionId, "change_field": "trailstatus", "change_type": "基本信息变更", "old_value": "商机线索", "new_value": "新增", "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": positionId, }) recordId4 = JyBiTidb.InsertByTx(tx, "dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": positionId, "change_field": "trailstatus", "change_type": "基本信息变更", "old_value": CodeTrail[trailstatus], "new_value": "商机线索", "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": positionId, }) } return ok1 && recordId > 0 && recordId1 > 0 && recordId2 > 0 && recordId3 > -1 && recordId4 > -1 }) { log.Println("领取线索成功") } else { log.Println("领取线索失败") } }(v) } wg.Wait() } func getSeatNumber(positionId int64) (seatNumber, name string) { positionData := JyTidb.FindOne("base_position", map[string]interface{}{"id": positionId}, "", "") if positionData != nil && len(*positionData) > 0 { userId := common.Int64All((*positionData)["user_id"]) if userId > 0 { userData, ok := Mgo.FindOne("user", map[string]interface{}{"base_user_id": userId}) if ok && userData != nil && len(*userData) > 0 { s_phone := common.ObjToString((*userData)["s_phone"]) if s_phone == "" { s_phone = common.ObjToString((*userData)["s_m_phone"]) } saleData := JyBiTidb.FindOne("jy_salesperson_info", map[string]interface{}{"phone": s_phone}, "", "") if saleData != nil && len(*saleData) > 0 { seatNumber = common.ObjToString((*saleData)["seatNumber"]) name = common.ObjToString((*saleData)["name"]) } } } } return } func ClueImport(this *biservice.ClueImportReq) *biservice.ClueImportResp { result, status := ClueImportSync(this) return &biservice.ClueImportResp{ ErrorCode: 0, Data: &biservice.ClueImport{ Status: int64(status), Result: result, }, } } func ClueImportSync(this *biservice.ClueImportReq) (string, int) { if ClueImportLock.TryLock() { defer ClueImportLock.Unlock() result, status, dataArr, countOpen, countAdd, countPrivate := "", 1, []map[string]interface{}{}, 0, 0, 0 phoneRegexp := regexp.MustCompile(`^1[0-9]{10}$`) data := JyBiTidb.Find("dwd_f_crm_bulk_import", map[string]interface{}{"PCBH": this.Pcbh}, "", "", -1, -1) if data != nil && len(*data) > 0 { for k, v := range *data { companyName := common.ObjToString(v["GSMC"]) name := common.ObjToString(v["XM"]) position := common.ObjToString(v["ZW"]) phone := common.ObjToString(v["LXFS"]) clueSource := common.ObjToString(v["XSXSLY"]) if companyName == "" { companyName = phone } isOK, dataMap := false, map[string]interface{}{ "cluename": companyName, "name": name, "phone": phone, "position": position, } if phone == "" { result += "第" + fmt.Sprint(k+2) + "行,“联系方式为空”\n" } else { if !phoneRegexp.MatchString(phone) { result += "第" + fmt.Sprint(k+2) + "行,“联系方式格式有误”\n" } else { userData := JyBiTidb.FindOne("dwd_f_userbase_baseinfo", map[string]interface{}{"phone": phone}, "", "") if userData != nil && len(*userData) > 0 { source := common.IntAll((*userData)["source"]) userId := common.ObjToString((*userData)["userid"]) uId := common.ObjToString((*userData)["uid"]) if source == 5 { result += "第" + fmt.Sprint(k+2) + "行,“该线索已归属域外”\n" } else { isOK = true dataMap["userId"] = userId dataMap["uId"] = uId } } } } if clueSource == "" { result += "第" + fmt.Sprint(k+2) + "行,“销售线索来源为空”\n" } else { sourceData := JyBiTidb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"name": clueSource}, "", "") if sourceData == nil || len(*sourceData) == 0 { result += "第" + fmt.Sprint(k+2) + "行,“销售线索来源不存在”\n" } else { isOK = true code := common.ObjToString((*sourceData)["code"]) pcode := common.ObjToString((*sourceData)["pcode"]) dataMap["top_cluetype"] = pcode dataMap["sub_cluetype"] = code } } if isOK { dataArr = append(dataArr, dataMap) } } nowTime := time.Now().Format(date.Date_Full_Layout) if result != "" { status = -1 JyBiTidb.Update("dwd_f_crm_bulk_import_record", map[string]interface{}{"PCBH": this.Pcbh}, map[string]interface{}{ "DRJSSJ": nowTime, //结束时间 "SBYY": result, //失败原因 "DRZT": "导入失败", }) } else { for _, v := range dataArr { phone := common.ObjToString(v["phone"]) cluename := common.ObjToString(v["cluename"]) name := common.ObjToString(v["name"]) position := common.ObjToString(v["position"]) clueData := JyBiTidb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"phone": phone}, "", "") if clueData == nil || len(*clueData) == 0 { countAdd++ clueId := JyBiTidb.Insert("dwd_f_crm_clue_info", map[string]interface{}{ "userid": v["userId"], "uid": v["uId"], "is_assign": 0, "comeintime": nowTime, "createtime": nowTime, "updatetime": nowTime, "cluename": cluename, "top_cluetype": v["top_cluetype"], "sub_cluetype": v["sub_cluetype"], "trailstatus": "01", "name": name, "phone": phone, "position": position, "batch_import": this.Pcbh, }) JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": -1, "change_type": "创建线索", "new_value": "线索导入创建", "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": this.PositionId, }) if JyBiTidb.Count("dwd_f_userbase_contacts", map[string]interface{}{"phone": phone}) == 0 { JyBiTidb.Insert("dwd_f_userbase_contacts", map[string]interface{}{ "status": 1, "is_delete": 1, "createtime": nowTime, "updatetime": nowTime, "phone": phone, "baseinfo_id": v["uId"], }) } } else { is_assign := common.IntAll((*clueData)["is_assign"]) clueId := common.Int64All((*clueData)["id"]) batch_import := common.ObjToString((*clueData)["batch_import"]) old_cluename := common.ObjToString((*clueData)["cluename"]) old_name := common.ObjToString((*clueData)["name"]) old_position := common.ObjToString((*clueData)["position"]) positionId := common.ObjToString((*clueData)["position_id"]) batch_imports := "" if is_assign == 0 { countOpen++ if batch_import != "" { batch_imports = batch_import + "," + this.Pcbh } else { batch_imports = this.Pcbh } updateData := map[string]interface{}{ "batch_import": batch_imports, "updatetime": nowTime, "top_cluetype": v["top_cluetype"], "sub_cluetype": v["sub_cluetype"], } if cluename != "" && cluename != old_cluename { updateData["cluename"] = cluename JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": -1, "change_field": "cluename", "change_type": "基本信息变更", "old_value": old_cluename, "new_value": cluename, "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": this.PositionId, }) } if name != "" && name != old_name { updateData["name"] = name JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": -1, "change_field": "name", "change_type": "基本信息变更", "old_value": old_name, "new_value": name, "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": this.PositionId, }) } if position != "" && position != old_position { updateData["position"] = position JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": -1, "change_field": "position", "change_type": "基本信息变更", "old_value": old_position, "new_value": position, "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": this.PositionId, }) } JyBiTidb.Update("dwd_f_crm_clue_info", map[string]interface{}{"id": clueId}, updateData) } else if is_assign == 1 { countPrivate++ updateData := map[string]interface{}{ "batch_import": batch_imports, "updatetime": nowTime, "top_cluetype": v["top_cluetype"], "sub_cluetype": v["sub_cluetype"], } updateData["is_task"] = 1 updateData["task_time"] = nowTime updateData["tasktime"] = nowTime updateData["taskstatus"] = 0 updateData["tasksource"] = "线索来源更新客户" if cluename != "" && cluename != old_cluename { updateData["cluename"] = cluename JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": positionId, "change_field": "cluename", "change_type": "基本信息变更", "old_value": old_cluename, "new_value": cluename, "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": this.PositionId, }) } if name != "" && name != old_name { updateData["name"] = name JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": positionId, "change_field": "name", "change_type": "基本信息变更", "old_value": old_name, "new_value": name, "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": this.PositionId, }) } if position != "" && position != old_position { updateData["position"] = position JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": positionId, "change_field": "position", "change_type": "基本信息变更", "old_value": old_position, "new_value": position, "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": this.PositionId, }) } JyBiTidb.Update("dwd_f_crm_clue_info", map[string]interface{}{"id": clueId}, updateData) JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{ "clue_id": clueId, "position_id": positionId, "change_type": "加入任务车", "new_value": "线索来源更新客户", "createtime": nowTime, "BCPCID": common.GetRandom(32), "operator_id": this.PositionId, }) } } } JyBiTidb.Update("dwd_f_crm_bulk_import_record", map[string]interface{}{"PCBH": this.Pcbh}, map[string]interface{}{ "DRJSSJ": nowTime, //结束时间 "ZJXST": len(dataArr), //总计线索条数 "ZFXSSHXST": countPrivate, //私海重复条数 "ZFXSGHXST": countOpen, //公海重复条数 "XZXST": countAdd, //新增条数 "DRZT": "导入成功", }) } } return result, status } else { return "有正在进行的导入任务", 2 } }