Browse Source

Merge remote-tracking branch 'origin/14.6'

Roc 1 year ago
parent
commit
a72fdf40b3

+ 36 - 6
controllers/company_share.go

@@ -88,11 +88,13 @@ func (this *CompanyController) CompanyShare() {
 	br.Msg = "设置成功"
 }
 
+// CompanyShareList
 // @Title 共享客户列表
 // @Description 共享客户列表接口
 // @Param   SellerId   query   string  false       "选择的销售id"
+// @Param   OriginalSellerId   query   string  false       "选择的原销售id"
 // @Param   Keyword   query   string  true       "搜索关键词"
-// @Param   ListParam   query   int  false       "筛选字段参数,用来筛选的字段, 枚举值:0:全部 、 1:已分配 、 2:未分配  "
+// @Param   ListParam   query   int  false       "筛选字段参数,用来筛选的字段, 枚举值:0:全部 、 1:已分配 、 2:未分配 、 3:未共享 "
 // @Param   SortParam   query   string  false       "排序字段参数,用来排序的字段, 枚举值:'viewTotal':总阅读次数 、 'viewTime':阅读时间 、 'roadShowTotal':累计路演次数 、`expireDay:到期时间` 、 `createTime:创建时间` 、 'formalTime': 转正时间 、 'freezeTime':冻结时间 、'lossTime':流失时间  、'tryOutDay':试用天数"
 // @Param   SortType   query   string  true       "如何排序,是正序还是倒序,枚举值:`asc 正序`,`desc 倒叙`"
 // @Param   PageSize   query   int  true       "每页数据条数"
@@ -116,6 +118,7 @@ func (this *CompanyController) CompanyShareList() {
 	pageSize, _ := this.GetInt("PageSize")
 	currentIndex, _ := this.GetInt("CurrentIndex")
 	sellerIds := this.GetString("SellerId")
+	originalSellerIds := this.GetString("OriginalSellerId")
 	keyword := this.GetString("Keyword")
 	//排序参数
 	sortParam := this.GetString("SortParam")
@@ -150,6 +153,14 @@ func (this *CompanyController) CompanyShareList() {
 		}
 	}
 
+	// 咨询组的分组id
+	groupId := 0
+	if utils.RunMode == "release" {
+		groupId = 37
+	} else {
+		groupId = 61
+	}
+
 	roleTypeCode := sysUser.RoleTypeCode
 	productId := services.GetProductId(roleTypeCode)
 	//权限控制
@@ -171,17 +182,36 @@ func (this *CompanyController) CompanyShareList() {
 		}
 	}
 
+	if listParam == 0 {
+		if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_SELLER || sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_GROUP || sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_TEAM {
+			//非咨询组销售,那么默认查看“未共享”的客户
+			if sysUser.GroupId != groupId {
+				listParam = 3
+				condition += ` AND b.seller_id = ? `
+				pars = append(pars, sysUser.AdminId)
+			} else {
+				condition += ` AND a.is_share=1 `
+			}
+		} else if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN || sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_ADMIN {
+			// 管理员,默认查看“待分配”客户
+			listParam = 2
+		}
+	}
+
 	if listParam == 1 {
-		condition += ` AND a.share_seller <> '' AND a.is_share=1 `
+		condition += ` AND a.share_seller_id > 0 AND a.is_share=1 `
 	} else if listParam == 2 {
-		condition += ` AND a.share_seller = '' AND a.is_share=1 `
-	} else {
-		condition += ` AND a.is_share=1 `
+		condition += ` AND a.share_seller_id = 0 AND a.is_share=1 `
+	} else if listParam == 3 { // 未共享
+		condition += ` AND a.is_share=0 and b.status="正式"`
 	}
 
 	if sellerIds != "" {
 		condition += ` AND a.share_seller_id IN (` + sellerIds + `) `
 	}
+	if originalSellerIds != "" {
+		condition += ` AND b.seller_id IN (` + originalSellerIds + `) `
+	}
 
 	total, err := company.GetShareCompanyListCount(condition, pars)
 	if err != nil {
@@ -1008,4 +1038,4 @@ func (this *CompanyController) CompanyShareListByCity() {
 	br.Msg = "获取成功"
 	br.Data = resp
 
-}
+}

+ 210 - 48
controllers/statistic_report.go

@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/shopspring/decimal"
 	"github.com/tealeg/xlsx"
 	"hongze/hz_crm_api/models"
 	"hongze/hz_crm_api/models/company"
@@ -5394,12 +5395,15 @@ func (this *StatisticReportController) RenewCompanyStatistics() {
 	tmpAllRenewFollowNumMap := make(map[int]int)
 	tmpAllExpireNumMap := make(map[int]int)
 	tmpAllRenewNumMap := make(map[int]int)
+	tmpAllUnusualRenewNumMap := make(map[int]int)  // 续约异常客户数量汇总
+	tmpAllFormalCompanyNumMap := make(map[int]int) // 当期正式客户数量汇总
 
 	//id集合汇总
 	tmpAllNotRenewIdMap := make(map[int]string)
 	tmpAllRenewFollowIdMap := make(map[int]string)
 	tmpAllExpireIdMap := make(map[int]string)
 	tmpAllRenewIdMap := make(map[int]string)
+	tmpAllUnusualRenewIdMap := make(map[int]string) // 续约异常客户id汇总
 
 	for _, v := range group {
 		v.ResearcherList = groupMap[v.GroupId]
@@ -5411,18 +5415,21 @@ func (this *StatisticReportController) RenewCompanyStatistics() {
 		tmpGroupRenewFollowNumMap := make(map[int]int)
 		tmpGroupExpireNumMap := make(map[int]int)
 		tmpGroupRenewNumMap := make(map[int]int)
+		tmpGroupUnusualRenewNumMap := make(map[int]int) //组内续约异常客户数
 
 		//id集合
 		tmpGroupNotRenewIdSliceMap := make(map[int][]string)
 		tmpGroupRenewFollowIdSliceMap := make(map[int][]string)
 		tmpGroupExpireIdSliceMap := make(map[int][]string)
 		tmpGroupRenewIdSliceMap := make(map[int][]string)
+		tmpGroupUnusualRenewIdSliceMap := make(map[int][]string) // 组内续约异常客户id汇总
 
 		//id集合
 		tmpGroupNotRenewIdMap := make(map[int]string)
 		tmpGroupRenewFollowIdMap := make(map[int]string)
 		tmpGroupExpireIdMap := make(map[int]string)
 		tmpGroupRenewIdMap := make(map[int]string)
+		tmpGroupUnusualRenewIdMap := make(map[int]string) // 组内续约异常客户id汇总
 
 		for _, researcher := range groupMap[v.GroupId] {
 			//组内研究员数据
@@ -5433,10 +5440,10 @@ func (this *StatisticReportController) RenewCompanyStatistics() {
 				startDateIndexList[index] = adminData.StartDate
 				endDateIndexList[index] = adminData.EndDate
 
-				var tmpNotRenewNum, tmpRenewFollowNum, tmpExpireStatus, tmpRenewStatus int
+				var tmpNotRenewNum, tmpRenewFollowNum, tmpExpireStatus, tmpRenewStatus, tmpUnusualRenewStatus int
 				//var tmpNotRenewIds, tmpRenewFollowIds, tmpExpireIds string
-				var tmpNotRenewIdSlice, tmpRenewFollowIdSlice, tmpExpireIdSlice, tmpRenewIdSlice []string
-				var tmpNotRenewId, tmpRenewFollowId, tmpExpireId, tmpRenewId string
+				var tmpNotRenewIdSlice, tmpRenewFollowIdSlice, tmpExpireIdSlice, tmpRenewIdSlice, tmpUnusualRenewIdSlice []string
+				var tmpNotRenewId, tmpRenewFollowId, tmpExpireId, tmpRenewId, tmpUnusualRenewId string
 
 				if num, ok := adminData.NotRenewMap[researcher.AdminId]; ok {
 					tmpNotRenewNum = num
@@ -5458,18 +5465,26 @@ func (this *StatisticReportController) RenewCompanyStatistics() {
 					tmpRenewIdSlice = append(tmpRenewIdSlice, adminData.RenewIdMap[researcher.AdminId])
 					tmpRenewId = strings.Join(tmpRenewIdSlice, ",")
 				}
+				// 续约异常客户
+				if num, ok := adminData.UnusualRenewMap[researcher.AdminId]; ok {
+					tmpUnusualRenewStatus = num
+					tmpUnusualRenewIdSlice = append(tmpUnusualRenewIdSlice, adminData.UnusualRenewIdMap[researcher.AdminId])
+					tmpUnusualRenewId = strings.Join(tmpUnusualRenewIdSlice, ",")
+				}
 
 				tmpAdminRsRenewRecordNum := statistic_report.CompanyRenewRecordNum{
-					NotRenewNum:    tmpNotRenewNum,
-					NotRenewIds:    tmpNotRenewId,
-					RenewFollowNum: tmpRenewFollowNum,
-					RenewFollowIds: tmpRenewFollowId,
-					ExpireNum:      tmpExpireStatus,
-					ExpireIds:      tmpExpireId,
-					RenewNum:       tmpRenewStatus,
-					RenewIds:       tmpRenewId,
-					StartDate:      adminData.StartDate,
-					EndDate:        adminData.EndDate,
+					NotRenewNum:     tmpNotRenewNum,
+					NotRenewIds:     tmpNotRenewId,
+					RenewFollowNum:  tmpRenewFollowNum,
+					RenewFollowIds:  tmpRenewFollowId,
+					ExpireNum:       tmpExpireStatus,
+					ExpireIds:       tmpExpireId,
+					RenewNum:        tmpRenewStatus,
+					RenewIds:        tmpRenewId,
+					UnusualRenewNum: tmpUnusualRenewStatus,
+					UnusualRenewIds: tmpUnusualRenewId,
+					StartDate:       adminData.StartDate,
+					EndDate:         adminData.EndDate,
 				}
 				tmpCompanyRenewRecordNumList = append(tmpCompanyRenewRecordNumList, tmpAdminRsRenewRecordNum)
 
@@ -5486,11 +5501,15 @@ func (this *StatisticReportController) RenewCompanyStatistics() {
 				if _, ok := tmpGroupRenewNumMap[index]; !ok {
 					tmpGroupRenewNumMap[index] = 0
 				}
+				if _, ok := tmpGroupUnusualRenewNumMap[index]; !ok {
+					tmpGroupUnusualRenewNumMap[index] = 0
+				}
 
 				tmpGroupNotRenewNumMap[index] += tmpNotRenewNum
 				tmpGroupRenewFollowNumMap[index] += tmpRenewFollowNum
 				tmpGroupExpireNumMap[index] += tmpExpireStatus
 				tmpGroupRenewNumMap[index] += tmpRenewStatus
+				tmpGroupUnusualRenewNumMap[index] += tmpUnusualRenewStatus
 
 				//组内数据汇总
 				if _, ok := tmpGroupNotRenewIdMap[index]; !ok {
@@ -5514,6 +5533,9 @@ func (this *StatisticReportController) RenewCompanyStatistics() {
 				if tmpRenewId != "" {
 					tmpGroupRenewIdSliceMap[index] = append(tmpGroupRenewIdSliceMap[index], tmpRenewId)
 				}
+				if tmpUnusualRenewId != "" {
+					tmpGroupUnusualRenewIdSliceMap[index] = append(tmpGroupUnusualRenewIdSliceMap[index], tmpUnusualRenewId)
+				}
 
 				//总数据汇总
 				if _, ok := tmpAllNotRenewNumMap[index]; !ok {
@@ -5533,20 +5555,8 @@ func (this *StatisticReportController) RenewCompanyStatistics() {
 				tmpAllRenewFollowNumMap[index] += tmpRenewFollowNum
 				tmpAllExpireNumMap[index] += tmpExpireStatus
 				tmpAllRenewNumMap[index] += tmpRenewStatus
-
-				////总数据汇总
-				//if _, ok := tmpAllNotRenewIdMap[index]; !ok {
-				//	tmpAllNotRenewIdMap[index] = ""
-				//}
-				//if _, ok := tmpAllRenewFollowIdMap[index]; !ok {
-				//	tmpAllRenewFollowIdMap[index] = ""
-				//}
-				//if _, ok := tmpAllExpireIdMap[index]; !ok {
-				//	tmpAllExpireIdMap[index] = ""
-				//}
-				//tmpAllNotRenewIdMap[index] += tmpNotRenewId
-				//tmpAllRenewFollowIdMap[index] += tmpRenewFollowId
-				//tmpAllExpireIdMap[index] += tmpExpireId
+				tmpAllUnusualRenewNumMap[index] = adminData.UnusualRenewTotal
+				tmpAllFormalCompanyNumMap[index] = adminData.FormalCompanyTotal
 			}
 			tmpAdminRenewRecord := statistic_report.AdminRenewRecord{
 				Name:                      researcher.RealName,
@@ -5561,18 +5571,21 @@ func (this *StatisticReportController) RenewCompanyStatistics() {
 			tmpGroupRenewFollowIdMap[i] = strings.Join(tmpGroupRenewFollowIdSliceMap[i], ",")
 			tmpGroupExpireIdMap[i] = strings.Join(tmpGroupExpireIdSliceMap[i], ",")
 			tmpGroupRenewIdMap[i] = strings.Join(tmpGroupRenewIdSliceMap[i], ",")
+			tmpGroupUnusualRenewIdMap[i] = strings.Join(tmpGroupUnusualRenewIdSliceMap[i], ",")
 
 			tmpGroupCompanyRenewRecordNum := statistic_report.CompanyRenewRecordNum{
-				NotRenewNum:    tmpGroupNotRenewNumMap[i],
-				NotRenewIds:    tmpGroupNotRenewIdMap[i],
-				RenewFollowNum: tmpGroupRenewFollowNumMap[i],
-				RenewFollowIds: tmpGroupRenewFollowIdMap[i],
-				ExpireNum:      tmpGroupExpireNumMap[i],
-				ExpireIds:      tmpGroupExpireIdMap[i],
-				RenewNum:       tmpGroupRenewNumMap[i],
-				RenewIds:       tmpGroupRenewIdMap[i],
-				StartDate:      startDateIndexList[i],
-				EndDate:        endDateIndexList[i],
+				NotRenewNum:     tmpGroupNotRenewNumMap[i],
+				NotRenewIds:     tmpGroupNotRenewIdMap[i],
+				RenewFollowNum:  tmpGroupRenewFollowNumMap[i],
+				RenewFollowIds:  tmpGroupRenewFollowIdMap[i],
+				ExpireNum:       tmpGroupExpireNumMap[i],
+				ExpireIds:       tmpGroupExpireIdMap[i],
+				RenewNum:        tmpGroupRenewNumMap[i],
+				RenewIds:        tmpGroupRenewIdMap[i],
+				UnusualRenewNum: tmpGroupUnusualRenewNumMap[i],
+				UnusualRenewIds: tmpGroupUnusualRenewIdMap[i],
+				StartDate:       startDateIndexList[i],
+				EndDate:         endDateIndexList[i],
 			}
 			tmpGroupCompanyRenewRecordNumList = append(tmpGroupCompanyRenewRecordNumList, tmpGroupCompanyRenewRecordNum)
 		}
@@ -5587,17 +5600,24 @@ func (this *StatisticReportController) RenewCompanyStatistics() {
 
 	//总体汇总数据
 	for i := 0; i < len(tmpAllRenewFollowNumMap); i++ {
+		unusualRate := ``
+		if tmpAllUnusualRenewNumMap[i] > 0 && tmpAllFormalCompanyNumMap[i] > 0 {
+			unusualRate = decimal.NewFromInt(int64(tmpAllUnusualRenewNumMap[i])*100).Div(decimal.NewFromInt(int64(tmpAllFormalCompanyNumMap[i]))).Round(2).String() + "%"
+		}
 		tmpGroupCompanyRenewRecordNum := statistic_report.CompanyRenewRecordNum{
-			NotRenewNum:    tmpAllNotRenewNumMap[i],
-			NotRenewIds:    tmpAllNotRenewIdMap[i],
-			RenewFollowNum: tmpAllRenewFollowNumMap[i],
-			RenewFollowIds: tmpAllRenewFollowIdMap[i],
-			ExpireNum:      tmpAllExpireNumMap[i],
-			ExpireIds:      tmpAllExpireIdMap[i],
-			RenewNum:       tmpAllRenewNumMap[i],
-			RenewIds:       tmpAllRenewIdMap[i],
-			StartDate:      startDateIndexList[i],
-			EndDate:        endDateIndexList[i],
+			NotRenewNum:     tmpAllNotRenewNumMap[i],
+			NotRenewIds:     tmpAllNotRenewIdMap[i],
+			RenewFollowNum:  tmpAllRenewFollowNumMap[i],
+			RenewFollowIds:  tmpAllRenewFollowIdMap[i],
+			ExpireNum:       tmpAllExpireNumMap[i],
+			ExpireIds:       tmpAllExpireIdMap[i],
+			RenewNum:        tmpAllRenewNumMap[i],
+			RenewIds:        tmpAllRenewIdMap[i],
+			UnusualRenewNum: tmpAllUnusualRenewNumMap[i],
+			UnusualRenewIds: tmpAllUnusualRenewIdMap[i],
+			UnusualRate:     unusualRate, // 异常率
+			StartDate:       startDateIndexList[i],
+			EndDate:         endDateIndexList[i],
 		}
 		allCompanyRenewRecordNum = append(allCompanyRenewRecordNum, tmpGroupCompanyRenewRecordNum)
 	}
@@ -6123,7 +6143,7 @@ func (this *StatisticReportController) InvoicePaymentList() {
 	br.Data = results
 }
 
-// ServiceList
+// SimpleList
 // @Title 合同套餐列表
 // @Description 合同套餐列表
 // @Param   ProductId  query  int  false  "套餐类型: 1-FICC(默认); 2-权益"
@@ -6195,3 +6215,145 @@ func (this *StatisticReportController) SimpleList() {
 	br.Msg = "获取成功"
 	br.Data = respList
 }
+
+// UnusualRenewCompanyStatistics
+// @Title 获取续约异常的客户统计数据
+// @Description 获取续约客户统计数据接口
+// @Param   DataType   query   string  true       "枚举值:week、month、time_interval"
+// @Param   StartDate   query   string  true       "开始日期,格式:2022-04-06"
+// @Param   EndDate   query   string  true       "结束日期,格式:2022-04-06"
+// @Success 200 {object} statistic_report.CompanyUnusualRenewRecordResp
+// @router /report/unusual_renew_company [get]
+func (this *StatisticReportController) UnusualRenewCompanyStatistics() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	dataType := this.GetString("DataType")
+	productId, _ := this.GetInt("ProductId", 1)
+	startDate := this.GetString("StartDate")
+	endDate := this.GetString("EndDate")
+
+	var companyUnusualRenewDataMapList []statistic_report.UnusualCompanyRenewDataMap
+	var err error
+	//var firstDate time.Time
+	switch dataType {
+	//获取列表
+	case "week":
+		nowWeekMonday := utils.GetNowWeekMonday() //本周周一
+		//companyRenewDataMapList, firstDate, err = statistic_report.GetWeekData()
+		companyUnusualRenewDataMapList, _, err = statistic_report.GetUnusualRenewWeekDataNum(nowWeekMonday, productId, 6)
+		if err != nil {
+			br.Msg = "数据异常"
+			br.ErrMsg = "数据异常,Err:" + err.Error()
+			return
+		}
+	case "month":
+		nowMonthFirstDay := utils.GetNowMonthFirstDay() //本月第一天
+		companyUnusualRenewDataMapList, _, err = statistic_report.GetUnusualRenewMonthDataNum(nowMonthFirstDay, productId, 6)
+		if err != nil {
+			br.Msg = "数据异常"
+			br.ErrMsg = "数据异常,Err:" + err.Error()
+			return
+		}
+	case "time_interval":
+		if startDate == `` || endDate == `` {
+			br.Msg = "开始日期或结束日期不能为空"
+			br.ErrMsg = "开始日期或结束日期不能为空,Err:" + err.Error()
+			return
+		}
+		companyUnusualRenewDataMapList, _, err = statistic_report.GetUnusualRenewTimeIntervalData(productId, startDate, endDate)
+		if err != nil {
+			br.Msg = "数据异常"
+			br.ErrMsg = "数据异常,Err:" + err.Error()
+			return
+		}
+
+	}
+
+	groupId := 0
+	if utils.RunMode == "release" {
+		groupId = 37
+	} else {
+		groupId = 61
+	}
+	subAdmins, err := system.GetAdminByGroupId(groupId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取销售失败"
+		br.ErrMsg = "获取销售失败,Err:" + err.Error()
+		return
+	}
+
+	//数据处理
+	list := make([]statistic_report.GroupUnusualRenewRecord, 0)
+	summaryList := make([]statistic_report.SummaryUnusualRenewRecordNum, 0)
+	companyRenewRecordResp := statistic_report.CompanyUnusualRenewRecordResp{
+		List:        list,
+		SummaryList: summaryList,
+	}
+
+	// 每日期组数据的汇总客户id
+	companyIdIndexMap := make(map[int][]string)
+	for k, v := range subAdmins {
+		tmpGroupCompanyRenewRecordNumList := make([]statistic_report.CompanyUnusualRenewRecordNum, 0)
+
+		for index, adminData := range companyUnusualRenewDataMapList {
+			tmpGroupCompanyRenewRecordNumList = append(tmpGroupCompanyRenewRecordNumList, statistic_report.CompanyUnusualRenewRecordNum{
+				UnusualRenewNum: adminData.UnusualRenewMap[v.AdminId],
+				UnusualRenewIds: adminData.UnusualRenewIdMap[v.AdminId],
+				StartDate:       adminData.StartDate,
+				EndDate:         adminData.EndDate,
+			})
+
+			if adminData.UnusualRenewIdMap[v.AdminId] != `` {
+				tmpCompanyIdList, ok := companyIdIndexMap[index]
+				if !ok {
+					tmpCompanyIdList = make([]string, 0)
+				}
+				companyIdIndexMap[index] = append(tmpCompanyIdList, adminData.UnusualRenewIdMap[v.AdminId])
+			}
+
+			if k == 0 {
+				unusualRate := ``
+				if adminData.UnusualRenewTotal > 0 && adminData.FormalCompanyTotal > 0 {
+					unusualRate = decimal.NewFromInt(int64(adminData.UnusualRenewTotal)*100).Div(decimal.NewFromInt(int64(adminData.FormalCompanyTotal))).Round(2).String() + `%`
+				}
+				summaryList = append(summaryList, statistic_report.SummaryUnusualRenewRecordNum{
+					UnusualRenewNum: adminData.UnusualRenewTotal,
+					UnusualRate:     unusualRate,
+				})
+			}
+		}
+		list = append(list, statistic_report.GroupUnusualRenewRecord{
+			SellerId:                  v.AdminId,
+			SellerName:                v.RealName,
+			CompanyRenewRecordNumList: tmpGroupCompanyRenewRecordNumList,
+		})
+	}
+
+	// 汇总数据
+	for index, _ := range summaryList {
+		tmpCompanyIdList, ok := companyIdIndexMap[index]
+		if ok {
+			summaryList[index].UnusualRenewIds = strings.Join(tmpCompanyIdList, ",")
+		}
+	}
+
+	companyRenewRecordResp.List = list
+	companyRenewRecordResp.SummaryList = summaryList
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = companyRenewRecordResp
+}

+ 3 - 0
controllers/sys_menu.go

@@ -98,6 +98,9 @@ func (this *SysRoleController) SysMenuList() {
 					child = append(child[:i], child[i+1:]...)
 				}
 			}
+			//if menu.Name == "正式客户共享" && !utils.InArrayByStr([]string{utils.ROLE_TYPE_CODE_ADMIN, utils.ROLE_TYPE_CODE_FICC_ADMIN, utils.ROLE_TYPE_CODE_FICC_SELLER, utils.ROLE_TYPE_CODE_FICC_GROUP, utils.ROLE_TYPE_CODE_FICC_TEAM}, sysUser.RoleTypeCode) {
+			//	child = append(child[:i], child[i+1:]...)
+			//}
 		}
 
 		if strings.Contains(item.Name, "出差管理") && sysUser.AdminId == utils.ApproveUserId {

+ 9 - 0
models/company/company_contract.go

@@ -262,3 +262,12 @@ func UpdateCompanyContractPackageDifference(packageDifference string, companyCon
 	_, err = o.Raw(sql, packageDifference, companyContractId).Exec()
 	return
 }
+
+// GetLastContractListByEndDate 通过最近一份合同的日期获取早于该合同的最晚一份合同
+func GetLastContractListByEndDate(companyId, productId int, endDate string) (item *CompanyContract, err error) {
+	o := orm.NewOrm()
+	sql := "SELECT * FROM company_contract where company_id = ? AND product_id= ? end_date < ? AND status = 1 ORDER BY end_date desc"
+	err = o.Raw(sql, companyId, productId, endDate).QueryRow(&item)
+
+	return
+}

+ 64 - 0
models/company/company_product.go

@@ -581,3 +581,67 @@ func GetCompanyProductListBycondition(condition string, pars []interface{}) (ite
 	_, err = o.Raw(sql, pars).QueryRows(&items)
 	return
 }
+
+// CompanyProductItem
+// @Description: 客户品种
+type CompanyProductItem struct {
+	CompanyProductId int       `orm:"column(company_product_id);pk" description:"客户产品id"`
+	CompanyId        int       `description:"客户id"`
+	ProductId        int       `description:"产品id"`
+	ProductName      string    `description:"产品名称"`
+	CompanyName      string    `description:"客户名称"`
+	Source           string    `description:"来源"`
+	Reasons          string    `description:"新增理由"`
+	Status           string    `description:"客户状态"`
+	IndustryId       int       `description:"行业id"`
+	IndustryName     string    `description:"行业名称"`
+	SellerId         int       `description:"销售id"`
+	SellerName       string    `description:"销售名称"`
+	GroupId          int       `description:"销售分组id"`
+	DepartmentId     int       `description:"销售部门id"`
+	IsSuspend        int       `description:"1:暂停,0:启用"`
+	SuspendTime      time.Time `description:"暂停启用时间"`
+	ApproveStatus    string    `description:"审批状态:'审批中','通过','驳回'"`
+	FreezeTime       time.Time `description:"冻结时间"`
+	Remark           string    `description:"备注信息"`
+	CreateTime       time.Time `description:"创建时间"`
+	ModifyTime       time.Time `description:"修改时间"`
+	StartDate        string    `description:"开始日期"`
+	EndDate          string    `description:"结束日期"`
+	ContractEndDate  string    `description:"合同结束日期"`
+	LoseReason       string    `description:"流失原因"`
+	LossTime         time.Time `description:"流失时间"`
+	CompanyType      string    `description:"客户类型"`
+	OpenCode         string    `description:"开放给第三方的编码,不让第三方定位我们的客户信息"`
+	Scale            string    `description:"管理规模,空不填,1::50亿以下,2:50~100亿,3:100亿以上。"`
+	ViewTotal        int       `description:"总阅读次数"`
+	RoadShowTotal    int       `description:"累计路演次数"`
+	LastViewTime     time.Time `description:"最后一次阅读时间"`
+	PackageType      int       `description:"套餐类型,0:无,1:大套餐,2:小套餐"`
+	IsFormal         int       `description:"是否已经转正式,0是没有转正式,1是已经转过正式"`
+	TodoStatus       string    `description:"任务处理状态;枚举值:'无任务','未完成','已完成'"`
+	TodoCreateTime   time.Time `description:"任务创建时间"`
+	TodoApproveTime  time.Time `description:"任务审批时间"`
+	TryStage         int       `description:"试用客户子标签:1未分类、2  推进、3 跟踪、4 预备"`
+	IsShare          int       `description:"0:非共享用户,1:共享客户"`
+	ShareSeller      string    `description:"共享销售员"`
+	ShareSellerId    int       `description:"共享销售员id"`
+}
+
+// GetCompanyProductItemByCompanyId
+// @Description: 根据客户ID获取客户产品列表
+// @author: Roc
+// @datetime 2023-12-07 11:06:58
+// @param companyIdList []int
+// @param productId int
+// @return items []*CompanyProductItem
+// @return err error
+func GetCompanyProductItemByCompanyId(companyId int, productId int) (items *CompanyProductItem, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT a.*,b.is_share,b.share_seller,b.share_seller_id FROM company_product as a 
+         JOIN company b on a.company_id=b.company_id
+         WHERE a.company_id = ? AND a.product_id = ? `
+	_, err = o.Raw(sql, companyId, productId).QueryRows(&items)
+
+	return
+}

+ 61 - 0
models/company/company_renewal_record.go

@@ -0,0 +1,61 @@
+package company
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// CompanyRenewalRecord
+// @Description: 客户续约状态记录表
+type CompanyRenewalRecord struct {
+	Id              int       `orm:"column(id);pk"`
+	CompanyId       int       `description:"客户id"`
+	ProductId       int       `description:"产品id"`
+	Source          int       `description:"类型,枚举值,1:续约异常客户;2:续约正常客户;3:超时续约客户"`
+	SellerId        int       `description:"销售id"`
+	SellerName      string    `description:"销售名称"`
+	ShareSellerId   int       `description:"共享销售id"`
+	ShareSellerName string    `description:"共享销售名称"`
+	CreateTime      time.Time `description:"创建时间"`
+	ModifyTime      time.Time `description:"修改时间"`
+}
+
+// GetUnusualRenewCompanyList 获取销售未续约数据
+func GetUnusualRenewCompanyList(startDate, endDate time.Time, productId int) (list []*CompanyRenewalRecord, err error) {
+	o := orm.NewOrm()
+	sql := `	SELECT
+	a.seller_id,a.share_seller_id,
+	count(
+	DISTINCT ( a.company_id )) num,
+	GROUP_CONCAT( DISTINCT a.company_id SEPARATOR ',' ) AS company_ids 
+	FROM
+	company_renewal_record as a
+WHERE
+	a.modify_time BETWEEN ? 
+	AND ? 
+    AND a.source = 1 
+	AND a.product_id = ?
+GROUP BY
+	a.seller_id;
+`
+	_, err = o.Raw(sql, startDate, endDate, productId).QueryRows(&list)
+
+	return
+}
+
+// Add
+// @Description: 添加续约用户记录
+// @author: Roc
+// @datetime 2023-12-07 14:16:37
+// @param item *CompanyRenewalRecord
+// @return err error
+func (item *CompanyRenewalRecord) Add() (err error) {
+	o := orm.NewOrm()
+	lastId, err := o.Insert(item)
+	if err != nil {
+		return
+	}
+	item.Id = int(lastId)
+
+	return
+}

+ 63 - 0
models/contract/contract.go

@@ -579,3 +579,66 @@ func GetContractListByCompanyName(companyName string) (item *ContractList, err e
 	err = o.Raw(sql, companyName).QueryRow(&item)
 	return
 }
+
+type RenewCompanyGroup struct {
+	SellerId int `description:"所属销售id"`
+	//AdminName string `description:"所属销售名称"`
+	Num        int    `description:"汇总次数"`
+	CompanyIds string `description:"客户id字符串"`
+}
+
+// GetExpiresCompanyGroupList 获取销售到期数据
+func GetExpiresCompanyGroupList(startDate, endDate time.Time, productId int) (list []*RenewCompanyGroup, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+	a.seller_id,
+	count(
+	DISTINCT ( a.company_id )) num,
+	GROUP_CONCAT( DISTINCT a.company_id SEPARATOR ',' ) AS company_ids 
+FROM
+	company_product as a 
+join company_contract as b on a.company_id=b.company_id and a.product_id=b.product_id
+WHERE
+	a.product_id=?
+AND	b.product_id=?
+AND
+	b.end_date >= ?
+	AND b.end_date < ? 
+AND b.status = 1
+GROUP BY
+	a.seller_id
+`
+	_, err = o.Raw(sql, productId, productId, startDate, endDate).QueryRows(&list)
+
+	return
+}
+
+// GetCountFormalCompany
+// @Description: 获取某个时间点前的合同客户数量
+// @author: Roc
+// @datetime 2023-12-05 09:36:28
+// @param endDate time.Time
+// @param productId int
+// @return total int
+// @return err error
+func GetCountFormalCompany(endDate time.Time, productId int) (total int, err error) {
+	o := orm.NewOrm()
+	sql := `select count(1) total from (
+    SELECT
+	a.seller_id
+FROM
+	company_product as a 
+join company_contract as b on a.company_id=b.company_id and a.product_id=b.product_id
+WHERE
+	a.product_id=?
+AND	b.product_id=?
+	AND b.end_date < ? 
+AND b.status = 1
+GROUP BY
+	a.company_id
+) z
+`
+	err = o.Raw(sql, productId, productId, endDate).QueryRow(&total)
+
+	return
+}

+ 1 - 0
models/db.go

@@ -263,6 +263,7 @@ func initCompany() {
 		new(company.CompanyContractNoRenewedAscribe),         // 合同确认不续约记录
 		new(company.CompanyContractNoRenewedAscribeLog),      // 合同确认不续约记录日志
 		new(company.CrmConfig),                               // 管理后台基本配置表
+		new(company.CompanyRenewalRecord),                    // 客户续约状态记录表
 	)
 }
 

+ 9 - 0
routers/commentsRouter.go

@@ -10528,6 +10528,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:StatisticReportController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:StatisticReportController"],
+        beego.ControllerComments{
+            Method: "UnusualRenewCompanyStatistics",
+            Router: `/report/unusual_renew_company`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:StatisticReportController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:StatisticReportController"],
         beego.ControllerComments{
             Method: "StackCompanyList",

+ 76 - 0
services/company_apply/company_approval.go

@@ -757,6 +757,9 @@ func afterApproved(companyApprovalId int, opUserId int, opUserName string) (err
 
 		//如果合同时间小于等于今天,那么立马执行合同内容
 		if time.Now().After(contractStartDate) {
+			// 合同处理完成后的续约异常记录
+			contactHandleCompanyRenewalRecord(contractInfo)
+
 			startDate = contractInfo.StartDate
 			endDate = contractInfo.EndDate
 			companyReportPermissionList, err = company.ApplyServiceUpdate(recodeInfo.CompanyId, recodeInfo.ProductId, opUser.AdminId, recodeInfo.CompanyApprovalId, recodeInfo.CompanyContractId, companyProduct.StartDate, contractInfo.EndDate, opUser.RealName, companyProduct.ProductName, contractInfo.PackageType, contractInfo.RaiPackageType)
@@ -887,6 +890,79 @@ func afterApproved(companyApprovalId int, opUserId int, opUserName string) (err
 	return
 }
 
+// contactHandleCompanyRenewalRecord
+// @Description: 合同处理完成后的续约异常记录
+// @author: Roc
+// @datetime 2023-12-07 14:24:44
+// @param contractInfo *company_contract.CompanyContract
+// @param day string
+// @return err error
+func contactHandleCompanyRenewalRecord(contractInfo *company.CompanyContractDetail) {
+	var err error
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("合同处理完成后的续约异常记录," + err.Error())
+		}
+	}()
+	// 判断合同类型是否是续约合同,如果不是的话,就不往下走了
+	if contractInfo.ContractType != `续约合同` {
+		return
+	}
+
+	day := time.Now().Format(utils.FormatDate)
+
+	// 获取早于当前合同结束日期的上一份合同
+	lastContract, tmpErr := company.GetLastContractListByEndDate(contractInfo.CompanyId, contractInfo.ProductId, contractInfo.EndDate)
+	if tmpErr != nil {
+		err = errors.New(fmt.Sprint("合同id:", contractInfo.CompanyContractId, ";通过最近一份合同的日期获取早于该合同的最晚一份合同失败,ERR:", tmpErr))
+		return
+	}
+	// 校验 上一份合同的结束日期 与 今天 相隔的天数
+	betweenDay, tmpErr := utils.GetDaysBetween2Date(utils.FormatDate, day, lastContract.EndDate)
+	if tmpErr != nil {
+		err = errors.New(fmt.Sprint("合同id:", contractInfo.CompanyContractId, ";计算两个日期相差的天数失败,ERR:", tmpErr))
+		return
+	}
+
+	source := 2 // 正常续约
+	// 如果间隔时间超过60天,那么标记为超时续约
+	if betweenDay > 60 {
+		source = 3 // 超时续约
+	}
+
+	// 如果间隔时间超过60天,那么标记为超时续约
+	companyProductItem, tmpErr := company.GetCompanyProductItemByCompanyId(contractInfo.CompanyId, contractInfo.ProductId)
+	if tmpErr != nil {
+		err = errors.New(fmt.Sprint("合同id:", contractInfo.CompanyContractId, ";GetCompanyProductItemByCompanyId失败,ERR:", tmpErr))
+		return
+	}
+
+	var shareSellerId int
+	var shareSellerName string
+	if companyProductItem.IsShare == 1 {
+		shareSellerId = companyProductItem.ShareSellerId
+		shareSellerName = companyProductItem.ShareSeller
+	}
+	item := &company.CompanyRenewalRecord{
+		Id:              0,
+		CompanyId:       contractInfo.CompanyId,
+		ProductId:       contractInfo.ProductId,
+		Source:          source,
+		SellerId:        companyProductItem.SellerId,
+		SellerName:      companyProductItem.SellerName,
+		ShareSellerId:   shareSellerId,
+		ShareSellerName: shareSellerName,
+		CreateTime:      time.Now(),
+		ModifyTime:      time.Now(),
+	}
+	tmpErr = item.Add()
+	if tmpErr != nil {
+		err = errors.New(fmt.Sprint("合同id:", contractInfo.CompanyContractId, ";添加续约异常记录失败,ERR:", tmpErr))
+	}
+
+	return
+}
+
 // afterReject 驳回完成后操作
 func afterReject(companyApprovalId, opUserId int, opUserName, remark string) (err error) {
 	defer func() {

+ 91 - 24
services/statistic_report/renew_company.go

@@ -1,6 +1,7 @@
 package statistic_report
 
 import (
+	"fmt"
 	"hongze/hz_crm_api/models/company"
 	"hongze/hz_crm_api/models/contract"
 	"hongze/hz_crm_api/utils"
@@ -9,16 +10,20 @@ import (
 )
 
 type CompanyRenewDataMap struct {
-	NotRenewMap      map[int]int    `description:"未续约客户数"`
-	NotRenewIdMap    map[int]string `description:"未续约客户ids"`
-	RenewFollowMap   map[int]int    `description:"续约跟进客户数"`
-	RenewFollowIdMap map[int]string `description:"续约跟进客户ids"`
-	ExpireMap        map[int]int    `description:"到期客户数"`
-	ExpireIdMap      map[int]string `description:"到期客户ids"`
-	RenewMap         map[int]int    `description:"续约客户数"`
-	RenewIdMap       map[int]string `description:"续约客户ids"`
-	StartDate        string         `description:"开始日期"`
-	EndDate          string         `description:"开始日期"`
+	NotRenewMap        map[int]int    `description:"未续约客户数"`
+	NotRenewIdMap      map[int]string `description:"未续约客户ids"`
+	RenewFollowMap     map[int]int    `description:"续约跟进客户数"`
+	RenewFollowIdMap   map[int]string `description:"续约跟进客户ids"`
+	ExpireMap          map[int]int    `description:"到期客户数"`
+	ExpireIdMap        map[int]string `description:"到期客户ids"`
+	RenewMap           map[int]int    `description:"续约客户数"`
+	RenewIdMap         map[int]string `description:"续约客户ids"`
+	UnusualRenewMap    map[int]int    `description:"续约异常客户数"`
+	UnusualRenewIdMap  map[int]string `description:"续约异常客户ids"`
+	UnusualRenewTotal  int            `description:"续约异常客户总数(去重)"`
+	FormalCompanyTotal int            `description:"当前正常客户总数(去重)"`
+	StartDate          string         `description:"开始日期"`
+	EndDate            string         `description:"开始日期"`
 }
 
 // GetRenewWeekDataNum 周度数据
@@ -104,12 +109,17 @@ func GetRenewTimeIntervalData(productId int, startDate, endDate string) (adminDa
 // getRenewSectionData 获取周期数据
 func getRenewSectionData(productId int, startDate, endDate time.Time, ch chan CompanyRenewDataMap) (adminDataMap CompanyRenewDataMap, err error) {
 	defer func() {
+		if err != nil {
+			utils.FileLog.Error("getRenewSectionData,err:" + err.Error())
+			fmt.Println(err)
+		}
 		ch <- adminDataMap
 	}()
 	notRenewMap := make(map[int]int)
 	renewFollowMap := make(map[int]int)
 	expireMap := make(map[int]int)
 	renewMap := make(map[int]int)
+	unusualRenewMap := make(map[int]int) // 续约异常客户
 
 	//activeMap := make(map[int]int)              //新增的试用客户数量(活跃)
 	//allActiveMap := make(map[int]int)           //全部的试用客户数量(活跃)
@@ -119,6 +129,12 @@ func getRenewSectionData(productId int, startDate, endDate time.Time, ch chan Co
 	renewFollowIdMap := make(map[int]string)
 	expireIdMap := make(map[int]string)
 	renewIdMap := make(map[int]string)
+	unusualRenewCompanyIdMap := make(map[int]string)     // 续约异常客户
+	var unusualRenewCompanyTotal, formalCompanyTotal int //续约异常客户总数  , 当前正式的客户数
+	formalCompanyTotal, err = contract.GetCountFormalCompany(endDate, productId)
+	if err != nil {
+		return
+	}
 
 	//activeIdMap := make(map[int]string)              //新增的试用客户id集合(活跃)
 	//allActiveIdMap := make(map[int]string)           //全部的试用客户id集合(活跃)
@@ -207,7 +223,7 @@ func getRenewSectionData(productId int, startDate, endDate time.Time, ch chan Co
 	//到期
 	//companyIdList := make([]string, 0)
 	{
-		data, tmpErr := company.GetExpiresCompanyGroupList(startDate, endDate, productId)
+		data, tmpErr := contract.GetExpiresCompanyGroupList(startDate, endDate, productId)
 
 		if tmpErr != nil {
 			err = tmpErr
@@ -224,7 +240,7 @@ func getRenewSectionData(productId int, startDate, endDate time.Time, ch chan Co
 		}
 	}
 
-	//续约
+	// 续约
 	//companyIdList := make([]string, 0)
 	{
 		contractIds, tmpErr := contract.GetLatestContractListByProductId(productId)
@@ -235,10 +251,8 @@ func getRenewSectionData(productId int, startDate, endDate time.Time, ch chan Co
 		}
 		contractId := strings.Join(contractIds, ",")
 		data, tmpErr := company.GetRenewCompanyGroupList(startDate, endDate, contractId)
-
 		if tmpErr != nil {
 			err = tmpErr
-			utils.FileLog.Error(err.Error())
 			return
 		}
 		var renewIdSlice []string
@@ -251,17 +265,70 @@ func getRenewSectionData(productId int, startDate, endDate time.Time, ch chan Co
 		}
 	}
 
+	// 续约异常
+	{
+
+		data, tmpErr := company.GetUnusualRenewCompanyList(startDate, endDate, productId)
+
+		if tmpErr != nil {
+			err = tmpErr
+			utils.FileLog.Error(err.Error())
+			return
+		}
+
+		unusualRenewCompanyIdListMap := make(map[int][]string) // 续约异常客户
+		for _, v := range data {
+			tmp, ok := unusualRenewMap[v.SellerId]
+			if !ok {
+				tmp = 0
+			}
+			unusualRenewMap[v.SellerId] = tmp + 1
+
+			// 共享人id不为空,且不是所属销售
+			if v.ShareSellerId > 0 && v.ShareSellerId != v.SellerId {
+				tmp2, ok := unusualRenewMap[v.ShareSellerId]
+				if !ok {
+					tmp = 0
+				}
+				unusualRenewMap[v.ShareSellerId] = tmp2 + 1
+			}
+
+			// 客户id
+			tmpCompanyIdList, ok := unusualRenewCompanyIdListMap[v.SellerId]
+			if !ok {
+				tmpCompanyIdList = make([]string, 0)
+			}
+			unusualRenewCompanyIdListMap[v.SellerId] = append(tmpCompanyIdList, fmt.Sprint(v.CompanyId))
+
+			tmpCompanyIdList2, ok := unusualRenewCompanyIdListMap[v.ShareSellerId]
+			if !ok {
+				tmpCompanyIdList2 = make([]string, 0)
+			}
+			unusualRenewCompanyIdListMap[v.ShareSellerId] = append(tmpCompanyIdList2, fmt.Sprint(v.CompanyId))
+
+			unusualRenewCompanyTotal++
+		}
+
+		for sellerId, tmpCompanyIdList := range unusualRenewCompanyIdListMap {
+			unusualRenewCompanyIdMap[sellerId] = strings.Join(tmpCompanyIdList, ",")
+		}
+	}
+
 	adminDataMap = CompanyRenewDataMap{
-		NotRenewMap:      notRenewMap,
-		NotRenewIdMap:    notRenewIdMap,
-		RenewFollowMap:   renewFollowMap,
-		RenewFollowIdMap: renewFollowIdMap,
-		ExpireMap:        expireMap,
-		ExpireIdMap:      expireIdMap,
-		RenewMap:         renewMap,
-		RenewIdMap:       renewIdMap,
-		StartDate:        startDate.Format(utils.FormatDate),
-		EndDate:          endDate.Format(utils.FormatDate),
+		NotRenewMap:        notRenewMap,
+		NotRenewIdMap:      notRenewIdMap,
+		RenewFollowMap:     renewFollowMap,
+		RenewFollowIdMap:   renewFollowIdMap,
+		ExpireMap:          expireMap,
+		ExpireIdMap:        expireIdMap,
+		RenewMap:           renewMap,
+		RenewIdMap:         renewIdMap,
+		UnusualRenewMap:    unusualRenewMap,
+		UnusualRenewIdMap:  unusualRenewCompanyIdMap,
+		UnusualRenewTotal:  unusualRenewCompanyTotal,
+		FormalCompanyTotal: formalCompanyTotal,
+		StartDate:          startDate.Format(utils.FormatDate),
+		EndDate:            endDate.Format(utils.FormatDate),
 	}
 	return
 }

+ 46 - 10
services/statistic_report/reponse.go

@@ -173,16 +173,19 @@ type AdminRenewRecord struct {
 
 // CompanyRenewRecordNum 系统续约客户统计信息
 type CompanyRenewRecordNum struct {
-	NotRenewNum    int    `description:"未续约客户数"`
-	NotRenewIds    string `description:"未续约客户ids"`
-	RenewFollowNum int    `description:"续约跟进客户数"`
-	RenewFollowIds string `description:"续约跟进客户ids"`
-	ExpireNum      int    `description:"到期客户数"`
-	ExpireIds      string `description:"到期客户ids"`
-	RenewNum       int    `description:"续约客户数"`
-	RenewIds       string `description:"续约客户ids"`
-	StartDate      string `description:"开始日期"`
-	EndDate        string `description:"结束日期"`
+	NotRenewNum     int    `description:"未续约客户数"`
+	NotRenewIds     string `description:"未续约客户ids"`
+	RenewFollowNum  int    `description:"续约跟进客户数"`
+	RenewFollowIds  string `description:"续约跟进客户ids"`
+	ExpireNum       int    `description:"到期客户数"`
+	ExpireIds       string `description:"到期客户ids"`
+	RenewNum        int    `description:"续约客户数"`
+	RenewIds        string `description:"续约客户ids"`
+	StartDate       string `description:"开始日期"`
+	EndDate         string `description:"结束日期"`
+	UnusualRenewNum int    `description:"续约异常客户数"`
+	UnusualRenewIds string `description:"续约异常客户ids"`
+	UnusualRate     string `description:"异常率"`
 }
 
 type YbChartCollectListResp struct {
@@ -195,3 +198,36 @@ type YbChartCollectListItem struct {
 	ChartInfo  *data_manage.ChartInfoView
 	CreateTime string
 }
+
+// CompanyUnusualRenewRecordResp
+// @Description: 续约异常客户统计返回
+type CompanyUnusualRenewRecordResp struct {
+	List        []GroupUnusualRenewRecord      `description:"系统用户分组信息"`
+	SummaryList []SummaryUnusualRenewRecordNum `description:"汇总信息"`
+}
+
+// GroupUnusualRenewRecord
+// @Description: 续约异常的分组信息
+type GroupUnusualRenewRecord struct {
+	SellerId                  int                            `description:"销售ID"`
+	SellerName                string                         `description:"销售名称"`
+	CompanyRenewRecordNumList []CompanyUnusualRenewRecordNum `description:"统计次数"`
+}
+
+// CompanyUnusualRenewRecordNum
+// @Description: 续约异常客户统计信息
+type CompanyUnusualRenewRecordNum struct {
+	StartDate       string `description:"开始日期"`
+	EndDate         string `description:"结束日期"`
+	UnusualRenewNum int    `description:"续约异常客户数"`
+	UnusualRenewIds string `description:"续约异常客户ids"`
+	UnusualRate     string `description:"异常率"`
+}
+
+// SummaryUnusualRenewRecordNum
+// @Description: 续约异常客户汇总数据
+type SummaryUnusualRenewRecordNum struct {
+	UnusualRenewNum int    `description:"续约异常客户数"`
+	UnusualRenewIds string `description:"续约异常客户ids"`
+	UnusualRate     string `description:"异常率"`
+}

+ 175 - 0
services/statistic_report/unusual_renew_company.go

@@ -0,0 +1,175 @@
+package statistic_report
+
+import (
+	"fmt"
+	"hongze/hz_crm_api/models/company"
+	"hongze/hz_crm_api/models/contract"
+	"hongze/hz_crm_api/utils"
+	"strings"
+	"time"
+)
+
+type UnusualCompanyRenewDataMap struct {
+	UnusualRenewMap    map[int]int    `description:"续约异常客户数"`
+	UnusualRenewIdMap  map[int]string `description:"续约异常客户ids"`
+	UnusualRenewTotal  int            `description:"续约异常客户总数(去重)"`
+	FormalCompanyTotal int            `description:"当前正常客户总数(去重)"`
+	StartDate          string         `description:"开始日期"`
+	EndDate            string         `description:"开始日期"`
+}
+
+// GetUnusualRenewWeekDataNum 周度数据
+func GetUnusualRenewWeekDataNum(nowWeekMonday time.Time, productId, dataNum int) (adminDataList []UnusualCompanyRenewDataMap, firstDate time.Time, err error) {
+	nowWeekSunday := nowWeekMonday.AddDate(0, 0, 7).Add(-1 * time.Second) //本周周日
+
+	chanList := make([]chan UnusualCompanyRenewDataMap, 0)
+	for i := 0; i < dataNum; i++ {
+		tmpCh := make(chan UnusualCompanyRenewDataMap, 0)
+		chanList = append(chanList, tmpCh)
+
+		lastWeekMonday := nowWeekMonday.AddDate(0, 0, -7*i)
+		lastWeekSunday := nowWeekSunday.AddDate(0, 0, -7*i)
+
+		// 第一个开始日期
+		firstDate = lastWeekMonday
+		go getUnusualRenewSectionData(productId, lastWeekMonday, lastWeekSunday, tmpCh)
+	}
+
+	adminDataList = make([]UnusualCompanyRenewDataMap, 0)
+	for _, vChan := range chanList {
+		var weekUnusualCompanyRenewDataMap UnusualCompanyRenewDataMap
+		weekUnusualCompanyRenewDataMap = <-vChan
+		close(vChan)
+		adminDataList = append(adminDataList, weekUnusualCompanyRenewDataMap)
+	}
+
+	return
+}
+
+// GetUnusualRenewMonthDataNum 月度数据
+func GetUnusualRenewMonthDataNum(nowMonthFirstDay time.Time, productId, dataNum int) (adminDataList []UnusualCompanyRenewDataMap, firstDate time.Time, err error) { //三个协程返回
+	//nowMonthLastDay := nowMonthFirstDay.AddDate(0, 1, 0).Add(-1 * time.Second) //本月最后一天
+
+	chanList := make([]chan UnusualCompanyRenewDataMap, 0)
+
+	for i := 0; i < dataNum; i++ {
+		tmpCh := make(chan UnusualCompanyRenewDataMap, 0)
+		chanList = append(chanList, tmpCh)
+
+		lastMonthFirstDay := nowMonthFirstDay.AddDate(0, -1*i, 0)                          //上个月第一天
+		lastMonthLastDay := nowMonthFirstDay.AddDate(0, -1*(i-1), 0).Add(-1 * time.Second) //上个月最后一天
+
+		// 第一个开始日期
+		firstDate = lastMonthFirstDay
+		go getUnusualRenewSectionData(productId, lastMonthFirstDay, lastMonthLastDay, tmpCh)
+	}
+
+	adminDataList = make([]UnusualCompanyRenewDataMap, 0)
+	for _, vChan := range chanList {
+		var weekUnusualCompanyRenewDataMap UnusualCompanyRenewDataMap
+		weekUnusualCompanyRenewDataMap = <-vChan
+		close(vChan)
+		adminDataList = append(adminDataList, weekUnusualCompanyRenewDataMap)
+	}
+
+	return
+}
+
+// GetUnusualRenewTimeIntervalData 区间数据
+func GetUnusualRenewTimeIntervalData(productId int, startDate, endDate string) (adminDataMapList []UnusualCompanyRenewDataMap, firstDate time.Time, err error) { //三个协程返回
+	startDateTimer, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+	endDateTimer, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
+	endDateTimer = endDateTimer.AddDate(0, 0, 1).Add(-1 * time.Second) //本月最后一天
+
+	//最早的一天
+	firstDate = startDateTimer
+
+	ch1 := make(chan UnusualCompanyRenewDataMap, 0)
+
+	go getUnusualRenewSectionData(productId, startDateTimer, endDateTimer, ch1)
+
+	var adminDataMap UnusualCompanyRenewDataMap
+
+	adminDataMap = <-ch1
+	close(ch1)
+
+	adminDataMapList = make([]UnusualCompanyRenewDataMap, 0)
+	adminDataMapList = append(adminDataMapList, adminDataMap)
+	return
+}
+
+// getUnusualRenewSectionData 获取周期数据
+func getUnusualRenewSectionData(productId int, startDate, endDate time.Time, ch chan UnusualCompanyRenewDataMap) (adminDataMap UnusualCompanyRenewDataMap, err error) {
+	defer func() {
+		ch <- adminDataMap
+	}()
+	unusualRenewMap := make(map[int]int)                 // 续约异常客户
+	unusualRenewCompanyIdMap := make(map[int]string)     // 续约异常客户id
+	var unusualRenewCompanyTotal, formalCompanyTotal int //续约异常客户总数  , 当前正式的客户数
+
+	// 当前正式的客户数
+	formalCompanyTotal, err = contract.GetCountFormalCompany(endDate, productId)
+	if err != nil {
+		utils.FileLog.Error(err.Error())
+		return
+	}
+
+	// 续约异常
+	{
+
+		data, tmpErr := company.GetUnusualRenewCompanyList(startDate, endDate, productId)
+
+		if tmpErr != nil {
+			err = tmpErr
+			utils.FileLog.Error(err.Error())
+			return
+		}
+
+		unusualRenewCompanyIdListMap := make(map[int][]string) // 续约异常客户
+		for _, v := range data {
+			tmp, ok := unusualRenewMap[v.SellerId]
+			if !ok {
+				tmp = 0
+			}
+			unusualRenewMap[v.SellerId] = tmp + 1
+
+			// 共享人id不为空,且不是所属销售
+			if v.ShareSellerId > 0 && v.ShareSellerId != v.SellerId {
+				tmp2, ok := unusualRenewMap[v.ShareSellerId]
+				if !ok {
+					tmp = 0
+				}
+				unusualRenewMap[v.ShareSellerId] = tmp2 + 1
+			}
+
+			// 客户id
+			tmpCompanyIdList, ok := unusualRenewCompanyIdListMap[v.SellerId]
+			if !ok {
+				tmpCompanyIdList = make([]string, 0)
+			}
+			unusualRenewCompanyIdListMap[v.SellerId] = append(tmpCompanyIdList, fmt.Sprint(v.CompanyId))
+
+			tmpCompanyIdList2, ok := unusualRenewCompanyIdListMap[v.ShareSellerId]
+			if !ok {
+				tmpCompanyIdList2 = make([]string, 0)
+			}
+			unusualRenewCompanyIdListMap[v.ShareSellerId] = append(tmpCompanyIdList2, fmt.Sprint(v.CompanyId))
+
+			unusualRenewCompanyTotal++
+		}
+
+		for sellerId, tmpCompanyIdList := range unusualRenewCompanyIdListMap {
+			unusualRenewCompanyIdMap[sellerId] = strings.Join(tmpCompanyIdList, ",")
+		}
+	}
+
+	adminDataMap = UnusualCompanyRenewDataMap{
+		UnusualRenewMap:    unusualRenewMap,
+		UnusualRenewIdMap:  unusualRenewCompanyIdMap,
+		UnusualRenewTotal:  unusualRenewCompanyTotal,
+		FormalCompanyTotal: formalCompanyTotal,
+		StartDate:          startDate.Format(utils.FormatDate),
+		EndDate:            endDate.Format(utils.FormatDate),
+	}
+	return
+}