Explorar o código

Merge branch 'crm/14.6' into debug

# Conflicts:
#	models/company_product.go
Roc hai 1 ano
pai
achega
0746c2fbed

+ 19 - 2
models/company_contract/company_contract.go

@@ -26,12 +26,12 @@ type CompanyContract struct {
 	RaiPackageType    int       `description:"权益套餐类型: 0-无; 1-70w大套餐; 2-45w大套餐"`
 }
 
-// 通过开始日期获取当天开始的合同列表
+// GetStartContractListByStartDate 通过开始日期获取当天开始的合同列表
 func GetStartContractListByStartDate(startDate string) (total int64, list []*CompanyContract, err error) {
 	o := orm.NewOrm()
 	sql := "SELECT * FROM company_contract where start_date = ? AND status = 1 "
 	total, err = o.Raw(sql, startDate).QueryRows(&list)
-	return
+
 	return
 }
 
@@ -48,6 +48,23 @@ type CompanyContractPermission struct {
 	ModifyTime        time.Time `description:"修改时间"`
 }
 
+// GetContractListByEndDate 通过结束日期获取当天结束的合同列表
+func GetContractListByEndDate(endDate string) (total int64, list []*CompanyContract, err error) {
+	o := orm.NewOrm()
+	sql := "SELECT * FROM company_contract where end_date = ? AND status = 1 "
+	total, err = o.Raw(sql, endDate).QueryRows(&list)
+
+	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
+}
 
 // 获取合同对应的权限列表
 func GetCompanyContractPermissionList(condition string, pars []interface{}) (items []*CompanyContractPermission, err error) {

+ 88 - 4
models/company_product.go

@@ -24,7 +24,7 @@ type CompanyOperationRecord struct {
 	Status          string    `description:"状态"`
 }
 
-//新增操作记录
+// 新增操作记录
 func AddCompanyOperationRecord(item *CompanyOperationRecord) (lastId int64, err error) {
 	o := orm.NewOrm()
 	lastId, err = o.Insert(item)
@@ -104,7 +104,7 @@ func CompanyLoss(companyId, productId int) (err error) {
 	return
 }
 
-//正式转试用
+// 正式转试用
 func CompanyTryOut(companyId, productId int) (companyReportPermissionList []*CompanyReportPermission, err error) {
 	o := orm.NewOrm()
 	startDate := time.Now().Format(utils.FormatDate)
@@ -193,7 +193,7 @@ type CompanyProduct struct {
 	TryStage         int       `description:"试用客户子标签:1未分类、2  推进、3 跟踪、4 预备"`
 }
 
-//获取产品详情
+// GetCompanyProduct 获取产品详情
 func GetCompanyProduct(companyId int, productId int) (companyProduct *CompanyProduct, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT *
@@ -202,7 +202,7 @@ func GetCompanyProduct(companyId int, productId int) (companyProduct *CompanyPro
 	return
 }
 
-//新增客户产品
+// 新增客户产品
 func AddCompanyProduct(item *CompanyProduct) (newId int64, err error) {
 	o := orm.NewOrm()
 	newId, err = o.Insert(item)
@@ -285,3 +285,87 @@ func UpdateCompanyProductIsSigningById(companyId, productId int) (err error) {
 	_, err = o.Raw(sql, companyId, productId).Exec()
 	return
 }
+
+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"`
+}
+
+// GetCompanyProductItemListByCompanyIdList
+// @Description: 根据客户ID列表获取客户产品列表
+// @author: Roc
+// @datetime 2023-12-07 11:06:58
+// @param companyIdList []int
+// @param productId int
+// @return items []*CompanyProductItem
+// @return err error
+func GetCompanyProductItemListByCompanyIdList(companyIdList []int, productId int) (items []*CompanyProductItem, err error) {
+	num := len(companyIdList)
+	if num <= 0 {
+		return
+	}
+	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 in (` + utils.GetOrmInReplace(num) + `) AND a.product_id = ? `
+	_, err = o.Raw(sql, companyIdList, productId).QueryRows(&items)
+
+	return
+}
+
+// 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
+}

+ 78 - 0
models/company_renewal_record.go

@@ -0,0 +1,78 @@
+package models
+
+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
+}
+
+// MultiAddCompanyRenewalRecord
+// @Description: 批量添加续约用户记录
+// @author: Roc
+// @datetime 2023-12-07 11:17:26
+// @param list []*CompanyRenewalRecord
+// @return err error
+func MultiAddCompanyRenewalRecord(list []*CompanyRenewalRecord) (err error) {
+	num := len(list)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(num, 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
+}

+ 2 - 2
models/db.go

@@ -134,7 +134,8 @@ func initCompany() {
 		new(CompanyEndDate),
 		new(CompanyProductUpdateLog), //客户产品状态变更表
 		new(CompanyViewStatistics),
-		new(CompanyRemindRecord), // 客户提醒记录
+		new(CompanyRemindRecord),  // 客户提醒记录
+		new(CompanyRenewalRecord), // 客户续约状态记录表
 	)
 }
 
@@ -213,7 +214,6 @@ func initCygx() {
 		new(cygx.CygxAllocationCompanyContractLog),
 		new(cygx.CygxAllocationCompanyContractPermission),
 		new(cygx.CygxAllocationCompanyContractPermissionLog),
-
 	)
 }
 

+ 139 - 1
services/company_contract/company_contract.go

@@ -15,7 +15,7 @@ import (
 	"time"
 )
 
-// 合同处理
+// HandleCompanyContract 合同处理
 func HandleCompanyContract(cont context.Context) (err error) {
 	defer func() {
 		if err != nil {
@@ -83,6 +83,12 @@ func HandleCompanyContract(cont context.Context) (err error) {
 				errorList = append(errorList, fmt.Sprint("合同id:", v.CompanyContractId, ";TryOutToFormal Err: ", e.Error()))
 			}
 		case 5, 6:
+			// 续约异常客户记录
+			tmpErr := contactHandleCompanyRenewalRecord(v, today)
+			if tmpErr != nil {
+				errorList = append(errorList, tmpErr.Error())
+			}
+
 			e := company.ApplyServiceUpdate(v.CompanyId, v.ProductId, utils.AdminId, v.CompanyContractId, v.StartDate, v.EndDate, utils.RealName, v.ProductName, v.PackageType, v.RaiPackageType)
 			if e != nil {
 				errorList = append(errorList, fmt.Sprint("合同id:", v.CompanyContractId, ";ApplyServiceUpdate Err: ", e.Error()))
@@ -140,3 +146,135 @@ func HandleCompanyContract(cont context.Context) (err error) {
 	}
 	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_contract.CompanyContract, day string) (err error) {
+	// 判断合同类型是否是续约合同,如果不是的话,就不往下走了
+	if contractInfo.ContractType != `续约合同` {
+		return
+	}
+
+	// 获取早于当前合同结束日期的上一份合同
+	lastContract, tmpErr := company_contract.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 := models.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 := &models.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
+}
+
+// HandleCompanyRenewalRecord
+// @Description: 处理续约客户的问题
+// @author: Roc
+// @datetime 2023-12-07 10:56:24
+// @param cont context.Context
+// @return err error
+func HandleCompanyRenewalRecord(cont context.Context) (err error) {
+	defer func() {
+		if err != nil {
+			//fmt.Println("合同处理 ErrMsg:"+err.Error())
+			//go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "合同处理 ErrMsg:"+err.Error(), utils.EmailSendToUsers)
+			go alarm_msg.SendAlarmMsg("合同处理 ErrMsg:"+err.Error(), 3)
+		}
+	}()
+	// 需求是60个自然后未续约的客户,所以要减去61天
+	endDate := time.Now().AddDate(0, 0, -61).Format(utils.FormatDate)
+	total, list, err := company_contract.GetContractListByEndDate(endDate)
+	if err != nil {
+		utils.FileLog.Info("HandleCompanyRenewalRecord GetStartContractListByEndDate Err:%s" + err.Error())
+		return
+	}
+	fmt.Sprintln("总共d%条数据待处理", total)
+	if total <= 0 {
+		return
+	}
+	companyIdList := make([]int, 0)
+	for _, companyInfo := range list {
+		companyIdList = append(companyIdList, companyInfo.CompanyId)
+	}
+
+	companyList, err := models.GetCompanyProductItemListByCompanyIdList(companyIdList, 1)
+	if err != nil {
+		utils.FileLog.Info("HandleCompanyRenewalRecord GetCompanyProductListByCompanyIdList Err:%s" + err.Error())
+		return
+	}
+
+	addList := make([]*models.CompanyRenewalRecord, 0)
+	for _, v := range companyList {
+		if v.Status != "正式" {
+			var shareSellerId int
+			var shareSellerName string
+			if v.IsShare == 1 {
+				shareSellerId = v.ShareSellerId
+				shareSellerName = v.ShareSeller
+			}
+			addList = append(addList, &models.CompanyRenewalRecord{
+				Id:              0,
+				CompanyId:       v.CompanyId,
+				ProductId:       v.ProductId,
+				Source:          1,
+				SellerId:        v.SellerId,
+				SellerName:      v.SellerName,
+				ShareSellerId:   shareSellerId,
+				ShareSellerName: shareSellerName,
+				CreateTime:      time.Now(),
+				ModifyTime:      time.Now(),
+			})
+		}
+	}
+
+	if len(addList) > 0 {
+		err = models.MultiAddCompanyRenewalRecord(addList)
+	}
+
+	return
+}

+ 4 - 0
services/task.go

@@ -51,6 +51,10 @@ func Task() {
 	handleCompanyContract := task.NewTask("handleCompanyContract", "0 1 2 * * *", company_contract.HandleCompanyContract)
 	task.AddTask("每日定时合同处理", handleCompanyContract)
 
+	// 每日续约异常客户信息处理
+	handleCompanyRenewalRecord := task.NewTask("handleCompanyContract", "0 5 2 * * *", company_contract.HandleCompanyRenewalRecord)
+	task.AddTask("每日续约异常客户信息处理", handleCompanyRenewalRecord)
+
 	//正式->试用
 	companyTryOut := task.NewTask("companyTryOut", "0 5 2 * * *", CompanyTryOut)
 	task.AddTask("正式->试用", companyTryOut)