Browse Source

test 销售统计、财务列表导入适应2.0版本

hsun 2 years ago
parent
commit
db27296faf

+ 1 - 1
controller/census/invoice_payment.go

@@ -266,7 +266,7 @@ func ExportInvoicePaymentCensusList(c *gin.Context, list []*fms.InvoicePaymentCe
 	titleRow := sheet.AddRow()
 	for i := range rowTitle {
 		v := titleRow.AddCell()
-		v.SetValue(rowTitle[i])
+		v.SetString(rowTitle[i])
 		v.SetStyle(style)
 	}
 

+ 378 - 0
controller/census/seller.go

@@ -0,0 +1,378 @@
+package census
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/go-playground/validator/v10"
+	"github.com/shopspring/decimal"
+	"github.com/tealeg/xlsx"
+	"hongze/fms_api/controller/resp"
+	"hongze/fms_api/global"
+	"hongze/fms_api/models/base"
+	"hongze/fms_api/models/crm"
+	"hongze/fms_api/models/fms"
+	crmService "hongze/fms_api/services/crm"
+	"hongze/fms_api/utils"
+	"net/http"
+	"time"
+)
+
+// SellerController 销售统计
+type SellerController struct{}
+
+// InvoiceGroupList
+// @Title 销售组开票统计列表
+// @Description 销售组开票统计列表
+// @Param   StartDate		query	string	false	"开始日期"
+// @Param   EndDate			query	string	false	"结束日期"
+// @Param   SortField		query	int		false	"排序字段: 1-开票金额; 2-组别占比"
+// @Param   SortType		query	int		false	"排序方式: 1-正序; 2-倒序"
+// @Param   IsExport		query	int		false	"是否导出: 0-否; 1-是"
+// @Success 200 {object} fms.CensusSellerGroupInvoiceItem
+// @router /census/seller/group_invoice_list [get]
+func (ct *SellerController) GroupInvoiceList(c *gin.Context) {
+	var req fms.CensusSellerGroupInvoiceListReq
+	if e := c.BindQuery(&req); e != nil {
+		err, ok := e.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+e.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", err.Translate(global.Trans), c)
+		return
+	}
+
+	outCond := ` department_id = %d AND parent_id = 0 `
+	outCond = fmt.Sprintf(outCond, crm.SellerDepartmentId)
+	cond := ` invoice_type = %d AND is_deleted = 0 AND seller_group_id != 0 `
+	cond = fmt.Sprintf(cond, fms.ContractInvoiceTypeMake)
+	pars := make([]interface{}, 0)
+	// 开票日期
+	if req.StartDate != "" && req.EndDate != "" {
+		st := fmt.Sprint(req.StartDate, " 00:00:00")
+		ed := fmt.Sprint(req.EndDate, " 23:59:59")
+		cond += ` AND (invoice_time BETWEEN '%s' AND '%s')`
+		cond = fmt.Sprintf(cond, st, ed)
+	}
+
+	page := new(base.Page)
+	page.SetPageSize(req.PageSize)
+	page.SetCurrent(req.Current)
+	// 排序, 默认开票金额倒序
+	sortFieldMap := map[int]string{0: "invoice_amount", 1: "invoice_amount", 2: "group_rate"}
+	sortTypeMap := map[int]bool{0: false, 1: true, 2: false}
+	page.AddOrderItem(base.OrderItem{Column: sortFieldMap[req.SortField], Asc: sortTypeMap[req.SortType]})
+	if req.IsExport == 1 {
+		page.SetPageSize(10000)
+		page.SetCurrent(1)
+	}
+
+	// 查询开票金额总和(减少子查询)
+	invOB := new(fms.ContractInvoice)
+	sumCond := cond
+	sumPars := make([]interface{}, 0)
+	invSum, e := invOB.Sum("amount", sumCond, sumPars)
+	if e != nil {
+		resp.FailMsg("获取失败", "获取开票金额总和失败, Err: "+e.Error(), c)
+		return
+	}
+
+	// 查询列表
+	groupOB := new(crm.SysGroup)
+	totalCond := outCond
+	totalPars := make([]interface{}, 0)
+	total, e := groupOB.Count(totalCond, totalPars)
+	if e != nil {
+		resp.FailMsg("获取失败", "获取销售组开票统计列表总数失败, Err: "+e.Error(), c)
+		return
+	}
+	list, e := fms.GetCensusSellerGroupInvoicePageList(page, cond, outCond, pars, invSum)
+	if e != nil {
+		resp.FailMsg("获取失败", "获取销售组开票统计列表失败, Err: "+e.Error(), c)
+		return
+	}
+
+	// 处理百分比, 乘100并保留两位小数
+	mulNum := decimal.NewFromFloat(100)
+	for i := range list {
+		d := decimal.NewFromFloat(list[i].GroupRate)
+		d = d.Mul(mulNum).Round(2)
+		a, _ := d.Float64()
+		list[i].GroupRate = a
+	}
+
+	// 是否导出
+	if req.IsExport == 1 {
+		ExportGroupInvoiceList(c, list, req)
+		return
+	}
+	page.SetTotal(total)
+	baseData := new(base.BaseData)
+	baseData.SetPage(page)
+	baseData.SetList(list)
+	resp.OkData("获取成功", baseData, c)
+}
+
+// ExportGroupInvoiceList 导出销售组开票统计列表
+func ExportGroupInvoiceList(c *gin.Context, list []*fms.CensusSellerGroupInvoiceItem, req fms.CensusSellerGroupInvoiceListReq) {
+	// 生成Excel文件
+	xlsxFile := xlsx.NewFile()
+	style := xlsx.NewStyle()
+	alignment := xlsx.Alignment{
+		Horizontal: "center",
+		Vertical:   "center",
+		WrapText:   true,
+	}
+	style.Alignment = alignment
+	style.ApplyAlignment = true
+
+	sheetName := "销售组开票统计"
+	sheet, err := xlsxFile.AddSheet(sheetName)
+	if err != nil {
+		resp.FailData("新增Sheet失败", "Err:"+err.Error(), c)
+		return
+	}
+
+	// 存在筛选则前两行显示时间信息
+	if req.StartDate != "" && req.EndDate != "" {
+		timeData := fmt.Sprintf("时间:%s至%s", req.StartDate, req.EndDate)
+		rowA := sheet.AddRow()
+		cellAA := rowA.AddCell()
+		cellAA.SetString("销售统计表")
+		cellAA.SetStyle(style)
+		rowB := sheet.AddRow()
+		rowB.AddCell().SetString(timeData)
+		// 第三行空出
+		sheet.AddRow()
+	}
+
+	// 数据表头
+	rowTitle := []string{"排名", "销售组别", "开票金额", "组别占比"}
+	titleRow := sheet.AddRow()
+	for i := range rowTitle {
+		v := titleRow.AddCell()
+		v.SetString(rowTitle[i])
+		v.SetStyle(style)
+	}
+
+	// 填充数据
+	for k, v := range list {
+		dataRow := sheet.AddRow()
+		dataRow.AddCell().SetString(fmt.Sprint(k + 1))            // 排名
+		dataRow.AddCell().SetString(v.GroupName)                  // 销售组别
+		dataRow.AddCell().SetString(fmt.Sprint(v.InvoiceAmount))  // 开票金额
+		dataRow.AddCell().SetString(fmt.Sprint(v.GroupRate, "%")) // 组别占比
+	}
+
+	// 输出文件
+	var buffer bytes.Buffer
+	_ = xlsxFile.Write(&buffer)
+	content := bytes.NewReader(buffer.Bytes())
+	randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
+	fileName := sheetName + randStr + ".xlsx"
+
+	c.Writer.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName))
+	c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
+	http.ServeContent(c.Writer, c.Request, fileName, time.Now(), content)
+}
+
+// InvoiceList
+// @Title 销售开票统计列表
+// @Description 销售开票统计列表
+// @Param   GroupId			query	int		false	"组别ID"
+// @Param   StartDate		query	string	false	"开始日期"
+// @Param   EndDate			query	string	false	"结束日期"
+// @Param   SortField		query	int		false	"排序字段: 1-开票金额; 2-组别占比; 3-全员占比"
+// @Param   SortType		query	int		false	"排序方式: 1-正序; 2-倒序"
+// @Param   IsExport		query	int		false	"是否导出: 0-否; 1-是"
+// @Success 200 {object} fms.CensusSellerInvoiceListReq
+// @router /census/seller/invoice_list [get]
+func (ct *SellerController) InvoiceList(c *gin.Context) {
+	var req fms.CensusSellerInvoiceListReq
+	if e := c.BindQuery(&req); e != nil {
+		err, ok := e.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+e.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", err.Translate(global.Trans), c)
+		return
+	}
+
+	pars := make([]interface{}, 0)
+	outCond := ` a.department_id = %d AND a.enabled = 1 `
+	outCond = fmt.Sprintf(outCond, crm.SellerDepartmentId)
+	totalCond := ` department_id = %d AND enabled = 1 `
+	totalCond = fmt.Sprintf(totalCond, crm.SellerDepartmentId)
+	totalPars := make([]interface{}, 0)
+	if req.GroupId > 0 {
+		// 筛选组别时, 查询当前组别的下级组(因为admin表存的group_id, 有三级的存的是子ID, 只有二级的存的才是父ID =_=!)
+		groupCond := `parent_id = ?`
+		groupPars := make([]interface{}, 0)
+		groupPars = append(groupPars, req.GroupId)
+		groupOB := new(crm.SysGroup)
+		groupList, e := groupOB.List(groupCond, groupPars)
+		if e != nil {
+			resp.FailMsg("获取失败", "获取组别下级组列表失败, Err: "+e.Error(), c)
+			return
+		}
+		groupIds := make([]int, 0)
+		groupIds = append(groupIds, req.GroupId)
+		for i := range groupList {
+			groupIds = append(groupIds, groupList[i].GroupId)
+		}
+		outCond += ` AND a.group_id IN (?) `
+		pars = append(pars, groupIds)
+		totalCond += ` AND group_id IN (?) `
+		totalPars = append(totalPars, groupIds)
+	}
+	sumCond := ` invoice_type = ? AND is_deleted = 0 AND seller_id != 0 `
+	sumPars := make([]interface{}, 0)
+	sumPars = append(sumPars, fms.ContractInvoiceTypeMake)
+	cond := ` c.invoice_type = %d AND c.is_deleted = 0 AND c.seller_id != 0 `
+	cond = fmt.Sprintf(cond, fms.ContractInvoiceTypeMake)
+	// 开票日期
+	if req.StartDate != "" && req.EndDate != "" {
+		st := fmt.Sprint(req.StartDate, " 00:00:00")
+		ed := fmt.Sprint(req.EndDate, " 23:59:59")
+		cond += ` AND (c.invoice_time BETWEEN '%s' AND '%s')`
+		cond = fmt.Sprintf(cond, st, ed)
+		sumCond += ` AND (invoice_time BETWEEN ? AND ?)`
+		sumPars = append(sumPars, st, ed)
+	}
+
+	page := new(base.Page)
+	page.SetPageSize(req.PageSize)
+	page.SetCurrent(req.Current)
+	// 排序, 默认开票金额倒序
+	sortFieldMap := map[int]string{0: "invoice_amount", 1: "invoice_amount", 2: "group_rate", 3: "seller_rate"}
+	sortTypeMap := map[int]bool{0: false, 1: true, 2: false}
+	page.AddOrderItem(base.OrderItem{Column: sortFieldMap[req.SortField], Asc: sortTypeMap[req.SortType]})
+	if req.IsExport == 1 {
+		page.SetPageSize(10000)
+		page.SetCurrent(1)
+	}
+
+	// 查询开票金额总和(减少子查询)
+	invOB := new(fms.ContractInvoice)
+	invSum, e := invOB.Sum("amount", sumCond, sumPars)
+	if e != nil {
+		resp.FailMsg("获取失败", "获取开票金额总和失败, Err: "+e.Error(), c)
+		return
+	}
+
+	// 查询列表
+	adminOB := new(crm.Admin)
+	total, e := adminOB.Count(totalCond, totalPars)
+	if e != nil {
+		resp.FailMsg("获取失败", "获取销售开票统计列表总数失败, Err: "+e.Error(), c)
+		return
+	}
+	list, e := fms.GetCensusSellerInvoicePageList(page, cond, outCond, pars, invSum)
+	if e != nil {
+		resp.FailMsg("获取失败", "获取销售开票统计列表失败, Err: "+e.Error(), c)
+		return
+	}
+
+	// 分组信息, list的groupId可能是三级的ID, 要转为对应的二级
+	groupMap, e := crmService.GetSellerTeamGroupMap()
+	if e != nil {
+		resp.FailMsg("获取失败", "获取组别对应信息失败, Err: "+e.Error(), c)
+		return
+	}
+
+	mulNum := decimal.NewFromFloat(100)
+	for i := range list {
+		g := groupMap[list[i].GroupId]
+		if g != nil {
+			list[i].GroupId = g.GroupId
+			list[i].GroupName = g.GroupName
+		}
+		// 处理百分比, 乘100并保留两位小数
+		d := decimal.NewFromFloat(list[i].GroupRate)
+		d = d.Mul(mulNum).Round(2)
+		a, _ := d.Float64()
+		list[i].GroupRate = a
+		d2 := decimal.NewFromFloat(list[i].SellerRate)
+		d2 = d2.Mul(mulNum).Round(2)
+		a2, _ := d2.Float64()
+		list[i].SellerRate = a2
+	}
+
+	// 是否导出
+	if req.IsExport == 1 {
+		ExportInvoiceList(c, list, req)
+		return
+	}
+	page.SetTotal(total)
+	baseData := new(base.BaseData)
+	baseData.SetPage(page)
+	baseData.SetList(list)
+	resp.OkData("获取成功", baseData, c)
+}
+
+// ExportInvoiceList 导出销售开票统计列表
+func ExportInvoiceList(c *gin.Context, list []*fms.CensusSellerInvoiceItem, req fms.CensusSellerInvoiceListReq) {
+	// 生成Excel文件
+	xlsxFile := xlsx.NewFile()
+	style := xlsx.NewStyle()
+	alignment := xlsx.Alignment{
+		Horizontal: "center",
+		Vertical:   "center",
+		WrapText:   true,
+	}
+	style.Alignment = alignment
+	style.ApplyAlignment = true
+
+	sheetName := "销售开票统计"
+	sheet, err := xlsxFile.AddSheet(sheetName)
+	if err != nil {
+		resp.FailData("新增Sheet失败", "Err:"+err.Error(), c)
+		return
+	}
+
+	// 存在筛选则前两行显示时间信息
+	if req.StartDate != "" && req.EndDate != "" {
+		timeData := fmt.Sprintf("时间:%s至%s", req.StartDate, req.EndDate)
+		rowA := sheet.AddRow()
+		cellAA := rowA.AddCell()
+		cellAA.SetString("销售统计表")
+		cellAA.SetStyle(style)
+		rowB := sheet.AddRow()
+		rowB.AddCell().SetString(timeData)
+		// 第三行空出
+		sheet.AddRow()
+	}
+
+	// 数据表头
+	rowTitle := []string{"排名", "销售员", "销售组别", "开票金额", "小组占比", "全员占比"}
+	titleRow := sheet.AddRow()
+	for i := range rowTitle {
+		v := titleRow.AddCell()
+		v.SetString(rowTitle[i])
+		v.SetStyle(style)
+	}
+
+	// 填充数据
+	for k, v := range list {
+		dataRow := sheet.AddRow()
+		dataRow.AddCell().SetString(fmt.Sprint(k + 1))             // 排名
+		dataRow.AddCell().SetString(v.SellerName)                  // 销售员
+		dataRow.AddCell().SetString(v.GroupName)                   // 销售组别
+		dataRow.AddCell().SetString(fmt.Sprint(v.InvoiceAmount))   // 开票金额
+		dataRow.AddCell().SetString(fmt.Sprint(v.GroupRate, "%"))  // 小组占比
+		dataRow.AddCell().SetString(fmt.Sprint(v.SellerRate, "%")) // 全员占比
+	}
+
+	// 输出文件
+	var buffer bytes.Buffer
+	_ = xlsxFile.Write(&buffer)
+	content := bytes.NewReader(buffer.Bytes())
+	randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
+	fileName := sheetName + randStr + ".xlsx"
+
+	c.Writer.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName))
+	c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
+	http.ServeContent(c.Writer, c.Request, fileName, time.Now(), content)
+}

+ 223 - 308
controller/contract/register.go

@@ -1005,14 +1005,7 @@ func (rg *RegisterController) Export(c *gin.Context) {
 	}
 
 	// 生成Excel文件
-	//dir, err := os.Executable()
-	//exPath := filepath.Dir(dir)
-	//filePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
 	xlsxFile := xlsx.NewFile()
-	//if err != nil {
-	//	resp.FailData("生成文件失败", "Err:"+err.Error(), c)
-	//	return
-	//}
 	style := xlsx.NewStyle()
 	alignment := xlsx.Alignment{
 		Horizontal: "center",
@@ -1022,53 +1015,53 @@ func (rg *RegisterController) Export(c *gin.Context) {
 	style.Alignment = alignment
 	style.ApplyAlignment = true
 
-	sheet, err := xlsxFile.AddSheet("合同登记")
+	sheetName := "财务列表"
+	sheet, err := xlsxFile.AddSheet(sheetName)
 	if err != nil {
 		resp.FailData("新增Sheet失败", "Err:"+err.Error(), c)
 		return
 	}
-	//_ = sheet.SetColWidth(0, 0, 60)
-	//_ = sheet.SetColWidth(4, 10, 60)
+
 	// 1行表头
 	titleRow := sheet.AddRow()
 	titleRow.SetHeight(40)
 	// 1行1列-右合并两格
 	cell1 := titleRow.AddCell()
-	cell1.HMerge = 2
-	cell1.SetValue("FICC客户签约表  2022")
+	cell1.HMerge = 3
+	cell1.SetString("FICC客户签约表  2022")
 	cell1.SetStyle(style)
 	// 右增两列空白格用于第一列合并, 否则后续单元格合并会有问题
-	titleRow.AddCell().SetValue("")
-	titleRow.AddCell().SetValue("")
+	titleRow.AddCell().SetString("")
+	titleRow.AddCell().SetString("")
+	titleRow.AddCell().SetString("")
 
 	// 1行2列
 	cell2 := titleRow.AddCell()
-	cell2.SetValue("FICC大套餐")
+	cell2.SetString("FICC大套餐")
 	cell2.SetStyle(style)
 
 	// 1行3列-右合并小套餐数
 	if permissionLen >= 1 {
 		cell3 := titleRow.AddCell()
 		cell3.HMerge = permissionLen - 1
-		cell3.SetValue("FICC小套餐")
+		cell3.SetString("FICC小套餐")
 		cell3.SetStyle(style)
 		// 同上右增单元格小套餐数-1的空白单元格用于合并
 		for i := 0; i < permissionLen-1; i++ {
-			titleRow.AddCell().SetValue("")
+			titleRow.AddCell().SetString("")
 		}
 	}
-	cell4 := titleRow.AddCell()
-	cell4.SetValue("市场策略")
-	cell4.SetStyle(style)
-	cell5 := titleRow.AddCell()
-	cell5.SetValue("财富管理")
-	cell5.SetStyle(style)
+	for i := range otherService {
+		cellOther := titleRow.AddCell()
+		cellOther.SetString(otherService[i].Title)
+		cellOther.SetStyle(style)
+	}
 
 	// 第二行表头
 	titleRow2 := sheet.AddRow()
 	titleRow2.SetHeight(60)
 	row2Title := make([]string, 0)
-	row2Title = append(row2Title, "客户名称", "续约-0\n新增-1", "销售", "FICC大套餐")
+	row2Title = append(row2Title, "客户名称", "新客户\n0-是\n1-否", "合同类型\n续约-0\n新增-1\n代付-2\n补充协议-3", "销售", "FICC大套餐")
 	for i := range permissionList {
 		row2Title = append(row2Title, permissionList[i].PermissionName)
 	}
@@ -1077,40 +1070,38 @@ func (rg *RegisterController) Export(c *gin.Context) {
 	for i := range otherService {
 		row2Title = append(row2Title, otherService[i].Title)
 	}
-	row2Title = append(row2Title, "套餐备注", "开始时间", "到期时间", "2022年合同金额", "约定付款时间", "签订日", "签订月",
-		"合同状态", "合同编号", "备注")
+	row2Title = append(row2Title, "套餐备注", "开始时间", "到期时间", "2022年合同金额", "约定付款时间", "签订日", "合同状态",
+		"合同编号", "合规备注")
 
 	// 设置表头
 	for i := range row2Title {
 		v := titleRow2.AddCell()
-		v.SetValue(row2Title[i])
+		v.SetString(row2Title[i])
 		v.SetStyle(style)
 	}
 
 	// 第二行表头-开票/收款(动态添加)
+	invoiceTitle := []string{"开票日", "开票金额", "销售", "备注"}
 	for i := 0; i < maxInvoice; i++ {
 		n := i + 1
-		c1 := titleRow2.AddCell()
-		t1 := fmt.Sprintf("%s%d", "开票日", n)
-		c1.SetValue(t1)
-		c1.SetStyle(style)
-		c2 := titleRow2.AddCell()
-		t2 := fmt.Sprintf("%s%d", "开票金额", n)
-		c2.SetValue(t2)
-		c2.SetStyle(style)
-		row2Title = append(row2Title, t1, t2)
+		for ii := range invoiceTitle {
+			c := titleRow2.AddCell()
+			t := fmt.Sprintf("%s%d", invoiceTitle[ii], n)
+			c.SetString(t)
+			c.SetStyle(style)
+			row2Title = append(row2Title, t)
+		}
 	}
+	paymentTitle := []string{"到款日", "到款金额", "备注"}
 	for i := 0; i < maxPayment; i++ {
 		n := i + 1
-		c1 := titleRow2.AddCell()
-		t1 := fmt.Sprintf("%s%d", "收款日", n)
-		c1.SetValue(t1)
-		c1.SetStyle(style)
-		c2 := titleRow2.AddCell()
-		t2 := fmt.Sprintf("%s%d", "收款金额", n)
-		c2.SetValue(t2)
-		c2.SetStyle(style)
-		row2Title = append(row2Title, t1, t2)
+		for ii := range paymentTitle {
+			c := titleRow2.AddCell()
+			t := fmt.Sprintf("%s%d", paymentTitle[ii], n)
+			c.SetString(t)
+			c.SetStyle(style)
+			row2Title = append(row2Title, t)
+		}
 	}
 	// 此处取第二行标题NameKeyMap, 后面的动态匹配
 	row2NameKeyMap := make(map[string]int)
@@ -1118,6 +1109,7 @@ func (rg *RegisterController) Export(c *gin.Context) {
 		row2NameKeyMap[row2Title[i]] = i
 	}
 
+	newCompanyMap := map[int]string{0: "1", 1: "0"}
 	contractTMap := map[int]int{
 		fms.ContractTypeNew:      1,
 		fms.ContractTypeRenew:    0,
@@ -1125,11 +1117,12 @@ func (rg *RegisterController) Export(c *gin.Context) {
 		fms.ContractTypePlus:     3, // 补充协议
 	}
 	for _, v := range list {
-		k := -1
+		k := -1	// 套餐匹配用
 		dataRow := sheet.AddRow()
 		dataRow.SetHeight(20)
-		k += 3
+		k += 4
 		dataRow.AddCell().SetString(v.CompanyName)
+		dataRow.AddCell().SetString(newCompanyMap[v.NewCompany])
 		dataRow.AddCell().SetString(fmt.Sprint(contractTMap[v.ContractType]))
 		dataRow.AddCell().SetString(v.SellerName)
 
@@ -1177,32 +1170,6 @@ func (rg *RegisterController) Export(c *gin.Context) {
 			dataRow.AddCell().SetString(otherCol)
 		}
 
-		// 财富管理/市场策略
-		k += 1
-		col5Name := row2Title[k]
-		col5 := ""
-		if svList != nil && len(svList) > 0 {
-			for isv := range svList {
-				if svList[isv].Title == col5Name {
-					col5 = "是"
-					break
-				}
-			}
-		}
-		dataRow.AddCell().SetString(col5)
-		k += 1
-		col6Name := row2Title[k]
-		col6 := ""
-		if svList != nil && len(svList) > 0 {
-			for isv := range svList {
-				if svList[isv].Title == col6Name {
-					col6 = "是"
-					break
-				}
-			}
-		}
-		dataRow.AddCell().SetString(col6)
-
 		// 其他信息
 		dataRow.AddCell().SetString(v.ServiceRemark)                                     // 套餐备注
 		dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", v.StartDate)) // 开始时间
@@ -1210,10 +1177,9 @@ func (rg *RegisterController) Export(c *gin.Context) {
 		dataRow.AddCell().SetString(fmt.Sprint("¥", v.ContractAmount))                   // 2022年合同金额
 		dataRow.AddCell().SetString(v.AgreedPayTime)                                     // 约定付款时间
 		dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", v.SignDate))  // 签订日
-		dataRow.AddCell().SetString(utils.TimeTransferString("2006/01", v.SignDate))     // 签订月
 		dataRow.AddCell().SetString(fms.ContractStatusKeyNameMap[v.ContractStatus])      // 合同状态
 		dataRow.AddCell().SetString(v.ContractCode)                                      // 合同编号
-		dataRow.AddCell().SetString(v.Remark)                                            // 备注
+		dataRow.AddCell().SetString(v.Remark)                                            // 合规备注
 
 		// 开票/到款信息
 		ivList := invoiceMap[v.ContractRegisterId]
@@ -1223,24 +1189,30 @@ func (rg *RegisterController) Export(c *gin.Context) {
 				if ia < ivListLen {
 					dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", ivList[ia].InvoiceDate)) // 开票日
 					dataRow.AddCell().SetString(fmt.Sprint(ivList[ia].Amount))                                  // 开票金额
+					dataRow.AddCell().SetString(ivList[ia].SellerName)                                          // 销售名称
+					dataRow.AddCell().SetString(ivList[ia].Remark)                                              // 开票备注
 				} else {
 					// 这里要把不够的填充为空
 					dataRow.AddCell().SetString("")
 					dataRow.AddCell().SetString("")
+					dataRow.AddCell().SetString("")
+					dataRow.AddCell().SetString("")
 				}
 			}
 		}
 		pyList := paymentMap[v.ContractRegisterId]
 		pyListLen := len(pyList)
 		if pyList != nil && pyListLen > 0 {
-			for ib := 0; ib < maxInvoice; ib++ {
+			for ib := 0; ib < maxPayment; ib++ {
 				if ib < pyListLen {
 					dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", pyList[ib].InvoiceDate)) // 收款日
 					dataRow.AddCell().SetString(fmt.Sprint(pyList[ib].Amount))                                  // 收款金额
+					dataRow.AddCell().SetString(pyList[ib].Remark)                                              // 收款备注
 				} else {
 					// 已经是最后的几列了其实可以不用填充空, 万一后面要加列此处还是填充上吧
 					dataRow.AddCell().SetString("")
 					dataRow.AddCell().SetString("")
+					dataRow.AddCell().SetString("")
 				}
 			}
 		}
@@ -1250,16 +1222,8 @@ func (rg *RegisterController) Export(c *gin.Context) {
 	var buffer bytes.Buffer
 	_ = xlsxFile.Write(&buffer)
 	content := bytes.NewReader(buffer.Bytes())
-	//err = xlsxFile.Save(filePath)
-	//if err != nil {
-	//	resp.FailData("保存文件失败", "Err:"+err.Error(), c)
-	//	return
-	//}
-	//defer func() {
-	//	_ = os.Remove(filePath)
-	//}()
 	randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
-	fileName := "财务列表_" + randStr + ".xlsx"
+	fileName := sheetName + randStr + ".xlsx"
 
 	c.Writer.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName))
 	c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
@@ -1412,13 +1376,13 @@ func (rg *RegisterController) InvoiceExport(c *gin.Context) {
 	titleRow := sheet.AddRow()
 	titleRow.SetHeight(40)
 	cell1 := titleRow.AddCell()
-	cell1.SetValue("合同编号")
+	cell1.SetString("合同编号")
 	cell1.SetStyle(style)
 	cell2 := titleRow.AddCell()
-	cell2.SetValue("开票金额")
+	cell2.SetString("开票金额")
 	cell2.SetStyle(style)
 	cell3 := titleRow.AddCell()
-	cell3.SetValue("开票日期")
+	cell3.SetString("开票日期")
 	cell3.SetStyle(style)
 
 	for _, v := range list {
@@ -1493,17 +1457,15 @@ func (rg *RegisterController) Import(c *gin.Context) {
 		contractCodeArr = append(contractCodeArr, registerList[i].ContractCode)
 	}
 
-	// 获取所有销售名称Map
-	sellerNameIdMap := make(map[string]int)
-	sellerCond := ``
-	sellerPars := make([]interface{}, 0)
-	sellerList, e := crm.GetCompanySellerByRoleCodes(sellerCond, sellerPars)
+	// 获取所有销售Map
+	sellerList, e := crmService.GetSellerDepartmentListWithGroupAndTeam()
 	if e != nil {
 		resp.FailData("获取销售列表失败", "Err:"+e.Error(), c)
 		return
 	}
+	sellerMap := make(map[string]*crm.SellerAdminWithGroupTeam)
 	for i := range sellerList {
-		sellerNameIdMap[sellerList[i].RealName] = sellerList[i].AdminId
+		sellerMap[sellerList[i].SellerName] = sellerList[i]
 	}
 
 	// 获取品种权限Map
@@ -1535,10 +1497,10 @@ func (rg *RegisterController) Import(c *gin.Context) {
 		serviceTempNameMap[serviceTempList[i].Title] = serviceTempList[i]
 	}
 
-	// TODO:导入开票信息时的销售信息以及导入到款信息时的付款方式信息
-
 	titleMap := make(map[int]string)
 	newIds := make([]int, 0)
+	newCompanyArr := []string{"0", "1"}
+	newCompanyMap := map[string]int{"0": 1, "1": 0}
 	contractTypeArr := []string{"0", "1", "2", "3"}
 	contractTypeMap := map[string]int{
 		"0": fms.ContractTypeRenew,
@@ -1546,6 +1508,19 @@ func (rg *RegisterController) Import(c *gin.Context) {
 		"2": fms.ContractTypeAgentPay,
 		"3": fms.ContractTypePlus,
 	}
+
+	// 更新登记状态
+	defer func() {
+		if len(newIds) > 0 {
+			go func() {
+				for i := range newIds {
+					fmsService.CheckContractRegisterAmount(newIds[i])
+				}
+			}()
+		}
+	}()
+
+	invoiceMax := 3
 	checkDate := time.Date(1900, 1, 1, 0, 0, 0, 0, time.Local)
 	for _, sheet := range xlFile.Sheets {
 		// 遍历行读取
@@ -1558,28 +1533,34 @@ func (rg *RegisterController) Import(c *gin.Context) {
 				for k, cell := range cells {
 					text := cell.String()
 					titleMap[k] = text
-					// 只检验前面部分表头
+					// 只检验前面部分表头, 后面很多动态列
 					if k == 0 {
 						if text != "客户名称" {
-							resp.Fail("匹配失败, 请按模板导入", c)
+							resp.Fail("【客户名称】列名称有误, 请参考模板导入", c)
 							return
 						}
 					}
 					if k == 1 {
-						if !strings.Contains(text, "续约") {
-							resp.Fail("匹配失败, 请按模板导入", c)
+						if !strings.Contains(text, "新客户") {
+							resp.Fail("【新客户】列名称有误, 请参考模板导入", c)
 							return
 						}
 					}
 					if k == 2 {
-						if text != "销售" {
-							resp.Fail("匹配失败, 请按模板导入", c)
+						if !strings.Contains(text, "合同类型") {
+							resp.Fail("【合同类型】列名称有误, 请参考模板导入", c)
 							return
 						}
 					}
 					if k == 3 {
+						if text != "销售" {
+							resp.Fail("【销售】列名称有误, 请参考模板导入", c)
+							return
+						}
+					}
+					if k == 4 {
 						if text != "FICC大套餐" {
-							resp.Fail("匹配失败, 请按模板导入", c)
+							resp.Fail("【FICC大套餐】列名称有误, 请参考模板导入", c)
 							return
 						}
 					}
@@ -1596,14 +1577,15 @@ func (rg *RegisterController) Import(c *gin.Context) {
 				rowServices := make([]*fms.ContractService, 0)
 				// 开票/到款
 				rowInvoices := make([]*fms.ContractInvoice, 0)
-
+				for ir := 0; ir < invoiceMax; ir++ {
+					rowInvoices = append(rowInvoices, new(fms.ContractInvoice))
+				}
+				rowPayments := make([]*fms.ContractInvoice, 0)
+				for ir := 0; ir < invoiceMax; ir++ {
+					rowPayments = append(rowPayments, new(fms.ContractInvoice))
+				}
+				// 小套餐权限
 				rowChartPermissionIdArr := make([]string, 0)
-				rowInvoice1 := new(fms.ContractInvoice)
-				rowInvoice2 := new(fms.ContractInvoice)
-				rowInvoice3 := new(fms.ContractInvoice)
-				rowInvoice4 := new(fms.ContractInvoice)
-				rowInvoice5 := new(fms.ContractInvoice)
-				rowInvoice6 := new(fms.ContractInvoice)
 
 				isSkip := false
 				for k, cell := range cells {
@@ -1617,8 +1599,17 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						rowRegister.CompanyName = v
 						continue
 					}
-					// 续约/新增
+					// 是否新客户
 					if k == 1 {
+						if !utils.InArrayByStr(newCompanyArr, v) {
+							resp.Fail(fmt.Sprintf("第%d行新客户有误, 请按模板导入", i+1), c)
+							return
+						}
+						rowRegister.NewCompany = newCompanyMap[v]
+						continue
+					}
+					// 合同类型
+					if k == 2 {
 						if !utils.InArrayByStr(contractTypeArr, v) {
 							resp.Fail(fmt.Sprintf("第%d行合同类型有误, 请按模板导入", i+1), c)
 							return
@@ -1631,21 +1622,22 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						continue
 					}
 					// 销售
-					if k == 2 {
+					if k == 3 {
 						if v == "" {
 							resp.Fail(fmt.Sprintf("第%d行销售名称不可为空, 请按模板导入", i+1), c)
 							return
 						}
-						rowRegister.SellerName = v
-						rowRegister.SellerId = sellerNameIdMap[rowRegister.SellerName]
-						if rowRegister.SellerId == 0 {
+						sellerItem := sellerMap[v]
+						if sellerItem == nil {
 							resp.Fail(fmt.Sprintf("第%d行销售名称与系统销售不匹配, 请核对名称后导入", i+1), c)
 							return
 						}
+						rowRegister.SellerId = sellerItem.SellerId
+						rowRegister.SellerName = sellerItem.SellerName
 						continue
 					}
 					// FICC大套餐
-					if k == 3 {
+					if k == 4 {
 						if v == "是" {
 							tempItem := serviceTempNameMap[titleMap[k]]
 							if tempItem == nil {
@@ -1666,7 +1658,7 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						continue
 					}
 					// FICC小套餐
-					if k >= 4 && k <= 23 {
+					if k >= 5 && k <= 25 {
 						// 小套餐权限
 						if v == "是" {
 							rowChartPermissionIdArr = append(rowChartPermissionIdArr, strconv.Itoa(chartPermissionNameIdMap[titleMap[k]]))
@@ -1674,7 +1666,7 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						continue
 					}
 					// 其他类型套餐
-					if k >= 24 && k <= 30 {
+					if k >= 26 && k <= 32 {
 						if v == "是" {
 							tempItem := serviceTempNameMap[titleMap[k]]
 							if tempItem == nil {
@@ -1695,12 +1687,12 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						continue
 					}
 					// 套餐备注
-					if k == 31 {
+					if k == 33 {
 						rowRegister.ServiceRemark = v
 						continue
 					}
 					// 开始时间/到期时间
-					if k == 32 {
+					if k == 34 {
 						// 转换失败可能是因为格式为Excel日期格式, 读取出来会是一串数字, 将其转换成日期字符串再处理
 						va := cell.Value
 						if va == "" {
@@ -1724,7 +1716,7 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						rowRegister.StartDate = startDate
 						continue
 					}
-					if k == 33 {
+					if k == 35 {
 						va := cell.Value
 						if va == "" {
 							resp.Fail(fmt.Sprintf("第%d行到期时间不可为空, 请按模板导入", i+1), c)
@@ -1747,7 +1739,7 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						continue
 					}
 					// 合同金额
-					if k == 34 {
+					if k == 36 {
 						amountStr := v
 						amount, e := strconv.ParseFloat(amountStr, 64)
 						if e != nil {
@@ -1758,13 +1750,12 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						continue
 					}
 					// 约定付款日期
-					if k == 35 {
+					if k == 37 {
 						rowRegister.AgreedPayTime = v
 						continue
 					}
 					// 签订日
-					// k == 32为签订月,可忽略
-					if k == 36 {
+					if k == 38 {
 						va := cell.Value
 						if va == "" {
 							continue
@@ -1786,7 +1777,7 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						continue
 					}
 					// 合同状态
-					if k == 38 {
+					if k == 39 {
 						rowRegister.ContractStatus = fms.ContractStatusNameKeyMap[v]
 						if rowRegister.ContractStatus == 0 {
 							resp.Fail(fmt.Sprintf("第%d行合同状态不匹配, 请按模板导入", i+1), c)
@@ -1795,7 +1786,7 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						continue
 					}
 					// 合同编号
-					if k == 39 {
+					if k == 40 {
 						rowContractCode := v
 						if rowContractCode == "" {
 							resp.Fail(fmt.Sprintf("第%d行合同编号不可为空, 请按模板导入", i+1), c)
@@ -1809,210 +1800,129 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						rowRegister.ContractCode = rowContractCode
 						continue
 					}
-					// 备注
-					if k == 40 {
+					// 合规备注
+					if k == 41 {
 						rowRegister.Remark = v
 						continue
 					}
-					// 开票日/开票金额
-					if k == 41 {
-						if v != "" {
-							va := cell.Value
-							invoiceDate, e := time.ParseInLocation("2006/01/02", va, time.Local)
-							if e != nil {
-								d := utils.ConvertToFormatDay(va, "2006/01/02")
-								invoiceDate, e = time.ParseInLocation("2006/01/02", d, time.Local)
+					// 开票列表
+					k2 := 41
+					for ir := 0; ir < invoiceMax; ir++ {
+						n := ir + 1
+						// 开票日
+						k2 += 1
+						if k == k2 {
+							if v != "" {
+								va := cell.Value
+								invoiceDate, e := time.ParseInLocation("2006/01/02", va, time.Local)
 								if e != nil {
-									resp.Fail(fmt.Sprintf("第%d行开票时间1格式转换有误, 请按模板导入", i+1), c)
-									return
+									d := utils.ConvertToFormatDay(va, "2006/01/02")
+									invoiceDate, e = time.ParseInLocation("2006/01/02", d, time.Local)
+									if e != nil {
+										resp.Fail(fmt.Sprintf("第%d行开票时间%d格式转换有误, 请按模板导入", i+1, n), c)
+										return
+									}
 								}
-							}
-							if invoiceDate.Before(checkDate) {
-								resp.Fail(fmt.Sprintf("第%d行开票时间1格式有误, 请按模板导入", i+1), c)
-								return
-							}
-							rowInvoice1.InvoiceDate = invoiceDate
-							rowInvoice1.ContractCode = rowRegister.ContractCode
-							rowInvoice1.InvoiceType = fms.ContractInvoiceTypeMake
-						}
-						continue
-					}
-					if k == 42 && v != "" {
-						amountStr := v
-						amount, e := strconv.ParseFloat(amountStr, 64)
-						if e != nil {
-							resp.Fail(fmt.Sprintf("第%d行开票金额1有误, 请按模板导入", i+1), c)
-							return
-						}
-						rowInvoice1.Amount = amount
-						rowInvoices = append(rowInvoices, rowInvoice1)
-						continue
-					}
-					if k == 43 {
-						if v != "" {
-							va := cell.Value
-							invoiceDate, e := time.ParseInLocation("2006/01/02", va, time.Local)
-							if e != nil {
-								d := utils.ConvertToFormatDay(va, "2006/01/02") //录入日期
-								invoiceDate, e = time.ParseInLocation("2006/01/02", d, time.Local)
-								if e != nil {
-									resp.Fail(fmt.Sprintf("第%d行开票时间2格式转换有误, 请按模板导入", i+1), c)
+								if invoiceDate.Before(checkDate) {
+									resp.Fail(fmt.Sprintf("第%d行开票时间%d格式有误, 请按模板导入", i+1, n), c)
 									return
 								}
+								rowInvoices[ir].InvoiceDate = invoiceDate
+								rowInvoices[ir].ContractCode = rowRegister.ContractCode
+								rowInvoices[ir].InvoiceType = fms.ContractInvoiceTypeMake
 							}
-							if invoiceDate.Before(checkDate) {
-								resp.Fail(fmt.Sprintf("第%d行开票时间2格式有误, 请按模板导入", i+1), c)
-								return
-							}
-							rowInvoice2.InvoiceDate = invoiceDate
-							rowInvoice2.ContractCode = rowRegister.ContractCode
-							rowInvoice2.InvoiceType = fms.ContractInvoiceTypeMake
-						}
-						continue
-					}
-					if k == 44 && v != "" {
-						amountStr := v
-						amount, e := strconv.ParseFloat(amountStr, 64)
-						if e != nil {
-							resp.Fail(fmt.Sprintf("第%d行开票金额2有误, 请按模板导入", i+1), c)
-							return
+							continue
 						}
-						rowInvoice2.Amount = amount
-						rowInvoices = append(rowInvoices, rowInvoice2)
-						continue
-					}
-					if k == 45 {
-						if v != "" {
-							va := cell.Value
-							invoiceDate, e := time.ParseInLocation("2006/01/02", va, time.Local)
-							if e != nil {
-								d := utils.ConvertToFormatDay(va, "2006/01/02") //录入日期
-								invoiceDate, e = time.ParseInLocation("2006/01/02", d, time.Local)
+						// 开票金额
+						k2 += 1
+						if k == k2 {
+							if v != "" {
+								amountStr := v
+								amount, e := strconv.ParseFloat(amountStr, 64)
 								if e != nil {
-									resp.Fail(fmt.Sprintf("第%d行开票时间3格式转换有误, 请按模板导入", i+1), c)
+									resp.Fail(fmt.Sprintf("第%d行开票金额%d有误, 请按模板导入", i+1, n), c)
 									return
 								}
+								rowInvoices[ir].Amount = amount
 							}
-							if invoiceDate.Before(checkDate) {
-								resp.Fail(fmt.Sprintf("第%d行开票时间3格式有误, 请按模板导入", i+1), c)
-								return
-							}
-							rowInvoice3.InvoiceDate = invoiceDate
-							rowInvoice3.ContractCode = rowRegister.ContractCode
-							rowInvoice3.InvoiceType = fms.ContractInvoiceTypeMake
-						}
-						continue
-					}
-					if k == 46 && v != "" {
-						amountStr := v
-						amount, e := strconv.ParseFloat(amountStr, 64)
-						if e != nil {
-							resp.Fail(fmt.Sprintf("第%d行开票金额3有误, 请按模板导入", i+1), c)
-							return
+							continue
 						}
-						rowInvoice3.Amount = amount
-						rowInvoices = append(rowInvoices, rowInvoice3)
-						continue
-					}
-					// 收款日/收款金额
-					if k == 47 {
-						if v != "" {
-							va := cell.Value
-							invoiceDate, e := time.ParseInLocation("2006/01/02", va, time.Local)
-							if e != nil {
-								d := utils.ConvertToFormatDay(va, "2006/01/02") //录入日期
-								invoiceDate, e = time.ParseInLocation("2006/01/02", d, time.Local)
-								if e != nil {
-									resp.Fail(fmt.Sprintf("第%d行收款时间1格式转换有误, 请按模板导入", i+1), c)
+						// 开票销售
+						k2 += 1
+						if k == k2 {
+							if v != "" {
+								sellerItem := sellerMap[v]
+								if sellerItem == nil {
+									resp.Fail(fmt.Sprintf("第%d行开票销售名称与系统销售不匹配, 请核对名称后导入", i+1), c)
 									return
 								}
+								rowInvoices[ir].SellerId = sellerItem.SellerId
+								rowInvoices[ir].SellerName = sellerItem.SellerName
+								rowInvoices[ir].SellerGroupId = sellerItem.GroupId
+								rowInvoices[ir].SellerGroupName = sellerItem.GroupName
+								rowInvoices[ir].SellerTeamId = sellerItem.TeamId
+								rowInvoices[ir].SellerTeamName = sellerItem.TeamName
 							}
-							if invoiceDate.Before(checkDate) {
-								resp.Fail(fmt.Sprintf("第%d行收款时间1格式有误, 请按模板导入", i+1), c)
-								return
-							}
-							rowInvoice4.InvoiceDate = invoiceDate
-							rowInvoice4.ContractCode = rowRegister.ContractCode
-							rowInvoice4.InvoiceType = fms.ContractInvoiceTypePay
+							continue
 						}
-						continue
-					}
-					if k == 48 && v != "" {
-						amountStr := v
-						amount, e := strconv.ParseFloat(amountStr, 64)
-						if e != nil {
-							resp.Fail(fmt.Sprintf("第%d行收款金额1有误, 请按模板导入", i+1), c)
-							return
+						// 备注
+						k2 += 1
+						if k == k2 {
+							if v != "" {
+								rowInvoices[ir].Remark = v
+							}
+							continue
 						}
-						rowInvoice4.Amount = amount
-						rowInvoices = append(rowInvoices, rowInvoice4)
-						continue
 					}
-					if k == 49 {
-						if v != "" {
-							va := cell.Value
-							invoiceDate, e := time.ParseInLocation("2006/01/02", va, time.Local)
-							if e != nil {
-								d := utils.ConvertToFormatDay(va, "2006/01/02") //录入日期
-								invoiceDate, e = time.ParseInLocation("2006/01/02", d, time.Local)
+					// 到款列表
+					for ir := 0; ir < invoiceMax; ir++ {
+						n := ir + 1
+						// 到款日
+						k2 += 1
+						if k == k2 {
+							if v != "" {
+								va := cell.Value
+								invoiceDate, e := time.ParseInLocation("2006/01/02", va, time.Local)
 								if e != nil {
-									resp.Fail(fmt.Sprintf("第%d行收款时间2格式转换有误, 请按模板导入", i+1), c)
+									d := utils.ConvertToFormatDay(va, "2006/01/02")
+									invoiceDate, e = time.ParseInLocation("2006/01/02", d, time.Local)
+									if e != nil {
+										resp.Fail(fmt.Sprintf("第%d行到款时间%d格式转换有误, 请按模板导入", i+1, n), c)
+										return
+									}
+								}
+								if invoiceDate.Before(checkDate) {
+									resp.Fail(fmt.Sprintf("第%d行到款时间%d格式有误, 请按模板导入", i+1, n), c)
 									return
 								}
+								rowPayments[ir].InvoiceDate = invoiceDate
+								rowPayments[ir].ContractCode = rowRegister.ContractCode
+								rowPayments[ir].InvoiceType = fms.ContractInvoiceTypePay
 							}
-							if invoiceDate.Before(checkDate) {
-								resp.Fail(fmt.Sprintf("第%d行收款时间2格式有误, 请按模板导入", i+1), c)
-								return
-							}
-							rowInvoice5.InvoiceDate = invoiceDate
-							rowInvoice5.ContractCode = rowRegister.ContractCode
-							rowInvoice5.InvoiceType = fms.ContractInvoiceTypePay
-						}
-						continue
-					}
-					if k == 50 && v != "" {
-						amountStr := v
-						amount, e := strconv.ParseFloat(amountStr, 64)
-						if e != nil {
-							resp.Fail(fmt.Sprintf("第%d行收款金额2有误, 请按模板导入", i+1), c)
-							return
+							continue
 						}
-						rowInvoice5.Amount = amount
-						rowInvoices = append(rowInvoices, rowInvoice5)
-						continue
-					}
-					if k == 51 {
-						if v != "" {
-							va := cell.Value
-							invoiceDate, e := time.ParseInLocation("2006/01/02", va, time.Local)
-							if e != nil {
-								d := utils.ConvertToFormatDay(va, "2006/01/02") //录入日期
-								invoiceDate, e = time.ParseInLocation("2006/01/02", d, time.Local)
+						// 到款金额
+						k2 += 1
+						if k == k2 {
+							if v != "" {
+								amountStr := v
+								amount, e := strconv.ParseFloat(amountStr, 64)
 								if e != nil {
-									resp.Fail(fmt.Sprintf("第%d行收款时间3格式转换有误, 请按模板导入", i+1), c)
+									resp.Fail(fmt.Sprintf("第%d行到款金额%d有误, 请按模板导入", i+1, n), c)
 									return
 								}
+								rowPayments[ir].Amount = amount
 							}
-							if invoiceDate.Before(checkDate) {
-								resp.Fail(fmt.Sprintf("第%d行收款时间3格式有误, 请按模板导入", i+1), c)
-								return
-							}
-							rowInvoice6.InvoiceDate = invoiceDate
-							rowInvoice6.ContractCode = rowRegister.ContractCode
-							rowInvoice6.InvoiceType = fms.ContractInvoiceTypePay
+							continue
 						}
-						continue
-					}
-					if k == 52 && v != "" {
-						amountStr := v
-						amount, e := strconv.ParseFloat(amountStr, 64)
-						if e != nil {
-							resp.Fail(fmt.Sprintf("第%d行收款金额3有误, 请按模板导入", i+1), c)
-							return
+						// 备注
+						k2 += 1
+						if k == k2 {
+							if v != "" {
+								rowPayments[ir].Remark = v
+							}
+							continue
 						}
-						rowInvoice6.Amount = amount
-						rowInvoices = append(rowInvoices, rowInvoice6)
-						continue
 					}
 				}
 
@@ -2049,8 +1959,20 @@ func (rg *RegisterController) Import(c *gin.Context) {
 					return
 				}
 				rowRegister.RegisterStatus = fms.ContractRegisterStatusIng
+				lastInvoices := make([]*fms.ContractInvoice, 0)
+				// 过滤信息不完整的开票到款
+				for l := range rowInvoices {
+					if rowInvoices[l].ContractCode != "" && rowInvoices[l].SellerId > 0 {
+						lastInvoices = append(lastInvoices, rowInvoices[l])
+					}
+				}
+				for l := range rowPayments {
+					if rowPayments[l].ContractCode != "" {
+						lastInvoices = append(lastInvoices, rowPayments[l])
+					}
+				}
 				// 新增登记、套餐、开票到款信息
-				newId, e := fms.CreateImportContractRegister(rowRegister, rowServices, rowInvoices)
+				newId, e := fms.CreateImportContractRegister(rowRegister, rowServices, lastInvoices)
 				if e != nil {
 					resp.FailData(fmt.Sprintf("第%d行导入失败", i+1), "新增导入登记失败, Err: "+e.Error(), c)
 					return
@@ -2060,12 +1982,5 @@ func (rg *RegisterController) Import(c *gin.Context) {
 		}
 	}
 
-	// 更新登记状态
-	go func() {
-		for i := range newIds {
-			fmsService.CheckContractRegisterAmount(newIds[i])
-		}
-	}()
-
 	resp.Ok("操作成功", c)
 }

+ 37 - 21
controller/crm/company_seller.go

@@ -6,6 +6,7 @@ import (
 	"hongze/fms_api/controller/resp"
 	"hongze/fms_api/global"
 	"hongze/fms_api/models/crm"
+	crmService "hongze/fms_api/services/crm"
 )
 
 // CompanySellerController CRM销售
@@ -29,31 +30,46 @@ func (rg *CompanySellerController) List(c *gin.Context) {
 		return
 	}
 
-	roleCodeArr := make([]string, 0)
-	if req.SellerType == crm.CompanyProductRai {
-		roleCodeArr = []string{
-			crm.ROLE_TYPE_CODE_RAI_ADMIN,
-			crm.ROLE_TYPE_CODE_RAI_DEPARTMENT,
-			crm.ROLE_TYPE_CODE_RAI_GROUP,
-			crm.ROLE_TYPE_CODE_RAI_SELLER,
-		}
-	} else {
-		roleCodeArr = []string{
-			crm.ROLE_TYPE_CODE_FICC_ADMIN,
-			crm.ROLE_TYPE_CODE_FICC_DEPARTMENT,
-			crm.ROLE_TYPE_CODE_FICC_GROUP,
-			crm.ROLE_TYPE_CODE_FICC_TEAM,
-			crm.ROLE_TYPE_CODE_FICC_SELLER,
-		}
-	}
-	cond := `b.role_type_code IN ?`
-	pars := make([]interface{}, 0)
-	pars = append(pars, roleCodeArr)
-	list, e := crm.GetCompanySellerByRoleCodes(cond, pars)
+	//roleCodeArr := make([]string, 0)
+	//if req.SellerType == crm.CompanyProductRai {
+	//	roleCodeArr = []string{
+	//		crm.ROLE_TYPE_CODE_RAI_ADMIN,
+	//		crm.ROLE_TYPE_CODE_RAI_DEPARTMENT,
+	//		crm.ROLE_TYPE_CODE_RAI_GROUP,
+	//		crm.ROLE_TYPE_CODE_RAI_SELLER,
+	//	}
+	//} else {
+	//	roleCodeArr = []string{
+	//		crm.ROLE_TYPE_CODE_FICC_ADMIN,
+	//		crm.ROLE_TYPE_CODE_FICC_DEPARTMENT,
+	//		crm.ROLE_TYPE_CODE_FICC_GROUP,
+	//		crm.ROLE_TYPE_CODE_FICC_TEAM,
+	//		crm.ROLE_TYPE_CODE_FICC_SELLER,
+	//	}
+	//}
+	//cond := `b.role_type_code IN ?`
+	//pars := make([]interface{}, 0)
+	//pars = append(pars, roleCodeArr)
+	//list, e := crm.GetCompanySellerByRoleCodes(cond, pars)
+	//if e != nil {
+	//	resp.FailData("获取失败", "获取销售列表失败, Err:"+e.Error(), c)
+	//	return
+	//}
+
+	// 此处调整为只取销售部门的人员, 而不是原先的根据角色取
+	sellerList, e := crmService.GetSellerDepartmentListWithGroupAndTeam()
 	if e != nil {
 		resp.FailData("获取失败", "获取销售列表失败, Err:"+e.Error(), c)
 		return
 	}
+	list := make([]*crm.CompanySellerList, 0)
+	for i := range sellerList {
+		list = append(list, &crm.CompanySellerList{
+			AdminId: sellerList[i].SellerId,
+			AdminName: sellerList[i].SellerName,
+			RealName: sellerList[i].SellerName,
+		})
+	}
 	resp.OkData("获取成功", list, c)
 }
 

+ 7 - 0
models/crm/admin.go

@@ -50,3 +50,10 @@ func (m *Admin) List(condition string, pars []interface{}) (list []*Admin, err e
 		Find(&list).Error
 	return
 }
+
+func (m *Admin) Count(condition string, pars []interface{}) (total int64, err error) {
+	err = global.MYSQL["report"].Model(m).
+		Where(condition, pars...).
+		Count(&total).Error
+	return
+}

+ 7 - 0
models/crm/sys_group.go

@@ -25,3 +25,10 @@ func (m *SysGroup) List(condition string, pars []interface{}) (list []*SysGroup,
 		Find(&list).Error
 	return
 }
+
+func (m *SysGroup) Count(condition string, pars []interface{}) (total int64, err error) {
+	err = global.MYSQL["report"].Model(m).
+		Where(condition, pars...).
+		Count(&total).Error
+	return
+}

+ 99 - 0
models/fms/contract_invoice.go

@@ -1,6 +1,7 @@
 package fms
 
 import (
+	"fmt"
 	"hongze/fms_api/global"
 	"hongze/fms_api/models/base"
 	"hongze/fms_api/utils"
@@ -68,6 +69,15 @@ func (c *ContractInvoice) Fetch(id int) (item *ContractInvoice, err error) {
 	return
 }
 
+func (c *ContractInvoice) Sum(field, condition string, pars []interface{}) (total float64, err error) {
+	selectField := fmt.Sprintf("SUM(%s)", field)
+	err = global.DEFAULT_MYSQL.Model(c).
+		Select(selectField).
+		Where(condition, pars...).
+		Find(&total).Error
+	return
+}
+
 func (c *ContractInvoice) List(condition string, pars []interface{}, orderRule string) (list []*ContractInvoice, err error) {
 	list = make([]*ContractInvoice, 0)
 	query := global.DEFAULT_MYSQL.Model(c).
@@ -321,3 +331,92 @@ type UpdatePaymentPayTypeReq struct {
 	ContractPaymentId int `json:"contract_payment_id" binding:"required,gte=1" description:"到款登记ID"`
 	PayType           int `json:"pay_type" binding:"oneof=1 2 3 4" description:"付款方式: 1-年付; 2-半年付; 3-季付; 4-次付"`
 }
+
+// CensusSellerGroupInvoiceListReq 销售组开票统计列表请求体
+type CensusSellerGroupInvoiceListReq struct {
+	StartDate string `json:"start_date" form:"start_date" binding:"omitempty,datetime=2006-01-02" description:"开始日期"`
+	EndDate   string `json:"end_date" form:"end_date" binding:"omitempty,datetime=2006-01-02" description:"结束日期"`
+	SortField int    `json:"sort_field" form:"sort_field" description:"排序字段: 1-开票金额; 2-组别占比"`
+	SortType  int    `json:"sort_type" form:"sort_type" description:"排序方式: 1-正序; 2-倒序"`
+	IsExport  int    `json:"is_export" form:"is_export" description:"是否导出: 0-否; 1-是"`
+	base.PageReq
+}
+
+// CensusSellerGroupInvoiceItem 销售组开票统计数据
+type CensusSellerGroupInvoiceItem struct {
+	GroupId       int     `json:"group_id" description:"分组ID"`
+	GroupName     string  `json:"group_name" description:"分组名称"`
+	InvoiceAmount float64 `json:"invoice_amount" description:"开票金额"`
+	GroupRate     float64 `json:"group_rate" description:"分组占比"`
+}
+
+// GetCensusSellerGroupInvoicePageList 获取销售组开票统计列表-分页
+func GetCensusSellerGroupInvoicePageList(page base.IPage, condition, outCond string, pars []interface{}, amountSum float64) (results []*CensusSellerGroupInvoiceItem, err error) {
+	tableName := `weekly_report.sys_group`
+	if global.CONFIG.Serve.RunMode == "debug" {
+		tableName = `test_v2_weekly_report.sys_group`
+	}
+	sql := `SELECT a.group_id, a.group_name, b.invoice_amount, b.group_rate FROM %s AS a LEFT JOIN `
+	sql += ` (
+				SELECT
+					seller_group_id,
+					seller_group_name,
+					SUM(amount) AS invoice_amount,
+					SUM(amount) / %f AS group_rate
+				FROM
+					contract_invoice
+				WHERE
+					%s
+				GROUP BY
+					seller_group_id
+			) AS b ON a.group_id = b.seller_group_id`
+	sql += ` WHERE %s ORDER BY %s LIMIT %d,%d`
+	sql = fmt.Sprintf(sql, tableName, amountSum, condition, outCond, page.GetOrderItemsString(), page.Offset(), page.GetPageSize())
+	err = global.DEFAULT_MYSQL.Raw(sql, pars).Scan(&results).Error
+	return
+}
+
+// CensusSellerInvoiceListReq 销售开票统计列表请求体
+type CensusSellerInvoiceListReq struct {
+	GroupId   int    `json:"group_id" form:"group_id" description:"销售组别ID"`
+	StartDate string `json:"start_date" form:"start_date" binding:"omitempty,datetime=2006-01-02" description:"开始日期"`
+	EndDate   string `json:"end_date" form:"end_date" binding:"omitempty,datetime=2006-01-02" description:"结束日期"`
+	SortField int    `json:"sort_field" form:"sort_field" description:"排序字段: 1-开票金额; 2-小组占比; 3-全员占比"`
+	SortType  int    `json:"sort_type" form:"sort_type" description:"排序方式: 1-正序; 2-倒序"`
+	IsExport  int    `json:"is_export" form:"is_export" description:"是否导出: 0-否; 1-是"`
+	base.PageReq
+}
+
+// CensusSellerInvoiceItem 销售组开票统计数据
+type CensusSellerInvoiceItem struct {
+	SellerId      int     `json:"seller_id" description:"销售ID"`
+	SellerName    string  `json:"seller_name" description:"销售名称"`
+	GroupId       int     `json:"group_id" description:"分组ID"`
+	GroupName     string  `json:"group_name" description:"分组名称"`
+	InvoiceAmount float64 `json:"invoice_amount" description:"开票金额"`
+	GroupRate     float64 `json:"group_rate" description:"分组占比"`
+	SellerRate    float64 `json:"seller_rate" description:"全员占比"`
+}
+
+// GetCensusSellerInvoicePageList 获取销售开票统计列表-分页
+func GetCensusSellerInvoicePageList(page base.IPage, condition, outCond string, pars []interface{}, amountSum float64) (results []*CensusSellerInvoiceItem, err error) {
+	tableName := `weekly_report.admin`
+	if global.CONFIG.Serve.RunMode == "debug" {
+		tableName = `test_v2_weekly_report.admin`
+	}
+	sql := `SELECT a.admin_id AS seller_id, a.real_name AS seller_name, a.group_id, b.invoice_amount, b.group_rate, b.seller_rate FROM %s AS a LEFT JOIN `
+	sql += ` (
+				SELECT c.seller_id, c.seller_group_id, SUM(c.amount) AS invoice_amount,
+				SUM(c.amount) / (
+					SELECT SUM(amount) FROM contract_invoice WHERE seller_group_id = c.seller_group_id AND %s
+				) AS group_rate,
+				SUM(c.amount) / %f AS seller_rate
+				FROM contract_invoice AS c
+				WHERE %s
+				GROUP BY c.seller_id
+			) AS b ON a.admin_id = b.seller_id `
+	sql += ` WHERE %s ORDER BY %s LIMIT %d,%d`
+	sql = fmt.Sprintf(sql, tableName, condition, amountSum, condition, outCond, page.GetOrderItemsString(), page.Offset(), page.GetPageSize())
+	err = global.DEFAULT_MYSQL.Raw(sql, pars...).Scan(&results).Error
+	return
+}

+ 6 - 0
routers/census.go

@@ -11,4 +11,10 @@ func InitCensus(rg *gin.RouterGroup) {
 	inv := new(census.InvoicePaymentController)
 	invGroup := rg.Group("invoice_payment/").Use(middleware.Token())
 	invGroup.GET("list", inv.List)
+
+	// 销售
+	sel := new(census.SellerController)
+	selGroup := rg.Group("seller/").Use(middleware.Token())
+	selGroup.GET("group_invoice_list", sel.GroupInvoiceList)
+	selGroup.GET("invoice_list", sel.InvoiceList)
 }

+ 32 - 5
services/crm/company_seller.go

@@ -41,8 +41,8 @@ func GetSellerDepartmentListWithGroupAndTeam() (sellerList []*crm.SellerAdminWit
 		v.SellerName = adminList[i].RealName
 		g := groupMap[adminList[i].GroupId]
 		if g != nil {
-			// 三级分组
 			if g.ParentId > 0 {
+				// 三级分组
 				p := groupMap[g.ParentId]
 				if p != nil {
 					v.GroupId = p.GroupId
@@ -50,13 +50,40 @@ func GetSellerDepartmentListWithGroupAndTeam() (sellerList []*crm.SellerAdminWit
 					v.TeamId = g.GroupId
 					v.TeamName = g.GroupName
 				}
-				continue
+			} else {
+				// 二级分组
+				v.GroupId = g.GroupId
+				v.GroupName = g.GroupName
 			}
-			// 二级分组
-			v.GroupId = g.GroupId
-			v.GroupName = g.GroupName
 		}
 		sellerList = append(sellerList, v)
 	}
 	return
 }
+
+// GetSellerTeamGroupMap 获取销售组别对应的大组信息
+func GetSellerTeamGroupMap() (teamGroupMap map[int]*crm.SysGroup, err error) {
+	teamGroupMap = make(map[int]*crm.SysGroup)
+	groupCond := `department_id = ?`
+	groupPars := make([]interface{}, 0)
+	groupPars = append(groupPars, crm.SellerDepartmentId)
+	groupOB := new(crm.SysGroup)
+	groupList, e := groupOB.List(groupCond, groupPars)
+	if e != nil {
+		err = errors.New("获取组别列表失败, Err: " + e.Error())
+		return
+	}
+	groupMap := make(map[int]*crm.SysGroup)
+	for i := range groupList {
+		groupMap[groupList[i].GroupId] = groupList[i]
+	}
+	for i := range groupList {
+		// 大组对应的是自己
+		if groupList[i].ParentId == 0 {
+			teamGroupMap[groupList[i].GroupId] = groupList[i]
+			continue
+		}
+		teamGroupMap[groupList[i].GroupId] = groupMap[groupList[i].ParentId]
+	}
+	return
+}

+ 1 - 0
services/fms/contract_register.go

@@ -21,6 +21,7 @@ func CheckContractRegisterAmount(registerId int) {
 	var err error
 	defer func() {
 		if err != nil {
+			fmt.Println("校验合同登记金额失败, ErrMsg: "+err.Error())
 			alarm_msg.SendAlarmMsg("校验合同登记金额失败, ErrMsg: "+err.Error(), 3)
 		}
 	}()