package contract

import (
	"encoding/json"
	"fmt"
	"github.com/rdlucklib/rdluck_tools/paging"
	"github.com/shopspring/decimal"
	"github.com/tealeg/xlsx"
	"hongze/hz_crm_api/controllers"
	"hongze/hz_crm_api/models"
	"hongze/hz_crm_api/models/company"
	"hongze/hz_crm_api/models/contract"
	"hongze/hz_crm_api/models/contract/request"
	"hongze/hz_crm_api/models/contract/response"
	"hongze/hz_crm_api/services"
	contractService "hongze/hz_crm_api/services/contract"
	"hongze/hz_crm_api/utils"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

// 审批流管理
type ContractApprovalController struct {
	controllers.BaseAuthController
}

// @Title 提交申请
// @Description 提交申请接口
// @Param   ContractId   query   int  true       "合同id编号"
// @Success Ret=200 申请成功
// @router /approval/apply [get]
func (this *ContractApprovalController) Apply() {
	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
	}

	//合同id编号
	contractId, err := this.GetInt("ContractId")
	if err != nil {
		br.Msg = "获取合同编号失败"
		br.ErrMsg = "获取合同编号失败，err：" + err.Error()
		return
	}
	if contractId <= 0 {
		br.Msg = "请传入合同编号"
		br.ErrMsg = "请传入合同编号"
		return
	}

	err, errMsg := contractService.Apply(contractId)
	if err != nil {
		br.Msg = "发起审批失败！"
		if errMsg != "" {
			br.Msg = errMsg
		}
		br.ErrMsg = "发起审批失败，Err:" + err.Error()
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "申请成功"
}

// List
// @Title 审批单列表
// @Description 审批单列表接口
// @Param   ContractBusinessType   query   string  false       "合同业务类型，枚举值：'业务合同','代付合同',不传默认是全部"
// @Param   ContractType   query   string  false       "合同类型，枚举值：'新签合同','续约合同','补充协议'"
// @Param   Status   query   string  false       "合同状态，枚举值：'待审批','已审批','已驳回','已撤回'"
// @Param   ProductId   query   int  false       "客户类型：传0或者不传为当前账号权限,1 代表是：ficc；2 代表是：权益"
// @Param   SellerId   query   string  false       "选择的销售id"
// @Param   Keyword   query   string  false       "搜索关键字"
// @Param   ModifyStartTime   query   string  false       "服务更新时间的选择开始时间，格式：2021-05-23 00:00:00"
// @Param   ModifyEndTime   query   string  false       "服务更新时间的选择结束时间，格式：2021-05-26 23:59:59"
// @Param   IsExport   query   bool  false       "是否导出excel，默认是false"
// @Success 200 {object} response.ContractApprovalListResp
// @router /approval/list [get]
func (this *ContractApprovalController) List() {
	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
	}

	//合同类型、产品类型、合同状态、更新时间、所选销售
	//关键字：合同编号、客户名称，社会信用码
	contractBusinessType := this.GetString("ContractBusinessType") //合同业务类型
	contractType := this.GetString("ContractType")
	status := this.GetString("Status")
	productId, _ := this.GetInt("ProductId")
	sellerIds := this.GetString("SellerId")
	keyword := this.GetString("Keyword")
	modifyStartTime := this.GetString("ModifyStartTime")
	modifyEndTime := this.GetString("ModifyEndTime")

	childCondition := ""
	condition := ""
	childPars := make([]interface{}, 0)
	pars := make([]interface{}, 0)
	productSlice := make([]int, 0) //需要下载的 产品 切片

	//如果不是超管或者合规，那么只能查看自己的合同
	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_ADMIN { //权益管理员
		condition += ` AND c.product_id = ? `
		pars = append(pars, 2)
	} else if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_ADMIN { //ficc管理员
		condition += ` AND c.product_id = ? `
		pars = append(pars, 1)
	} else {
		if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_COMPLIANCE && sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
			condition += ` AND c.seller_id = ? `
			pars = append(pars, sysUser.AdminId)
		}
	}

	//合同类型、、更新时间、所选销售
	//关键字：合同编号、客户名称，社会信用码
	if contractType != "" {
		condition += ` AND c.contract_type = ? `
		pars = append(pars, contractType)
	}
	//合同业务类型
	if contractBusinessType != "" {
		condition += ` AND c.contract_business_type = ? `
		pars = append(pars, contractBusinessType)
	}
	//审批状态
	if status != "" {
		//childCondition += ` AND status = ? `
		//childPars = append(childPars, status)

		if status == "已审批" {
			condition += ` AND c.status in ("已审批","已驳回")  `
		} else {
			condition += ` AND c.status = ? `
			pars = append(pars, status)
		}
	} else {
		//childCondition += ` AND status != "已撤回" `

		condition += ` AND c.status not in ("已撤回","待提交")  `
	}
	//产品类型
	if productId > 0 {
		condition += ` AND c.product_id = ? `
		pars = append(pars, productId)

		productSlice = append(productSlice, productId)
	} else {
		nowProductId := services.GetProductId(sysUser.RoleTypeCode)
		if nowProductId > 0 {
			productSlice = append(productSlice, nowProductId)
		} else {
			productSlice = append(productSlice, 1)
			productSlice = append(productSlice, 2)
		}
	}
	//所选销售
	if sellerIds != "" {
		condition += ` AND c.seller_id IN (` + sellerIds + `) `
	}
	//更新开始时间

	//更新开始时间
	if modifyStartTime != "" {
		condition += ` AND a.modify_time >= ? `
		pars = append(pars, modifyStartTime)
	}
	//更新结束时间
	if modifyEndTime != "" {
		condition += ` AND a.modify_time <= ? `
		pars = append(pars, modifyEndTime)
	}
	//关键字
	if keyword != "" {
		condition += ` AND (c.contract_code LIKE '%` + keyword + `%' OR c.company_name LIKE '%` + keyword + `%' OR c.credit_code LIKE '%` + keyword + `%' ) `
	}

	pageSize, _ := this.GetInt("PageSize")
	currentIndex, _ := this.GetInt("CurrentIndex")

	var startSize int
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if currentIndex <= 0 {
		currentIndex = 1
	}
	startSize = paging.StartIndex(currentIndex, pageSize)
	//是否导出报表
	isExport, _ := this.GetBool("IsExport")
	if isExport {
		pageSize = 10000
		currentIndex = 1
	}

	total, err := contract.GetContractApprovalListCount(condition, pars)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取数据总数失败，Err:" + err.Error()
		return
	}

	list, err := contract.GetContractApprovalList(childCondition, condition, childPars, pars, startSize, pageSize)
	if err != nil {
		br.Msg = "获取审批列表失败！"
		br.ErrMsg = "获取审批列表失败，Err:" + err.Error()
		return
	}

	if len(list) > 0 {
		contractApprovalIdSlice := make([]string, 0)
		for i := 0; i < len(list); i++ {
			contractApprovalIdSlice = append(contractApprovalIdSlice, strconv.Itoa(list[i].ContractApprovalId))
		}
		contractApprovalIdStr := strings.Join(contractApprovalIdSlice, ",")

		//获取审批流列表数据
		contractApprovalRecordList, err := contract.GetContractApprovalRecordList(contractApprovalIdStr, sysUser.AdminId)
		if err != nil {
			br.Msg = "获取审批流列表失败！"
			br.ErrMsg = "获取审批流列表失败，Err:" + err.Error()
			return
		}
		contractApprovalRecordMap := make(map[int]*contract.ContractApprovalRecord)
		for i := 0; i < len(contractApprovalRecordList); i++ {
			contractApprovalRecordMap[contractApprovalRecordList[i].ContractApprovalId] = contractApprovalRecordList[i]
		}

		for i := 0; i < len(list); i++ {
			item := list[i]
			list[i].StartDateStr = item.StartDate.Format(utils.FormatDate)
			list[i].EndDateStr = item.EndDate.Format(utils.FormatDate)
			list[i].CreateTimeStr = item.CreateTime.Format(utils.FormatDateTime)
			list[i].ModifyTimeStr = item.ModifyTime.Format(utils.FormatDateTime)
			list[i].ApproveTimeStr = item.ApproveTime.Format(utils.FormatDateTime)
			list[i].CheckBackFileTimeStr = item.CheckBackFileTime.Format(utils.FormatDateTime)
			list[i].InvalidTimeStr = item.InvalidTime.Format(utils.FormatDateTime)
			list[i].RescindTimeStr = item.RescindTime.Format(utils.FormatDateTime)

			//合同操作权限
			var opButton contract.ContractButton

			var contractDetail contract.ContractDetail
			jsonErr := json.Unmarshal([]byte(list[i].ContractDetail), &contractDetail)
			if jsonErr != nil {
				br.Msg = "审批合同数据转换失败！"
				br.ErrMsg = "审批合同数据转换失败，Err:" + jsonErr.Error()
				return
			}
			list[i].ContractInfo = contractDetail
			//校验最新审批流数据
			if contractApprovalRecord, has := contractApprovalRecordMap[item.ContractApprovalId]; has {
				//审批流id
				list[i].ContractApprovalRecordId = contractApprovalRecord.ContractApprovalRecordId
				//审批时间
				list[i].ApproveTime = contractApprovalRecord.ApproveTime
				list[i].ApproveTimeStr = contractApprovalRecord.ApproveTime.Format(utils.FormatDateTime)
				//判断是否有操作权限
				list[i].Status = contractApprovalRecord.Status

				//判断是否处于待审批状态
				if contractApprovalRecord.Status == "待审批" {
					//如果不是审批者，那么不能审批操作
					if contractApprovalRecord.NodeType != "check" {
						continue
					}
					//如果没有指定审批人的话
					if contractApprovalRecord.ApproveUserId <= 0 {
						//判断是否与审批角色一致，如果一致，那么允许操作审批
						if contractApprovalRecord.ApproveRoleTypeCode == sysUser.RoleTypeCode {
							opButton.Approval = true
						}
					} else if contractApprovalRecord.ApproveUserId == sysUser.AdminId {
						//如果指定审批人就是自己的话，那么操作审批
						opButton.Approval = true
					}
				}
			}

			if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_COMPLIANCE {
				if item.ContractStatus == "已审批" {
					opButton.CheckBackFile = true
				}
				if item.ContractStatus == "已签回" {
					opButton.RescindFile = true
					opButton.CheckBackFile = true
				}
			}

			//合同状态（突然说要改成展示合同状态，那就根据业务需求，改成返回：合同状态咯）
			list[i].Status = item.ContractStatus

			//合同操作权限
			list[i].OpButton = opButton
		}
	}

	page := paging.GetPaging(currentIndex, pageSize, total)
	//导出excel
	if isExport {
		contractApprovalListExport(this, list, productSlice, br)
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = response.ContractApprovalListResp{
		List:   list,
		Paging: page,
	}
}

// ContractApprovalListExport 导出审批列表
func contractApprovalListExport(this *ContractApprovalController, list []*contract.ContractApprovalList, productSlice []int, br *models.BaseResponse) {
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}

	fmt.Println("list len:", len(list))
	//获取合同套餐服务列表
	serviceTemplateList, err := contract.GetAllContractServiceTemplateList()
	if err != nil {
		br.Msg = "获取合同套餐服务列表失败！"
		br.ErrMsg = "获取合同套餐服务列表失败，Err:" + err.Error()
		return
	}
	templateTitleMap := make(map[int]string)
	for _, serviceTemplate := range serviceTemplateList {
		templateTitleMap[serviceTemplate.ServiceTemplateId] = serviceTemplate.Title
	}
	//业务合同的关联合同id集合
	businessContractIdList := make([]string, 0)
	//代付合同的关联合同id集合
	paymentOnBehalfContractIdList := make([]string, 0)
	//所有合同id集合（用于查询服务内容）
	allServiceContractIdList := make([]string, 0)
	//基础合同的关联合同数据
	contractRelationMap := make(map[int][]*contract.RelationContractList)

	for _, v := range list {
		allServiceContractIdList = append(allServiceContractIdList, fmt.Sprint(v.ContractId))
		switch v.ContractBusinessType {
		case "业务合同":
			businessContractIdList = append(businessContractIdList, fmt.Sprint(v.ContractId))
		case "代付合同":
			paymentOnBehalfContractIdList = append(paymentOnBehalfContractIdList, fmt.Sprint(v.ContractId))
		}
	}
	//业务合同的关联合同
	if len(businessContractIdList) > 0 {
		contractIdStr := strings.Join(businessContractIdList, ",")
		businessContractList, err := contract.GetContractRelationListByRelationContractIds(contractIdStr)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取业务关联合同失败，Err:" + err.Error()
			return
		}
		for _, v := range businessContractList {
			//代付合同id
			allServiceContractIdList = append(allServiceContractIdList, fmt.Sprint(v.PaymentOnBehalfContractId))

			if _, ok := contractRelationMap[v.ContractId]; ok {
				contractRelationMap[v.ContractId] = append(contractRelationMap[v.ContractId], v)
			} else {
				tmpList := make([]*contract.RelationContractList, 0)
				contractRelationMap[v.ContractId] = append(tmpList, v)
			}
		}
	}

	//代付合同的关联合同
	if len(paymentOnBehalfContractIdList) > 0 {
		paymentOnBehalfContractIdStr := strings.Join(paymentOnBehalfContractIdList, ",")
		paymentOnBehalfContractList, err := contract.GetContractRelationListByPaymentOnBehalfContractIds(paymentOnBehalfContractIdStr)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取代付关联合同失败，Err:" + err.Error()
			return
		}
		for _, v := range paymentOnBehalfContractList {
			//业务合同id
			allServiceContractIdList = append(allServiceContractIdList, fmt.Sprint(v.ContractId))

			if _, ok := contractRelationMap[v.PaymentOnBehalfContractId]; ok {
				contractRelationMap[v.PaymentOnBehalfContractId] = append(contractRelationMap[v.PaymentOnBehalfContractId], v)
			} else {
				tmpList := make([]*contract.RelationContractList, 0)
				contractRelationMap[v.PaymentOnBehalfContractId] = append(tmpList, v)
			}
		}
	}

	//获取合同详情
	serviceListMap := make(map[int][]*contract.ContractServiceAndDetail, 0)
	if len(allServiceContractIdList) > 0 {
		allRelationIdStr := strings.Join(allServiceContractIdList, ",")
		tmpServiceList, err := contract.GetContractServiceAndDetailListByIds(allRelationIdStr)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取关联合同服务详情失败，Err:" + err.Error()
			return
		}

		allContractServiceIdList := make([]string, 0)
		serviceDetailListMap := make(map[int][]*contract.ContractServiceDetail, 0)
		for _, service := range tmpServiceList {
			if service.HasDetail == "是" {
				allContractServiceIdList = append(allContractServiceIdList, strconv.Itoa(service.ContractServiceId))
			}
		}
		if len(allContractServiceIdList) > 0 {
			allContractServiceIdStr := strings.Join(allContractServiceIdList, ",")
			list, detailErr := contract.GetContractServiceDetailListByServiceIds(allContractServiceIdStr)
			if detailErr != nil {
				br.Msg = "获取失败"
				br.ErrMsg = "查找合同服务详情异常，Err:" + err.Error()
				return
			}
			for _, v := range list {
				if _, ok := serviceDetailListMap[v.ContractServiceId]; ok {
					serviceDetailListMap[v.ContractServiceId] = append(serviceDetailListMap[v.ContractServiceId], v)
				} else {
					tmpList := make([]*contract.ContractServiceDetail, 0)
					serviceDetailListMap[v.ContractServiceId] = append(tmpList, v)
				}
			}
		}

		for _, service := range tmpServiceList {
			if service.HasDetail == "是" {
				if serviceDetailList, ok := serviceDetailListMap[service.ContractServiceId]; ok {
					service.DetailList = serviceDetailList
				}
				//套餐名称
				if title, ok := templateTitleMap[service.ServiceTemplateId]; ok {
					service.Title = title
				}
			}

			//服务列表
			if _, ok := serviceListMap[service.ContractId]; ok {
				serviceListMap[service.ContractId] = append(serviceListMap[service.ContractId], service)
			} else {
				tmpList := make([]*contract.ContractServiceAndDetail, 0)
				serviceListMap[service.ContractId] = append(tmpList, service)
			}
		}
	}

	//生成excel文件
	dir, err := os.Executable()
	exPath := filepath.Dir(dir)
	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
	xlsxFile := xlsx.NewFile()
	if err != nil {
		br.Msg = "生成文件失败"
		br.ErrMsg = "生成文件失败"
		return
	}

	//设置默认字体和文字大小
	xlsx.SetDefaultFont(12, "宋体")

	//定义边框样式
	border := xlsx.NewBorder("thin", "thin", "thin", "thin")
	//定义文字排版样式
	alignment := xlsx.Alignment{
		Horizontal: "center",
		Vertical:   "center",
		WrapText:   true,
	}

	//普通样式
	style := xlsx.NewStyle()
	style.Alignment = alignment
	style.ApplyAlignment = true
	style.Border = *border

	//标红文字，便于查看哪些产品被勾选
	redStyle := xlsx.NewStyle()
	redStyle.Alignment = alignment
	redStyle.ApplyAlignment = true
	redStyle.Font.Color = "ff0000"
	//定义底色需要标黄的 单元格颜色
	redFill := xlsx.Fill{"solid", "ffff00", "ffff00"}
	redStyle.Fill = redFill
	redStyle.Border = *border

	//标题样式
	titleStyle := xlsx.NewStyle()
	titleFont := xlsx.NewFont(14, "宋体")
	titleFont.Bold = true
	titleStyle.Font = *titleFont
	titleStyle.Alignment = alignment
	titleStyle.Border = *border

	//titleStyle.ApplyAlignment = true

	//表头
	headerStyle := xlsx.NewStyle()
	headerFont := xlsx.NewFont(12, "宋体")
	headerFont.Bold = true
	headerStyle.Font = *headerFont
	headerStyle.Alignment = alignment
	headerStyle.ApplyAlignment = true
	headerStyle.Border = *border

	defer func() {
		os.Remove(downLoadnFilePath)
	}()

	//遍历所拥有的的产品权限，然后插入到对应的sheet表单中
	for pidIndex := 0; pidIndex < len(productSlice); pidIndex++ {
		productId := productSlice[pidIndex]
		//表单名称
		sheetName := "合同数据"
		switch productId {
		case 1:
			sheetName = "ficc合同信息"
		case 2:
			sheetName = "权益合同信息"
		}
		//新增一个sheet表单
		sheel, err := xlsxFile.AddSheet(sheetName)
		if err != nil {
			br.Msg = "新增Sheet失败"
			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
			return
		}
		//设置列宽
		sheel.SetColWidth(0, 0, 28)
		sheel.SetColWidth(1, 1, 30)
		sheel.SetColWidth(2, 2, 18)
		sheel.SetColWidth(3, 3, 18)
		sheel.SetColWidth(4, 4, 35)
		sheel.SetColWidth(5, 6, 20)
		sheel.SetColWidth(7, 7, 40)
		//合同信息列
		endContractInfoColIndex := 9
		sheel.SetColWidth(8, 8, 40)
		sheel.SetColWidth(9, 9, 40)
		//权限列
		sheel.SetColWidth(endContractInfoColIndex, endContractInfoColIndex+18, 30)

		//标题行
		titleRow := sheel.AddRow()
		titleRow.SetHeight(30)

		//合同信息列
		titleCell := titleRow.AddCell()
		titleCell.HMerge = 7 //向右合并列数，不包括自身列
		//遍历去添加需要合并的列
		for i := 0; i < 7; i++ {
			titleRow.AddCell()
		}

		//报表标题名称
		titleCell.SetValue("合同信息")
		titleCell.SetStyle(titleStyle)

		startI := 8
		customStartCellI := 8

		serviceSlice := make([]string, 0)
		serviceCellMap := make(map[string]int)

		//获取所有套餐列表
		{
			serviceList, err := getServiceTemplateList(productId)
			if err != nil {
				br.Msg = "查询套餐类型失败"
				br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
				return
			}
			for i := 0; i < len(serviceList); i++ {
				//需要向右合并添加的列数
				addCellNum := 0

				item := serviceList[i]
				//套餐服务列
				servicesCell := titleRow.AddCell()
				//套餐名称
				servicesCell.SetValue(item.Title)
				servicesCell.SetStyle(titleStyle)

				//ficc小套餐
				if item.ServiceTemplateId == 2 {
					productPermission := make(map[int]string)
					productPermission[1] = "每日宏观商品复盘"
					productPermission[2] = "能化专栏《化里化外》"
					productPermission[3] = "股债日评"
					productPermission[4] = "黑色专栏《知白守黑》"
					productPermission[5] = "有色专栏《有声有色》"
					for id, name := range productPermission {
						key := fmt.Sprint(item.ServiceTemplateId, "_product_permission_", id)
						serviceCellMap[key] = startI
						serviceSlice = append(serviceSlice, name)
						startI++
						addCellNum++
					}

					permissionList := make([]*company.PermissionSetItem, 0)
					allPermissions, permissionMap, e := services.GetBaseFiccPermissionSetItem()
					if e != nil {
						br.Msg = "查询基础权限失败"
						br.ErrMsg = "查询基础权限失败,Err:" + e.Error()
						return
					}
					//遍历获取
					for _, v := range allPermissions {
						if v.ParentId == 0 {
							items, ok := permissionMap[v.ChartPermissionId]
							if ok {
								permissionList = append(permissionList, items...)
							}
						}
					}
					/*for _, v := range utils.PermissionFiccClassifyArr {
						items, err := company.GetPermissionSetItems(1, v)
						if err != nil {
							br.Msg = "获取失败"
							br.ErrMsg = "获取权限信息失败，Err:" + err.Error()
							return
						}
						permissionList = append(permissionList, items...)
					}*/

					//权限列表
					for j := 0; j < len(permissionList); j++ {
						key := fmt.Sprint(item.ServiceTemplateId, "_permission_", permissionList[j].ChartPermissionId)
						serviceCellMap[key] = startI
						serviceSlice = append(serviceSlice, permissionList[j].PermissionName)
						startI++
						addCellNum++
					}
					//因为自己本身有一列了，所以在最后增加列的时候，需要减去自身列
					addCellNum = addCellNum - 1
					if addCellNum > 0 {
						for tmpAddCellNum := 0; tmpAddCellNum < addCellNum; tmpAddCellNum++ {
							titleRow.AddCell()
						}
						servicesCell.HMerge = addCellNum //向右合并列数，不包括自身列
					}
					continue
				} else {
					if item.Children != nil && len(item.Children) > 0 {
						for j := 0; j < len(item.Children); j++ {
							key := fmt.Sprint("service_template_", item.Children[j].ServiceTemplateId)
							serviceCellMap[key] = startI
							serviceSlice = append(serviceSlice, item.Children[j].Title)
							startI++
							addCellNum++
						}
						//因为自己本身有一列了，所以在最后增加列的时候，需要减去自身列
						addCellNum = addCellNum - 1
						if addCellNum > 0 {
							for tmpAddCellNum := 0; tmpAddCellNum < addCellNum; tmpAddCellNum++ {
								titleRow.AddCell()
							}
							servicesCell.HMerge = addCellNum //向右合并列数，不包括自身列
						}
					} else {
						key := fmt.Sprint("service_template_", item.ServiceTemplateId)
						serviceCellMap[key] = startI
						serviceSlice = append(serviceSlice, item.Title)
						startI++
					}
				}
			}
		}

		//表头
		headerRow := sheel.AddRow()
		headerRow.SetHeight(24)

		//合同基础信息
		{
			codeHeaderCell := headerRow.AddCell()
			codeHeaderCell.SetValue("合同编号")
			codeHeaderCell.SetStyle(headerStyle)

			companyHeaderCell := headerRow.AddCell()
			companyHeaderCell.SetValue("客户名称")
			companyHeaderCell.SetStyle(headerStyle)

			typeHeaderCell := headerRow.AddCell()
			typeHeaderCell.SetValue("合同类型")
			typeHeaderCell.SetStyle(headerStyle)

			priceHeaderCell := headerRow.AddCell()
			priceHeaderCell.SetValue("合同金额")
			priceHeaderCell.SetStyle(headerStyle)

			dateHeaderCell := headerRow.AddCell()
			dateHeaderCell.SetValue("合同有效期")
			dateHeaderCell.SetStyle(headerStyle)

			sellerHeaderCell := headerRow.AddCell()
			sellerHeaderCell.SetValue("销售")
			sellerHeaderCell.SetStyle(headerStyle)

			payHeaderCell := headerRow.AddCell()
			payHeaderCell.SetValue("付款方")
			payHeaderCell.SetStyle(headerStyle)

			useHeaderCell := headerRow.AddCell()
			useHeaderCell.SetValue("实际使用方")
			useHeaderCell.SetStyle(headerStyle)

			statusHeaderCell := headerRow.AddCell()
			statusHeaderCell.SetValue("合同状态")
			statusHeaderCell.SetStyle(headerStyle)

			remarkHeaderCell := headerRow.AddCell()
			remarkHeaderCell.SetValue("备注")
			remarkHeaderCell.SetStyle(headerStyle)
		}

		//添加服务套餐名称
		for _, service := range serviceSlice {
			cell := headerRow.AddCell()
			cell.SetValue(service)
			cell.SetStyle(headerStyle)
		}

		for _, v := range list {
			//如果当前合同不是该产品
			if v.ProductId != productId {
				continue
			}
			dataRow := sheel.AddRow()
			dataRow.SetHeight(24)

			//合同基础信息
			{
				codeCell := dataRow.AddCell()
				codeCell.SetValue(v.ContractCode)
				codeCell.SetStyle(style)

				companyCell := dataRow.AddCell()
				companyCell.SetValue(v.CompanyName)
				companyCell.SetStyle(style)

				typeCell := dataRow.AddCell()
				typeCell.SetValue(v.ContractType)
				typeCell.SetStyle(style)

				priceCell := dataRow.AddCell()
				priceCell.SetValue(v.Price)
				priceCell.SetStyle(style)

				dateCell := dataRow.AddCell()
				dateCell.SetValue(fmt.Sprint(v.StartDate.Format(utils.FormatDate), " 至 ", v.EndDate.Format(utils.FormatDate)))
				dateCell.SetStyle(style)

				sellerCell := dataRow.AddCell()
				sellerCell.SetValue(v.SellerName)
				sellerCell.SetStyle(style)

				//付款方
				payStr := v.PayChannel
				payCell := dataRow.AddCell()
				if v.ContractBusinessType == "业务合同" {
					if relationContractList, ok := contractRelationMap[v.ContractId]; ok {
						payCompanyNameList := make([]string, 0)
						for _, relationContract := range relationContractList {
							payCompanyNameList = append(payCompanyNameList, relationContract.CompanyName)
						}
						payStr = strings.Join(payCompanyNameList, ",")
					}
				} else {
					payStr = v.CompanyName
				}
				payCell.SetValue(payStr)
				payCell.SetStyle(style)

				//使用方
				useStr := ``
				useCell := dataRow.AddCell()
				if v.ContractBusinessType == "代付合同" {
					if relationContractList, ok := contractRelationMap[v.ContractId]; ok {
						payCompanyNameList := make([]string, 0)
						for _, relationContract := range relationContractList {
							payCompanyNameList = append(payCompanyNameList, relationContract.CompanyName)
						}
						useStr = strings.Join(payCompanyNameList, ",")
					}
				} else {
					useStr = v.CompanyName
				}
				useCell.SetValue(useStr)
				useCell.SetStyle(style)

				statusCell := dataRow.AddCell()
				statusCell.SetValue(v.Status)
				statusCell.SetStyle(style)

				//备注：该字段由三部分拼接：服务内容中的补充内容+赠送时间+优惠金额
				//补充内容直接取该字段内容；
				//赠送时间以年为单位，超过整年的月份作为赠送月份，如14个月即为赠送2个月；
				//优惠金额等于原价-优惠后价格=优惠价格

				//补充内容
				var remark string
				if v.Remark != "" {
					remark += "补充内容：" + v.Remark
				}

				//赠送时间
				//合同结束日期与合同开始日期的时间差（小时差）
				newDecimal := decimal.NewFromFloat(v.EndDate.Sub(v.StartDate).Hours())
				//分母为365天 * 24 小时
				newDecimal2 := decimal.NewFromInt(24 * 365)
				//计算出来相差多少年，保留一位小数（四舍五入）
				numYearDecimal := newDecimal.Div(newDecimal2).Round(1).Mul(decimal.NewFromInt(10))
				//如果大于1年，那么才去判断是否赠送
				numYear, _ := numYearDecimal.Float64()
				if numYear > 10 {
					//获取多出来的整数年数据
					numYearDecimal = numYearDecimal.Mod(decimal.NewFromInt(10)).Div(decimal.NewFromInt(10))
					//计算赠送出来的月份
					numMonthDecimal := numYearDecimal.Mul(decimal.NewFromInt(12)).Round(0)
					numMonth, _ := numMonthDecimal.Float64()
					if numMonth > 0 {
						if remark != "" {
							remark += "；"
						}
						remark += "赠送时间为：" + numMonthDecimal.String() + "个月"
					}
				}

				//优惠金额
				if v.OriginalPrice > v.Price {
					differencePrice := v.OriginalPrice - v.Price
					differencePriceDecimal := decimal.NewFromFloat(differencePrice)

					if remark != "" {
						remark += "；"
					}
					remark += "优惠金额：" + differencePriceDecimal.String() + "元。"
				}
				remarkCell := dataRow.AddCell()
				remarkCell.SetValue(remark)
				remarkCell.SetStyle(style)
			}

			//服务套餐
			{
				cellServiceMap := make(map[int]string)
				for _, cellI := range serviceCellMap {
					cellServiceMap[cellI] = "否"
				}

				//如果没有服务那么就进入下一个循环
				tmpService, ok := serviceListMap[v.ContractId]
				if !ok {
					continue
				}
				if tmpService != nil && len(tmpService) > 0 {
					permissionValues := []string{
						"FICC周报", "商品双周报+线上电话会讨论会<br/>（由弘则的研究员主持线上讨论）", "数据点评", "深度月报：包括宏观经济月报和下游草根调研月报+电话会讨论会<br/>（由弘则的研究员主持线上讨论）",
					}
					for _, item := range tmpService {
						//ficc小套餐
						if item.ServiceTemplateId == 2 {
							for _, detail := range item.DetailList {
								var tableCel request.AddContractServiceDetailReq
								tmpErr := json.Unmarshal([]byte(detail.Col1), &tableCel)
								if tmpErr != nil {
									err = tmpErr
									return
								}
								if tableCel.Value == "商品复盘" {
									var tableCel2 request.AddContractServiceDetailReq
									//获取品种列数据
									tmpErr := contractService.GetProductCelData(*detail, &tableCel2)
									if tmpErr != nil {
										err = tmpErr
										return
									}
									//tableCel2.Tag
									for _, serviceId := range tableCel2.ValueId {
										key := fmt.Sprint(item.ServiceTemplateId, "_product_permission_", serviceId)
										if cellI, ok := serviceCellMap[key]; ok {
											cellServiceMap[cellI] = "是"
										}
									}

								} else if strings.Contains(strings.Join(permissionValues, ","), tableCel.Value) {
									//获取品种列数据
									var tableCel2 request.AddContractServiceDetailReq
									tmpErr := contractService.GetProductCelData(*detail, &tableCel2)
									if tmpErr != nil {
										err = tmpErr
										return
									}
									for _, serviceId := range tableCel2.ValueId {
										key := fmt.Sprint(item.ServiceTemplateId, "_permission_", serviceId)
										if cellI, ok := serviceCellMap[key]; ok {
											cellServiceMap[cellI] = "是"
										}
									}
								}
							}
						} else {
							key := fmt.Sprint("service_template_", item.ServiceTemplateId)
							if cellI, ok := serviceCellMap[key]; ok {
								cellServiceMap[cellI] = "是"
							}
						}
					}
				}

				//遍历所有套餐
				for tmpStartCellI := customStartCellI; tmpStartCellI < startI; tmpStartCellI++ {
					servicesCell := dataRow.AddCell()
					cellValue, ok := cellServiceMap[tmpStartCellI]
					if ok == false {
						cellValue = "否"
					}
					servicesCell.SetValue(cellValue)
					if cellValue == "是" { //勾选了话，标红处理
						servicesCell.SetStyle(redStyle)
					} else {
						servicesCell.SetStyle(style)
					}
				}
			}

		}
	}
	err = xlsxFile.Save(downLoadnFilePath)
	if err != nil {
		br.Msg = "保存文件失败"
		br.ErrMsg = "保存文件失败"
		return
	}
	randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
	downloadFileName := "合同列表" + randStr + ".xlsx"
	this.Ctx.Output.Download(downLoadnFilePath, downloadFileName)
	br.Ret = 200
	br.Success = true
	br.Msg = "导出成功"
}

// @Title 合同列表数据导出
// @Description 合同列表数据导出接口
// @Description 合同列表接口
// @Param   ContractType   query   string  false       "合同类型，枚举值：'新签合同','续约合同','补充协议'"
// @Param   ContractStatus   query   string  false       "合同状态，枚举值：'待提交','待审批','已撤回','已审批','已驳回','已作废'"
// @Param   ProductId   query   int  false       "客户类型：传0或者不传为当前账号权限,1 代表是：ficc；2 代表是：权益"
// @Param   ModifyStartTime   query   string  false       "服务更新时间的选择开始时间，格式：2021-05-23 00:00:00"
// @Param   ModifyEndTime   query   string  false       "服务更新时间的选择结束时间，格式：2021-05-26 23:59:59"
// @Param   SellerId   query   string  false       "选择的销售id"
// @Param   Keyword   query   string  false       "搜索关键字"
// @Success 200 {object} response.ContractListResp
// @router /approval/export [get]
func (this *ContractApprovalController) Export() {
	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
	}

	contractType := this.GetString("ContractType")
	contractStatus := this.GetString("ContractStatus")
	productId, _ := this.GetInt("ProductId")
	modifyStartTime := this.GetString("ModifyStartTime")
	modifyEndTime := this.GetString("ModifyEndTime")
	sellerIds := this.GetString("SellerId")
	keyword := this.GetString("Keyword")

	condition := ""
	pars := make([]interface{}, 0)

	//如果不是超管或者合规，那么只能查看自己的合同
	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_ADMIN {
		condition += ` AND product_id = 1 AND status not in ("待提交","已撤回") `
	} else if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_ADMIN {
		condition += ` AND product_id = 2 AND status not in ("待提交","已撤回") `
	} else {
		if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_COMPLIANCE && sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
			condition += ` AND seller_id = ? `
			pars = append(pars, sysUser.AdminId)
		}
	}

	//需要下载的 产品 切片
	productSlice := make([]int, 0)

	//合同类型、、更新时间、所选销售
	//关键字：合同编号、客户名称，社会信用码
	if contractType != "" {
		condition += ` AND contract_type = ? `
		pars = append(pars, contractType)
	}
	//合同状态
	if contractStatus != "" {
		if contractStatus == "已审批" {
			condition += ` AND status in ("已审批","已驳回")  `
		} else {
			condition += ` AND status = ? `
			pars = append(pars, contractStatus)
		}
	} else {
		//condition += ` AND status != "已撤回" `

		condition += ` AND status not in ("已撤回","待提交")  `
	}

	//产品类型
	if productId > 0 {
		condition += ` AND product_id = ? `
		pars = append(pars, productId)

		productSlice = append(productSlice, productId)
	} else {
		nowProductId := services.GetProductId(sysUser.RoleTypeCode)
		if nowProductId > 0 {
			productSlice = append(productSlice, nowProductId)
		} else {
			productSlice = append(productSlice, 1)
			productSlice = append(productSlice, 2)
		}
	}
	//所选销售
	if sellerIds != "" {
		condition += ` AND seller_id IN (` + sellerIds + `) `
	}
	//更新开始时间
	if modifyStartTime != "" {
		condition += ` AND modify_time >= ? `
		pars = append(pars, modifyStartTime)
	}
	//更新结束时间
	if modifyEndTime != "" {
		condition += ` AND modify_time <= ? `
		pars = append(pars, modifyEndTime)
	}
	//关键字
	if keyword != "" {
		condition += ` AND (contract_code LIKE '%` + keyword + `%' OR company_name LIKE '%` + keyword + `%' OR credit_code LIKE '%` + keyword + `%' ) `
	}

	//取 一万 条合同数据
	list, err := contract.GetContractList(condition, "", pars, 0, 10000)
	if err != nil {
		br.Msg = "获取合同列表失败！"
		br.ErrMsg = "获取合同列表失败，Err:" + err.Error()
		return
	}
	//获取合同套餐服务列表
	serviceTemplateList, err := contract.GetAllContractServiceTemplateList()
	if err != nil {
		br.Msg = "获取合同套餐服务列表失败！"
		br.ErrMsg = "获取合同套餐服务列表失败，Err:" + err.Error()
		return
	}
	templateTitleMap := make(map[int]string)
	for _, serviceTemplate := range serviceTemplateList {
		templateTitleMap[serviceTemplate.ServiceTemplateId] = serviceTemplate.Title
	}

	for i := 0; i < len(list); i++ {
		item := list[i]
		list[i].StartDateStr = item.StartDate.Format(utils.FormatDate)
		list[i].EndDateStr = item.EndDate.Format(utils.FormatDate)

		list[i].CreateTimeStr = item.CreateTime.Format(utils.FormatDateTime)
		list[i].ModifyTimeStr = item.ModifyTime.Format(utils.FormatDateTime)

		//服务列表
		serviceList, err := contract.GetContractServiceAndDetailList(item.ContractId)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "查找合同服务异常，Err:" + err.Error()
			return
		}
		for i := 0; len(serviceList) > i; i++ {
			if serviceList[i].HasDetail == "是" {
				list, detailErr := contract.GetContractServiceDetailListByServiceId(serviceList[i].ContractServiceId)
				if detailErr != nil {
					br.Msg = "获取失败"
					br.ErrMsg = "查找合同服务详情异常，Err:" + err.Error()
					return
				}

				//套餐名称
				serviceList[i].DetailList = list
				if title, ok := templateTitleMap[serviceList[i].ServiceTemplateId]; ok {
					serviceList[i].Title = title
				}
			}
		}
		list[i].Service = serviceList
	}

	//生成excel文件
	dir, err := os.Executable()
	exPath := filepath.Dir(dir)
	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
	xlsxFile := xlsx.NewFile()
	if err != nil {
		br.Msg = "生成文件失败"
		br.ErrMsg = "生成文件失败"
		return
	}

	//设置默认字体和文字大小
	xlsx.SetDefaultFont(12, "宋体")

	//定义边框样式
	border := xlsx.NewBorder("thin", "thin", "thin", "thin")
	//定义文字排版样式
	alignment := xlsx.Alignment{
		Horizontal: "center",
		Vertical:   "center",
		WrapText:   true,
	}

	//普通样式
	style := xlsx.NewStyle()
	style.Alignment = alignment
	style.ApplyAlignment = true
	style.Border = *border

	//标红文字，便于查看哪些产品被勾选
	redStyle := xlsx.NewStyle()
	redStyle.Alignment = alignment
	redStyle.ApplyAlignment = true
	redStyle.Font.Color = "ff0000"
	//定义底色需要标黄的 单元格颜色
	redFill := xlsx.Fill{"solid", "ffff00", "ffff00"}
	redStyle.Fill = redFill
	redStyle.Border = *border

	//标题样式
	titleStyle := xlsx.NewStyle()
	titleFont := xlsx.NewFont(14, "宋体")
	titleFont.Bold = true
	titleStyle.Font = *titleFont
	titleStyle.Alignment = alignment
	titleStyle.Border = *border

	//titleStyle.ApplyAlignment = true

	//表头
	headerStyle := xlsx.NewStyle()
	headerFont := xlsx.NewFont(12, "宋体")
	headerFont.Bold = true
	headerStyle.Font = *headerFont
	headerStyle.Alignment = alignment
	headerStyle.ApplyAlignment = true
	headerStyle.Border = *border

	defer func() {
		os.Remove(downLoadnFilePath)
	}()

	//遍历所拥有的的产品权限，然后插入到对应的sheet表单中
	for pidIndex := 0; pidIndex < len(productSlice); pidIndex++ {
		productId = productSlice[pidIndex]
		//表单名称
		sheetName := "合同数据"
		switch productId {
		case 1:
			sheetName = "ficc合同信息"
		case 2:
			sheetName = "权益合同信息"
		}
		//新增一个sheet表单
		sheel, err := xlsxFile.AddSheet(sheetName)
		if err != nil {
			br.Msg = "新增Sheet失败"
			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
			return
		}
		//设置列宽
		sheel.SetColWidth(0, 0, 28)
		sheel.SetColWidth(1, 1, 30)
		sheel.SetColWidth(2, 2, 18)
		sheel.SetColWidth(3, 3, 18)
		sheel.SetColWidth(4, 4, 35)
		sheel.SetColWidth(5, 6, 20)
		sheel.SetColWidth(7, 7, 40)
		sheel.SetColWidth(7, 35, 30)

		//标题行
		titleRow := sheel.AddRow()
		titleRow.SetHeight(30)

		//合同信息列
		titleCell := titleRow.AddCell()
		titleCell.HMerge = 7 //向右合并列数，不包括自身列
		//遍历去添加需要合并的列
		for i := 0; i < 7; i++ {
			titleRow.AddCell()
		}

		//报表标题名称
		titleCell.SetValue("合同信息")
		titleCell.SetStyle(titleStyle)

		startI := 8
		customStartCellI := 8

		serviceSlice := make([]string, 0)
		serviceCellMap := make(map[string]int)

		//获取所有套餐列表
		{
			serviceList, err := getServiceTemplateList(productId)
			if err != nil {
				br.Msg = "查询套餐类型失败"
				br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
				return
			}
			for i := 0; i < len(serviceList); i++ {
				//需要向右合并添加的列数
				addCellNum := 0

				item := serviceList[i]
				//套餐服务列
				servicesCell := titleRow.AddCell()
				//套餐名称
				servicesCell.SetValue(item.Title)
				servicesCell.SetStyle(titleStyle)

				//ficc小套餐
				if item.ServiceTemplateId == 2 {
					productPermission := make(map[int]string)
					productPermission[1] = "每日宏观商品复盘"
					productPermission[2] = "能化专栏《化里化外》"
					productPermission[3] = "股债日评"
					productPermission[4] = "黑色专栏《知白守黑》"
					productPermission[5] = "有色专栏《有声有色》"
					for id, name := range productPermission {
						key := fmt.Sprint(item.ServiceTemplateId, "_product_permission_", id)
						serviceCellMap[key] = startI
						serviceSlice = append(serviceSlice, name)
						startI++
						addCellNum++
					}

					permissionList := make([]*company.PermissionSetItem, 0)
					allPermissions, permissionMap, e := services.GetBaseFiccPermissionSetItem()
					if e != nil {
						br.Msg = "查询基础权限失败"
						br.ErrMsg = "查询基础权限失败,Err:" + e.Error()
						return
					}
					//遍历获取
					for _, v := range allPermissions {
						if v.ParentId == 0 {
							items, ok := permissionMap[v.ChartPermissionId]
							if ok {
								permissionList = append(permissionList, items...)
							}
						}
					}
					/*for _, v := range utils.PermissionFiccClassifyArr {
						items, err := company.GetPermissionSetItems(1, v)
						if err != nil {
							br.Msg = "获取失败"
							br.ErrMsg = "获取权限信息失败，Err:" + err.Error()
							return
						}
						permissionList = append(permissionList, items...)
					}
					*/
					//权限列表
					for j := 0; j < len(permissionList); j++ {
						key := fmt.Sprint(item.ServiceTemplateId, "_permission_", permissionList[j].ChartPermissionId)
						serviceCellMap[key] = startI
						serviceSlice = append(serviceSlice, permissionList[j].PermissionName)
						startI++
						addCellNum++
					}
					//因为自己本身有一列了，所以在最后增加列的时候，需要减去自身列
					addCellNum = addCellNum - 1
					if addCellNum > 0 {
						for tmpAddCellNum := 0; tmpAddCellNum < addCellNum; tmpAddCellNum++ {
							titleRow.AddCell()
						}
						servicesCell.HMerge = addCellNum //向右合并列数，不包括自身列
					}
					continue
				} else {
					if item.Children != nil && len(item.Children) > 0 {
						for j := 0; j < len(item.Children); j++ {
							key := fmt.Sprint("service_template_", item.Children[j].ServiceTemplateId)
							serviceCellMap[key] = startI
							serviceSlice = append(serviceSlice, item.Children[j].Title)
							startI++
							addCellNum++
						}
						//因为自己本身有一列了，所以在最后增加列的时候，需要减去自身列
						addCellNum = addCellNum - 1
						if addCellNum > 0 {
							for tmpAddCellNum := 0; tmpAddCellNum < addCellNum; tmpAddCellNum++ {
								titleRow.AddCell()
							}
							servicesCell.HMerge = addCellNum //向右合并列数，不包括自身列
						}
					} else {
						key := fmt.Sprint("service_template_", item.ServiceTemplateId)
						serviceCellMap[key] = startI
						serviceSlice = append(serviceSlice, item.Title)
						startI++
					}
				}
			}
		}

		//表头
		headerRow := sheel.AddRow()
		headerRow.SetHeight(24)

		//合同基础信息
		{
			codeHeaderCell := headerRow.AddCell()
			codeHeaderCell.SetValue("合同编号")
			codeHeaderCell.SetStyle(headerStyle)

			companyHeaderCell := headerRow.AddCell()
			companyHeaderCell.SetValue("客户名称")
			companyHeaderCell.SetStyle(headerStyle)

			typeHeaderCell := headerRow.AddCell()
			typeHeaderCell.SetValue("合同类型")
			typeHeaderCell.SetStyle(headerStyle)

			priceHeaderCell := headerRow.AddCell()
			priceHeaderCell.SetValue("合同金额")
			priceHeaderCell.SetStyle(headerStyle)

			dateHeaderCell := headerRow.AddCell()
			dateHeaderCell.SetValue("合同有效期")
			dateHeaderCell.SetStyle(headerStyle)

			sellerHeaderCell := headerRow.AddCell()
			sellerHeaderCell.SetValue("销售")
			sellerHeaderCell.SetStyle(headerStyle)

			statusHeaderCell := headerRow.AddCell()
			statusHeaderCell.SetValue("合同状态")
			statusHeaderCell.SetStyle(headerStyle)

			remarkHeaderCell := headerRow.AddCell()
			remarkHeaderCell.SetValue("备注")
			remarkHeaderCell.SetStyle(headerStyle)
		}

		//添加服务套餐名称
		for _, service := range serviceSlice {
			cell := headerRow.AddCell()
			cell.SetValue(service)
			cell.SetStyle(headerStyle)
		}

		for _, v := range list {
			//如果当前合同不是该产品
			if v.ProductId != productId {
				continue
			}
			dataRow := sheel.AddRow()
			dataRow.SetHeight(24)

			//合同基础信息
			{
				codeCell := dataRow.AddCell()
				codeCell.SetValue(v.ContractCode)
				codeCell.SetStyle(style)

				companyCell := dataRow.AddCell()
				companyCell.SetValue(v.CompanyName)
				companyCell.SetStyle(style)

				typeCell := dataRow.AddCell()
				typeCell.SetValue(v.ContractType)
				typeCell.SetStyle(style)

				priceCell := dataRow.AddCell()
				priceCell.SetValue(v.Price)
				priceCell.SetStyle(style)

				dateCell := dataRow.AddCell()
				dateCell.SetValue(fmt.Sprint(v.StartDate.Format(utils.FormatDate), " 至 ", v.EndDate.Format(utils.FormatDate)))
				dateCell.SetStyle(style)

				sellerCell := dataRow.AddCell()
				sellerCell.SetValue(v.SellerName)
				sellerCell.SetStyle(style)

				statusCell := dataRow.AddCell()
				statusCell.SetValue(v.Status)
				statusCell.SetStyle(style)

				//备注：该字段由三部分拼接：服务内容中的补充内容+赠送时间+优惠金额
				//补充内容直接取该字段内容；
				//赠送时间以年为单位，超过整年的月份作为赠送月份，如14个月即为赠送2个月；
				//优惠金额等于原价-优惠后价格=优惠价格

				//补充内容
				var remark string
				if v.Remark != "" {
					remark += "补充内容：" + v.Remark
				}

				//赠送时间
				//合同结束日期与合同开始日期的时间差（小时差）
				newDecimal := decimal.NewFromFloat(v.EndDate.Sub(v.StartDate).Hours())
				//分母为365天 * 24 小时
				newDecimal2 := decimal.NewFromInt(24 * 365)
				//计算出来相差多少年，保留一位小数（四舍五入）
				numYearDecimal := newDecimal.Div(newDecimal2).Round(1).Mul(decimal.NewFromInt(10))
				//如果大于1年，那么才去判断是否赠送
				numYear, _ := numYearDecimal.Float64()
				if numYear > 10 {
					//获取多出来的整数年数据
					numYearDecimal = numYearDecimal.Mod(decimal.NewFromInt(10)).Div(decimal.NewFromInt(10))
					//计算赠送出来的月份
					numMonthDecimal := numYearDecimal.Mul(decimal.NewFromInt(12)).Round(0)
					numMonth, _ := numMonthDecimal.Float64()
					if numMonth > 0 {
						if remark != "" {
							remark += "；"
						}
						remark += "赠送时间为：" + numMonthDecimal.String() + "个月"
					}
				}

				//优惠金额
				if v.OriginalPrice > v.Price {
					differencePrice := v.OriginalPrice - v.Price
					differencePriceDecimal := decimal.NewFromFloat(differencePrice)

					if remark != "" {
						remark += "；"
					}
					remark += "优惠金额：" + differencePriceDecimal.String() + "元。"
				}
				remarkCell := dataRow.AddCell()
				remarkCell.SetValue(remark)
				remarkCell.SetStyle(style)
			}

			//服务套餐
			{
				cellServiceMap := make(map[int]string)
				for _, cellI := range serviceCellMap {
					cellServiceMap[cellI] = "否"
				}

				if v.Service != nil && len(v.Service) > 0 {
					permissionValues := []string{
						"FICC周报", "商品双周报+线上电话会讨论会<br/>（由弘则的研究员主持线上讨论）", "数据点评", "深度月报：包括宏观经济月报和下游草根调研月报+电话会讨论会<br/>（由弘则的研究员主持线上讨论）",
					}
					for _, item := range v.Service {
						//ficc小套餐
						if item.ServiceTemplateId == 2 {
							for _, detail := range item.DetailList {
								var tableCel request.AddContractServiceDetailReq
								tmpErr := json.Unmarshal([]byte(detail.Col1), &tableCel)
								if tmpErr != nil {
									err = tmpErr
									return
								}
								if tableCel.Value == "商品复盘" {
									var tableCel2 request.AddContractServiceDetailReq
									//获取品种列数据
									tmpErr := contractService.GetProductCelData(*detail, &tableCel2)
									if tmpErr != nil {
										err = tmpErr
										return
									}
									//tableCel2.Tag
									for _, serviceId := range tableCel2.ValueId {
										key := fmt.Sprint(item.ServiceTemplateId, "_product_permission_", serviceId)
										if cellI, ok := serviceCellMap[key]; ok {
											cellServiceMap[cellI] = "是"
										}
									}

								} else if strings.Contains(strings.Join(permissionValues, ","), tableCel.Value) {
									//获取品种列数据
									var tableCel2 request.AddContractServiceDetailReq
									tmpErr := contractService.GetProductCelData(*detail, &tableCel2)
									if tmpErr != nil {
										err = tmpErr
										return
									}
									for _, serviceId := range tableCel2.ValueId {
										key := fmt.Sprint(item.ServiceTemplateId, "_permission_", serviceId)
										if cellI, ok := serviceCellMap[key]; ok {
											cellServiceMap[cellI] = "是"
										}
									}
								}
							}
						} else {
							key := fmt.Sprint("service_template_", item.ServiceTemplateId)
							if cellI, ok := serviceCellMap[key]; ok {
								cellServiceMap[cellI] = "是"
							}
						}
					}
				}

				//遍历所有套餐
				for tmpStartCellI := customStartCellI; tmpStartCellI < startI; tmpStartCellI++ {
					servicesCell := dataRow.AddCell()
					cellValue, ok := cellServiceMap[tmpStartCellI]
					if ok == false {
						cellValue = "否"
					}
					servicesCell.SetValue(cellValue)
					if cellValue == "是" { //勾选了话，标红处理
						servicesCell.SetStyle(redStyle)
					} else {
						servicesCell.SetStyle(style)
					}
				}
			}

		}
	}
	err = xlsxFile.Save(downLoadnFilePath)
	if err != nil {
		br.Msg = "保存文件失败"
		br.ErrMsg = "保存文件失败"
		return
	}
	randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
	downloadFileName := "合同列表" + randStr + ".xlsx"
	this.Ctx.Output.Download(downLoadnFilePath, downloadFileName)
	br.Ret = 200
	br.Success = true
	br.Msg = "导出成功"
}

// CancelApply
// @Title 撤回审批申请
// @Description 撤回审批申请接口
// @Param   ContractApprovalRecordId   query   int  true       "审批流id编号"
// @Param   ContractId   query   int  true       "合同id编号"
// @Success Ret=200 撤回申请成功
// @router /approval/cancelApply [get]
func (this *ContractApprovalController) CancelApply() {
	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
	}

	//合同id编号
	contractId, err := this.GetInt("ContractId")
	if err != nil {
		br.Msg = "获取审批流编号失败"
		br.ErrMsg = "获取审批流编号失败，err：" + err.Error()
		return
	}

	//审批流id编号
	contractApprovalRecordId, err := this.GetInt("ContractApprovalRecordId", 0)
	if err != nil {
		br.Msg = "获取审批流编号失败"
		br.ErrMsg = "获取审批流编号失败，err：" + err.Error()
		return
	}
	if contractApprovalRecordId <= 0 && contractId <= 0 {
		br.Msg = "请传入审批流编号获取合同编号"
		br.ErrMsg = "请传入审批流编号获取合同编号"
		return
	}
	if contractApprovalRecordId > 0 {
		//获取审批流信息
		contractApprovalRecord, err := contract.GetContractApprovalRecordById(contractApprovalRecordId)
		if err != nil {
			br.Msg = "获取审批流信息失败！"
			br.ErrMsg = "获取审批流信息失败，Err:" + err.Error()
			return
		}
		err = contractService.CancelApply(contractApprovalRecord, sysUser.AdminId)
		if err != nil {
			br.Msg = "撤回申请失败！"
			br.ErrMsg = "撤回申请失败，Err:" + err.Error()
			return
		}
	} else if contractId > 0 {
		//获取审批流信息
		contractInfo, err := contract.GetContractById(contractId)
		if err != nil {
			br.Msg = "获取审批流信息失败！"
			br.ErrMsg = "获取审批流信息失败，Err:" + err.Error()
			return
		}
		err = contractService.CancelApplyByContract(contractInfo, sysUser.AdminId)
		if err != nil {
			br.Msg = "撤回申请失败！"
			br.ErrMsg = "撤回申请失败，Err:" + err.Error()
			return
		}
	} else {
		br.Msg = "请传入审批流编号获取合同编号"
		br.ErrMsg = "请传入审批流编号获取合同编号"
		return
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "撤回申请成功"
}

// @Title 驳回审批
// @Description 驳回审批接口
// @Param	request	body request.RejectReq true "type json string"
// @Success Ret=200 驳回成功
// @router /approval/reject [post]
func (this *ContractApprovalController) Reject() {
	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
	}

	var req request.RejectReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	//审批流id编号
	contractApprovalRecordId := req.ContractApprovalRecordId
	if contractApprovalRecordId <= 0 {
		br.Msg = "请传入审批流编号"
		br.ErrMsg = "请传入审批流编号"
		return
	}

	//获取审批流信息
	contractApprovalRecord, err := contract.GetContractApprovalRecordById(contractApprovalRecordId)
	if err != nil {
		br.Msg = "获取审批流信息失败！"
		br.ErrMsg = "获取审批流信息失败，Err:" + err.Error()
		return
	}
	err = contractService.Reject(contractApprovalRecord, sysUser, req.Remark)
	if err != nil {
		br.Msg = "驳回审批失败！"
		br.ErrMsg = "驳回审批失败，Err:" + err.Error()
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "驳回成功"
}

// @Title 处理审批单
// @Description 处理审批单
// @Param	request	body request.ApprovedReq true "type json string"
// @Success Ret=200 申请成功
// @router /approval/approved [post]
func (this *ContractApprovalController) Approved() {
	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
	}

	var req request.ApprovedReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	//审批流id编号
	contractApprovalRecordId := req.ContractApprovalRecordId
	if contractApprovalRecordId <= 0 {
		br.Msg = "请传入审批流编号"
		br.ErrMsg = "请传入审批流编号"
		return
	}

	//获取审批流信息
	contractApprovalRecord, err := contract.GetContractApprovalRecordById(contractApprovalRecordId)
	if err != nil {
		br.Msg = "获取审批流信息失败！"
		br.ErrMsg = "获取审批流信息失败，Err:" + err.Error()
		return
	}
	err = contractService.Approved(contractApprovalRecord, sysUser, req.Remark)
	if err != nil {
		br.Msg = "审核失败！"
		br.ErrMsg = "审核失败，Err:" + err.Error()
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "审核通过"
}
