package contract

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"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"
	"hongze/fms_api/models/system"
	crmService "hongze/fms_api/services/crm"
	fmsService "hongze/fms_api/services/fms"
	"hongze/fms_api/utils"
	"net/http"
	"strconv"
	"strings"
	"time"
)

// // RegisterController 合同登记
type PreRegisterController struct{}

// InvoiceList
// @Title 预登记列表
// @Description 预登记列表
// @Param   Keyword			query	string	false	"关键词"
// @Success 200 {object} fms.ContractInvoiceItem
// @router /contract/pre_register/list [get]
func (rg *PreRegisterController) List(c *gin.Context) {
	var req fms.PreRegisterListReq
	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
	}
	pageSize := req.PageSize
	pageIndex := req.Current
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if pageIndex <= 0 {
		pageIndex = 1
	}

	cond := ` invoice_type IN (3, 4) `
	pars := make([]interface{}, 0)
	if req.Keyword != "" {
		kw := "%" + req.Keyword + "%"
		cond += ` AND company_name LIKE ? `
		pars = append(pars, kw)
	}
	// 货币列表
	currencyOB := new(fms.CurrencyUnit)
	currencyCond := `enable = 1`
	currencyPars := make([]interface{}, 0)
	currencyList, e := currencyOB.List(currencyCond, currencyPars)
	if e != nil {
		resp.FailMsg("获取失败", "获取货币列表失败, Err: "+e.Error(), c)
		return
	}
	unitMap := make(map[string]string)
	for i := range currencyList {
		unitMap[currencyList[i].Code] = currencyList[i].UnitName
	}

	page := new(base.Page)
	page.SetPageSize(req.PageSize)
	page.SetCurrent(req.Current)
	if req.IsExport == 1 {
		page.SetPageSize(10000)
		page.SetCurrent(1)
	}
	sortTypeMap := map[int]bool{0: false, 1: true, 2: false}
	page.AddOrderItem(base.OrderItem{Column: "create_time", Asc: sortTypeMap[0]})

	total, list, e := fms.GetContractPreRegisterItemPageList(page, cond, pars)
	if e != nil {
		resp.FailMsg("获取失败", "获取预登记列表失败, Err: "+e.Error(), c)
		return
	}
	serviceMap := make(map[int]string, 0)
	registerIds := make([]int, 0)
	for i := range list {
		list[i].UnitName = unitMap[list[i].CurrencyUnit]
		registerIds = append(registerIds, list[i].ContractRegisterId)
	}

	if len(registerIds) > 0 {
		serviceMap, _, e = fmsService.GetContractServiceNameFormat(registerIds)
		if e != nil {
			resp.FailMsg("获取失败", e.Error(), c)
			return
		}
	}

	respList := make([]*fms.ContractPreRegisterList, 0)

	for _, v := range list {
		item := new(fms.ContractPreRegisterList)
		item.ContractPreRegisterItem = v
		item.ServicesName = serviceMap[v.ContractRegisterId]
		if v.HasPayment == 1 {
			//代付
			if v.ContractType == 1 {
				item.ContractTypeString = "代付合同(新签)"
			} else if v.ContractType == 2 {
				item.ContractTypeString = "代付合同(续约)"
			} else {
				item.ContractTypeString = "代付合同(补充)"
			}
		} else {
			if v.ContractType == 1 {
				item.ContractTypeString = "自付合同(新签)"
			} else if v.ContractType == 2 {
				item.ContractTypeString = "自付合同(续约)"
			} else {
				item.ContractTypeString = "自付合同(补充)"
			}
		}
		respList = append(respList, item)
	}

	if req.IsExport == 1 {
		ExportPreRegister(c, list)
		return
	}
	page.SetTotal(total)
	baseData := new(base.BaseData)
	baseData.SetPage(page)
	baseData.SetList(respList)
	resp.OkData("获取成功", baseData, c)
}

// Add
// @Title 新增预登记
// @Description 新增预登记
// @Param	request  body  fms.PrepayAddReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /contract/pre_register/add [post]
func (rg *PreRegisterController) Add(c *gin.Context) {
	req := new(fms.PreRegisterAddReq)
	err := c.ShouldBind(&req)
	if err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
			return
		}
		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
		return
	}
	claims, _ := c.Get("adminInfo")
	adminInfo := claims.(*system.SysAdmin)

	// 日期校验
	var startDate, endDate time.Time
	if req.StartDate != "" && req.EndDate != "" {
		startDate, err = time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
		if err != nil {
			resp.FailMsg("约定开始日期格式有误", "合同开始日期格式有误, Err: "+err.Error(), c)
			return
		}
		endDate, err = time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
		if err != nil {
			resp.FailMsg("约定结束日期格式有误", "合同结束日期格式有误, Err: "+err.Error(), c)
			return
		}
	}

	var currencyUnit string
	if len(req.List) > 0 {
		currencyUnit = req.List[0].CurrencyUnit
	}
	// 获取销售分组信息
	sellerList, e := crmService.GetSellerDepartmentListWithEnable()
	if e != nil {
		resp.FailData("获取销售失败", "Err:"+e.Error(), c)
		return
	}
	sellerMap := make(map[int]*crm.SellerAdminWithGroupTeam)
	for i := range sellerList {
		sellerMap[sellerList[i].SellerId] = sellerList[i]
	}

	admin := new(crm.Admin)
	sellerIds := strings.Split(req.SellerIds, ",")
	if len(sellerIds) > 2 {
		resp.Fail("最多只能选择两个销售", c)
		return
	}

	var sellers []*crm.Admin
	var pars []interface{}
	cond := ``
	if len(sellerIds) > 0 {
		cond = ` admin_id in (?) `
		pars = append(pars, sellerIds)
		sellers, e = admin.List(cond, pars)
		if e != nil {
			resp.FailMsg("获取销售信息失败", "获取销售信息失败, Err: "+e.Error(), c)
			return
		}
	}

	//新增合同
	ob := new(fms.ContractRegister)
	//ob.ContractCode = req.ContractCode
	ob.CompanyName = req.CompanyName
	ob.ProductIds = req.ProductIds
	ob.StartDate = startDate
	ob.EndDate = endDate
	ob.HasInvoice = 1
	ob.Set()
	ob.CurrencyUnit = currencyUnit
	ob.ContractType = req.ContractType
	ob.HasPayment = req.HasPayment
	if req.RegisterType == fms.ContractInvoiceTypePreMake {
		//sellerItem := sellerMap[r.SellerId]
		//if sellerItem == nil {
		//	resp.Fail("销售信息异常", c)
		//	return
		//}
		for _, v := range sellers {
			if v.DepartmentId == crm.SellerDepartmentId {
				ob.SellerId = v.AdminId
				ob.SellerName = v.AdminName
			} else if v.DepartmentId == crm.RaiSellerDepartmentId {
				ob.RaiSellerId = v.AdminId
				ob.RaiSellerName = v.AdminName
			}
		}
	}

	// 套餐信息
	serviceAmountMap := make(map[int]float64)
	serviceList, e := fmsService.HandleContractServiceAndDetail(req.Services, true, serviceAmountMap)
	if e != nil {
		resp.FailMsg("操作失败", "获取合同套餐详情失败, Err: "+e.Error(), c)
		return
	}

	if e = ob.Create(); e != nil {
		resp.FailMsg("操作失败", "新增合同失败, Err: "+e.Error(), c)
		return
	}
	if ob.ContractRegisterId == 0 {
		resp.FailMsg("操作失败", "新增合同失败,合同ID为0", c)
		return
	}

	if e = fms.CreateContractRegisterAndServicesAndPayMent(ob, serviceList); e != nil {
		resp.FailMsg("操作失败", "新增合同及套餐失败, Err: "+e.Error(), c)
		return
	}

	for _, r := range req.List {
		// 货币及汇率
		rateList, e := fmsService.GetTodayCurrencyRateList()
		if e != nil {
			resp.FailMsg("操作失败", "获取今日货币汇率失败, Err: "+e.Error(), c)
			return
		}
		var rate float64
		for i := range rateList {
			if r.CurrencyUnit == rateList[i].Code {
				rate = rateList[i].RMBRate
				break
			}
		}
		if rate <= 0 {
			resp.FailMsg("操作失败", "货币汇率信息有误", c)
			return
		}

		registerDate, e := time.Parse(utils.FormatDate, r.RegisterDate)
		if e != nil {
			resp.FailMsg("日期转换失败", "日期转换失败, Err: "+e.Error(), c)
			return
		}

		v := &fms.ContractInvoice{
			ContractRegisterId: ob.ContractRegisterId,
			OriginAmount:       r.Amount,
			CurrencyUnit:       r.CurrencyUnit,
			InvoiceType:        req.RegisterType,
			InvoiceDate:        registerDate,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			Remark:             r.Remark,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
			TimeBase:           base.TimeBase{},
		}
		v.Set()

		a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", v.OriginAmount/rate), 64)
		v.Amount = a

		sellerItem := sellerMap[r.SellerId]
		if sellerItem == nil {
			resp.Fail("销售信息异常", c)
			return
		}

		v.SellerId = sellerItem.SellerId
		v.SellerName = sellerItem.SellerName
		v.SellerGroupId = sellerItem.GroupId
		v.SellerGroupName = sellerItem.GroupName
		v.SellerTeamId = sellerItem.TeamId
		v.SellerTeamName = sellerItem.TeamName

		// 新增开票到款记录
		if e = v.Create(); e != nil {
			resp.FailMsg("操作失败", "新增预登记失败, Err: "+e.Error(), c)
			return
		}

		//预登记列表
		pp := &fms.ContractPreRegister{
			ContractRegisterId: ob.ContractRegisterId,
			CompanyName:        req.CompanyName,
			InvoiceType:        req.RegisterType,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
			TimeBase:           base.TimeBase{},
		}
		pp.Set()
		pp.CurrencyUnit = r.CurrencyUnit
		pp.ContractType = req.ContractType
		pp.HasPayment = req.HasPayment
		if pp.InvoiceType == fms.ContractInvoiceTypePreMake {
			//开票走开票字段
			pp.InvoiceId = v.ContractInvoiceId
			pp.InvoiceDate = registerDate
			pp.OriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.OriginAmount/rate), 64)
			pp.Amount = a
			pp.Remark = r.Remark
			sellerItem := sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}

			pp.SellerId = sellerItem.SellerId
			pp.SellerName = sellerItem.SellerName
			pp.SellerGroupId = sellerItem.GroupId
			pp.SellerGroupName = sellerItem.GroupName
			pp.SellerTeamId = sellerItem.TeamId
			pp.SellerTeamName = sellerItem.TeamName

			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
		} else {
			//到款
			pp.ArriveId = v.ContractInvoiceId
			pp.ArriveDate = registerDate
			pp.ArriveOriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.ArriveOriginAmount/rate), 64)
			pp.ArriveAmount = a
			pp.ArriveRemark = r.Remark

			sellerItem := sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}
			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
		}

		// 新增开票到款记录
		if pp.ContractRegisterId == 0 {
			resp.FailMsg("操作失败", "新增预登记失败,合同ID为0", c)
			return
		}
		if e = pp.Create(); e != nil {
			resp.FailMsg("操作失败", "新增预登记失败, Err: "+e.Error(), c)
			return
		}

		v.PreRegisterId = pp.PreRegisterId
		if e = v.Update([]string{"PreRegisterId"}); e != nil {
			fmt.Println("更新开票登记失败, Err: " + e.Error())
			return
		}
	}

	// 开票到款汇总
	go fmsService.SummaryInvoicePaymentByContractRegisterId(ob.ContractRegisterId)

	//预登记后更新register表开票到款合计金额
	go fmsService.CheckContractRegisterAmountAfterPre(ob.ContractRegisterId)

	resp.Ok("操作成功", c)
}

// Edit
// @Title 编辑预登记
// @Description 编辑预登记
// @Param	request  body  fms.ContractRegisterEditReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /contract/pre_register/edit [post]
func (rg *PreRegisterController) Edit(c *gin.Context) {
	req := new(fms.PreRegisterEditReq)
	err := c.ShouldBind(&req)
	if err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
			return
		}
		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
		return
	}
	claims, _ := c.Get("adminInfo")
	adminInfo := claims.(*system.SysAdmin)

	// 日期校验
	var startDate, endDate time.Time
	if req.StartDate != "" && req.EndDate != "" {
		startDate, err = time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
		if err != nil {
			resp.FailMsg("约定开始日期格式有误", "合同开始日期格式有误, Err: "+err.Error(), c)
			return
		}
		endDate, err = time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
		if err != nil {
			resp.FailMsg("约定结束日期格式有误", "合同结束日期格式有误, Err: "+err.Error(), c)
			return
		}
	}

	var currencyUnit string
	if len(req.List) > 0 {
		currencyUnit = req.List[0].CurrencyUnit
	}
	// 获取销售分组信息
	sellerList, e := crmService.GetSellerDepartmentListWithEnable()
	if e != nil {
		resp.FailData("获取销售失败", "Err:"+e.Error(), c)
		return
	}
	sellerMap := make(map[int]*crm.SellerAdminWithGroupTeam)
	for i := range sellerList {
		sellerMap[sellerList[i].SellerId] = sellerList[i]
	}

	admin := new(crm.Admin)
	sellerIds := strings.Split(req.SellerIds, ",")
	if len(sellerIds) > 2 {
		resp.Fail("最多只能选择两个销售", c)
		return
	}
	var sellers []*crm.Admin
	var pars []interface{}
	cond := ``
	if len(sellerIds) > 0 {
		cond = ` admin_id in (?) `
		pars = append(pars, sellerIds)
		sellers, e = admin.List(cond, pars)
		if e != nil {
			resp.FailMsg("获取销售信息失败", "获取销售信息失败, Err: "+e.Error(), c)
			return
		}
	}

	//修改合同
	ob := new(fms.ContractRegister)
	//ob.ContractCode = req.ContractCode
	ob.ContractRegisterId = req.ContractRegisterId
	ob.CompanyName = req.CompanyName
	ob.ProductIds = req.ProductIds
	ob.StartDate = startDate
	ob.EndDate = endDate
	ob.ModifyTime = time.Now().Local()
	ob.CurrencyUnit = currencyUnit
	ob.ContractType = req.ContractType
	ob.HasPayment = req.HasPayment
	if req.RegisterType == fms.ContractInvoiceTypePreMake {
		//sellerItem := sellerMap[r.SellerId]
		//if sellerItem == nil {
		//	resp.Fail("销售信息异常", c)
		//	return
		//}
		for _, v := range sellers {
			if v.DepartmentId == crm.SellerDepartmentId {
				ob.SellerId = v.AdminId
				ob.SellerName = v.AdminName
			} else if v.DepartmentId == crm.RaiSellerDepartmentId {
				ob.RaiSellerId = v.AdminId
				ob.RaiSellerName = v.AdminName
			}
		}
	}

	// 套餐信息
	serviceAmountMap := make(map[int]float64)
	serviceList, e := fmsService.HandleContractServiceAndDetail(req.Services, true, serviceAmountMap)
	if e != nil {
		resp.FailMsg("操作失败", "获取合同套餐详情失败, Err: "+e.Error(), c)
		return
	}
	updateCols := []string{
		"ProductIds", "CompanyName", "SellerId", "SellerName", "StartDate", "EndDate",
		"RaiSellerId", "RaiSellerName", "ModifyTime", "CurrencyUnit","ContractType","HasPayment",
	}

	invoiceList := make([]*fms.ContractInvoice, 0)
	ppList := make([]*fms.ContractPreRegister, 0)
	var sellerItem *crm.SellerAdminWithGroupTeam
	for _, r := range req.List {
		// 货币及汇率
		rateList, e := fmsService.GetTodayCurrencyRateList()
		if e != nil {
			resp.FailMsg("操作失败", "获取今日货币汇率失败, Err: "+e.Error(), c)
			return
		}
		var rate float64
		for i := range rateList {
			if r.CurrencyUnit == rateList[i].Code {
				rate = rateList[i].RMBRate
				break
			}
		}
		if rate <= 0 {
			resp.FailMsg("操作失败", "货币汇率信息有误", c)
			return
		}

		registerDate, e := time.Parse(utils.FormatDate, r.RegisterDate)
		if e != nil {
			resp.FailMsg("日期转换失败", "日期转换失败, Err: "+e.Error(), c)
			return
		}

		v := &fms.ContractInvoice{
			ContractInvoiceId:  r.InvoiceId,
			ContractRegisterId: ob.ContractRegisterId,
			OriginAmount:       r.Amount,
			CurrencyUnit:       r.CurrencyUnit,
			InvoiceType:        req.RegisterType,
			InvoiceDate:        registerDate,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			Remark:             r.Remark,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
		}
		v.TimeBase.ModifyTime = time.Now().Local()

		a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", v.OriginAmount/rate), 64)
		v.Amount = a

		sellerItem = sellerMap[r.SellerId]
		if sellerItem == nil {
			resp.Fail("销售信息异常", c)
			return
		}
		fmt.Println("SellerId",sellerItem.SellerId)
		fmt.Println("SellerName",sellerItem.SellerName)
		v.SellerId = sellerItem.SellerId
		v.SellerName = sellerItem.SellerName
		v.SellerGroupId = sellerItem.GroupId
		v.SellerGroupName = sellerItem.GroupName
		v.SellerTeamId = sellerItem.TeamId
		v.SellerTeamName = sellerItem.TeamName

		//预登记列表
		pp := &fms.ContractPreRegister{
			PreRegisterId:      r.PreRegisterId,
			ContractRegisterId: ob.ContractRegisterId,
			CompanyName:        req.CompanyName,
			InvoiceType:        req.RegisterType,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
			TimeBase:           base.TimeBase{},
		}
		pp.Set()
		pp.CurrencyUnit = r.CurrencyUnit
		pp.ContractType = req.ContractType
		pp.HasPayment = req.HasPayment
		ppUpdateCols := make([]string, 0)
		if pp.InvoiceType == fms.ContractInvoiceTypePreMake {
			//开票走开票字段
			pp.Remark = r.Remark
			pp.InvoiceDate = registerDate
			pp.OriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.OriginAmount/rate), 64)
			pp.Amount = a

			sellerItem = sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}

			pp.InvoiceId = v.ContractInvoiceId
			pp.SellerId = sellerItem.SellerId
			pp.SellerName = sellerItem.SellerName
			pp.SellerGroupId = sellerItem.GroupId
			pp.SellerGroupName = sellerItem.GroupName
			pp.SellerTeamId = sellerItem.TeamId
			pp.SellerTeamName = sellerItem.TeamName

			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
			ppUpdateCols = append(ppUpdateCols, "InvoiceDate", "Amount", "OriginAmount", "SellerId",
				"SellerName", "SellerGroupId", "SellerGroupName", "SellerTeamId", "SellerTeamName", "InvoiceId",
				"PaymentSellerId", "PaymentSellerName", "PaymentSellerGroupId", "PaymentSellerGroupName", "PaymentSellerTeamId", "PaymentSellerTeamName","ContractType","HasPayment")
		} else {
			//到款
			pp.ArriveRemark = r.Remark
			pp.ArriveDate = registerDate
			pp.ArriveId = v.ContractInvoiceId
			pp.ArriveOriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.ArriveOriginAmount/rate), 64)
			pp.ArriveAmount = a

			sellerItem = sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}

			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
			ppUpdateCols = append(ppUpdateCols, "CurrencyUnit", "ArriveDate", "ArriveAmount", "ArriveOriginAmount", "ArriveId",
				"PaymentSellerId", "PaymentSellerName", "PaymentSellerGroupId", "PaymentSellerGroupName", "PaymentSellerTeamId", "PaymentSellerTeamName","ContractType","HasPayment")
		}

		if pp.PreRegisterId == 0 {
			if e = pp.Create(); e != nil {
				resp.FailMsg("操作失败", "新增预登记失败, Err: "+e.Error(), c)
				return
			}
			v.PreRegisterId = pp.PreRegisterId
		} else {
			ppUpdateCols = append(ppUpdateCols,
				"CurrencyUnit", "CompanyName", "Remark", "ArriveRemark", "InvoiceTime", "ArriveTime",
				"ServiceProductId", "CurrencyUnit", "StartDate", "EndDate", "ModifyTime")
			if e = pp.Update(ppUpdateCols); e != nil {
				resp.FailMsg("操作失败", "更新预登记记录失败, Err: "+e.Error(), c)
				return
			}
		}

		invoiceList = append(invoiceList, v)
		ppList = append(ppList, pp)
	}
	invoiceUpdateCols := []string{
		"CurrencyUnit", "OriginAmount", "Amount", "InvoiceDate", "AdminId", "AdminName", "Remark",
		"ServiceProductId", "StartDate", "EndDate", "ModifyTime", "SellerId", "SellerName", "SellerGroupId", "SellerGroupName", "SellerTeamId", "SellerTeamName",
	}
	// 更新合同登记、套餐、开票到款
	if e = fms.UpdateContractPreRegister(ob, updateCols, serviceList, invoiceList, invoiceUpdateCols, req.DelInvoiceIds, req.DelPreRegisterIds, ppList, sellerItem, req.RegisterType); e != nil {
		resp.FailMsg("操作失败", "更新合同及套餐失败, Err: "+e.Error(), c)
		return
	}

	// 开票到款汇总
	go fmsService.SummaryInvoicePaymentByContractRegisterId(ob.ContractRegisterId)

	//预登记后更新register表开票到款合计金额
	go fmsService.CheckContractRegisterAmountAfterPre(ob.ContractRegisterId)
	resp.Ok("操作成功", c)
}

// Del
// @Title 删除到款预登记
// @Description 删除到款预登记
// @Param	request  body  fms.ContractRegisterDelReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /contract/pre_register/del [post]
func (rg *PreRegisterController) Del(c *gin.Context) {
	req := new(fms.PreRegisterDelReq)
	err := c.ShouldBind(&req)
	if err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
			return
		}
		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
		return
	}

	if req.InvoiceId != 0 {
		ob := new(fms.ContractInvoice)
		item, e := ob.Fetch(req.InvoiceId)
		if e != nil {
			if e == utils.ErrNoRow {
				resp.Fail("合同登记不存在或已被删除", c)
				return
			}
			resp.FailMsg("获取合同登记失败", "Err:"+e.Error(), c)
			return
		}
		e = item.Delete()
		if e != nil {
			resp.FailMsg("删除记录失败", "Err:"+e.Error(), c)
			return
		}
	}

	if req.ArriveId != 0 {
		ob := new(fms.ContractInvoice)
		item, e := ob.Fetch(req.ArriveId)
		if e != nil {
			if e == utils.ErrNoRow {
				resp.Fail("合同登记不存在或已被删除", c)
				return
			}
			resp.FailMsg("获取合同登记失败", "Err:"+e.Error(), c)
			return
		}
		e = item.Delete()
		if e != nil {
			resp.FailMsg("删除记录失败", "Err:"+e.Error(), c)
			return
		}
	}

	ob := new(fms.ContractPreRegister)
	item, e := ob.Fetch(req.PreRegisterId)
	if e != nil {
		if e == utils.ErrNoRow {
			resp.Fail("预登记记录不存在或已被删除", c)
			return
		}
		resp.FailMsg("获取预登记失败", "Err:"+e.Error(), c)
		return
	}
	e = item.Delete()
	if e != nil {
		resp.FailMsg("删除预登记记录失败", "Err:"+e.Error(), c)
		return
	}

	e = fms.DeleteInvoicePaymentSummaryByInvoiceIdAndPaymentId(req.InvoiceId, req.ArriveId, req.ContractRegisterId)
	if e != nil {
		resp.FailMsg("删除统计记录失败", "Err:"+e.Error(), c)
		return
	}
	//删除预登记新增的假合同
	count, e := fms.GetInvoiceCountByRegisterId(req.ContractRegisterId)
	if e != nil {
		resp.FailMsg("删除统计记录失败", "Err:"+e.Error(), c)
		return
	}
	if count == 0{
		ob := new(fms.ContractRegister)
		item, e := ob.Fetch(req.ContractRegisterId)
		if e != nil {
			if e == utils.ErrNoRow {
				resp.Fail("合同登记不存在或已被删除", c)
				return
			}
			resp.FailMsg("获取合同登记失败", "Err:"+e.Error(), c)
			return
		}
		nowTime := time.Now().Local()
		item.IsDeleted = 1
		item.ModifyTime = nowTime
		updateCols := []string{"IsDeleted", "ModifyTime"}
		if e = item.Update(updateCols); e != nil {
			resp.FailMsg("操作失败", "更新合同登记失败, Err:"+e.Error(), c)
			return
		}
	}

	resp.Ok("操作成功", c)
}

// Detail
// @Title 预登记记录详情
// @Description 预登记记录详情
// @Param	request  body  fms.PreRegisterDetailReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /contract/pre_register/detail [post]
func (rg *PreRegisterController) Detail(c *gin.Context) {
	req := new(fms.PreRegisterDetailReq)
	err := c.ShouldBind(&req)
	if err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
			return
		}
		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
		return
	}

	ob := new(fms.ContractRegister)
	item, e := ob.Fetch(req.ContractRegisterId)
	if e != nil {
		if e == utils.ErrNoRow {
			resp.Fail("合同登记不存在或已被删除", c)
			return
		}
		resp.FailMsg("获取合同登记失败", "Err:"+e.Error(), c)
		return
	}

	nItme := fms.ContractRegisterItem{
		ContractRegisterId: item.ContractRegisterId,
		ContractCode:       item.ContractCode,
		RelateContractCode: item.RelateContractCode,
		CrmContractId:      item.CrmContractId,
		ContractSource:     item.ContractSource,
		CompanyName:        item.CompanyName,
		ActualCompanyName:  item.ActualCompanyName,
		ProductIds:         item.ProductIds,
		SellerId:           item.SellerId,
		SellerName:         item.SellerName,
		RaiSellerId:        item.RaiSellerId,
		RaiSellerName:      item.RaiSellerName,
		ContractType:       item.ContractType,
		ContractAmount:     item.ContractAmount,
		InvoicedAmount:     item.InvoicedAmount,
		PaymentAmount:      item.PaymentAmount,
		CurrencyUnit:       item.CurrencyUnit,
		RMBRate:            item.RMBRate,
		StartDate:          item.StartDate.Format(utils.FormatDate),
		EndDate:            item.EndDate.Format(utils.FormatDate),
		SignDate:           item.SignDate.Format(utils.FormatDate),
		AgreedPayTime:      item.AgreedPayTime,
		ContractStatus:     item.ContractStatus,
		RegisterStatus:     item.RegisterStatus,
		Remark:             item.Remark,
		ServiceRemark:      item.ServiceRemark,
		HasPayment:         item.HasPayment,
		NewCompany:         item.NewCompany,
		CreateTime:         item.CreateTime.Format(utils.FormatDateTime),
	}

	if nItme.StartDate == "0001-01-01" {
		nItme.StartDate = ""
	}
	if nItme.EndDate == "0001-01-01" {
		nItme.EndDate = ""
	}

	cond := ``
	pars := make([]interface{}, 0)

	if req.InvoiceId == 0 && req.ArriveId == 0 {
		cond = `a.contract_register_id = ? `
		pars = append(pars, req.ContractRegisterId)
	} else {
		cond = `a.contract_register_id = ?  AND a.contract_invoice_id =? `
		pars = append(pars, req.ContractRegisterId)
	}

	if req.InvoiceType == 4 {
		pars = append(pars, req.ArriveId)
	} else {
		pars = append(pars, req.InvoiceId)
	}
	list, e := fms.GetContractInvoiceDetailItemList(cond, pars)
	if e != nil {
		err = fmt.Errorf("获取开票到款列表失败, Err: %s", e.Error())
		return
	}

	if req.DetailType == 1 {
		dupList, e := fms.GetDuplicateContractInvoiceDetailItemListWithType(nItme.CompanyName, nItme.StartDate, nItme.EndDate, req.ContractType, req.HasPayment)
		if e != nil {
			err = fmt.Errorf("获取开票到款列表失败, Err: %s", e.Error())
			return
		}
		for _, v := range dupList {
			if v.ContractRegisterId != req.ContractRegisterId {
				list = append(list, v)
			}
		}
	}
	respList := make([]*fms.ContractInvoiceDetailItem, 0)
	for _, v := range list {
		if v.InvoiceType == req.InvoiceType {
			respList = append(respList, v)
		}
	}

	//获取ficc小套餐品种
	sysConf := new(system.SysConfig)
	confCond := `config_code = ?`
	confPars := make([]interface{}, 0)
	confPars = append(confPars, system.ConfigKeyCrmPermissionFiccClassify)
	confItem, e := sysConf.FetchByCondition(confCond, confPars)
	if e != nil {
		resp.FailData("获取失败", "Err:"+e.Error(), c)
		return
	}
	if confItem.ConfigValue == "" {
		resp.FailData("获取失败", "FICC品种分类配置为空", c)
		return
	}
	classifyArr := strings.Split(confItem.ConfigValue, ",")
	if len(classifyArr) == 0 {
		resp.FailData("获取失败", "FICC品种分类配置为空", c)
		return
	}
	// 获取FICC权限
	ficcCond := `enabled = 1 AND permission_type = 0 AND product_id = ? AND classify_name IN ?`
	ficcPars := make([]interface{}, 0)
	ficcPars = append(ficcPars, 1, classifyArr)
	items, e := crm.GetPermissionSetItemsByCondition(ficcCond, ficcPars)
	if e != nil {
		resp.FailData("获取失败", "获取FICC权限信息失败, Err: "+e.Error(), c)
		return
	}
	ficcItemMap := make(map[string][]*crm.PermissionSetItem, 0)
	for i := range items {
		if ficcItemMap[items[i].ClassifyName] == nil {
			ficcItemMap[items[i].ClassifyName] = make([]*crm.PermissionSetItem, 0)
		}
		ficcItemMap[items[i].ClassifyName] = append(ficcItemMap[items[i].ClassifyName], items[i])
	}

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

	for i := range classifyArr {
		if classifyArr[i] == "市场策略" {
			continue
		}
		checkList := make([]int, 0)
		if classifyArr[i] == "宏观经济" {
			checkList = append(checkList, 1)
		}

		pItem := fms.ContractServiceTemplateItem{
			ServiceTemplateId: 90000 + i*100,
		}

		ficcItems := ficcItemMap[classifyArr[i]]
		for _, ficcItem := range ficcItems {
			sTempIdMap[strconv.Itoa(ficcItem.ChartPermissionId)] = pItem.ServiceTemplateId + ficcItem.ChartPermissionId
		}
	}

	services, e := fms.GetContractServiceAndDetailList(req.ContractRegisterId)
	if e != nil {
		err = fmt.Errorf(fmt.Sprint("查找合同服务异常", e))
		return
	}

	serviceTemplateIdSlice := make([]string, 0)
	for _, service := range services {
		if service.Title == "FICC小套餐" {
			serviceTemplateIdSlice = strings.Split(service.ChartPermissionIds, ",")
		}
	}

	serviceTemplateIds := make([]int, 0)
	for _, v := range serviceTemplateIdSlice {
		serviceTemplateIds = append(serviceTemplateIds, sTempIdMap[v])
	}
	respItem := fms.ContractPreRegisterDetail{
		ContractRegisterItem: &nItme,
		List:                 respList,
		Services:             services,
		ServiceTemplateIds:   serviceTemplateIds,
	}

	resp.OkData("获取成功", respItem, c)
}

// Save
// @Title 预登记保存
// @Description 预登记保存
// @Param	request  body  fms.PrepayAddReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /contract/pre_register/save [post]
func (rg *PreRegisterController) Save(c *gin.Context) {
	req := new(fms.PreRegisterSaveReq)
	err := c.ShouldBind(&req)
	if err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
			return
		}
		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
		return
	}
	claims, _ := c.Get("adminInfo")
	adminInfo := claims.(*system.SysAdmin)

	// 日期校验
	var startDate, endDate time.Time
	if req.StartDate != "" && req.EndDate != "" {
		startDate, err = time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
		if err != nil {
			resp.FailMsg("约定开始日期格式有误", "合同开始日期格式有误, Err: "+err.Error(), c)
			return
		}
		endDate, err = time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
		if err != nil {
			resp.FailMsg("约定结束日期格式有误", "合同结束日期格式有误, Err: "+err.Error(), c)
			return
		}
	}

	// 获取销售分组信息
	sellerList, e := crmService.GetSellerDepartmentListWithEnable()
	if e != nil {
		resp.FailData("获取销售失败", "Err:"+e.Error(), c)
		return
	}
	sellerMap := make(map[int]*crm.SellerAdminWithGroupTeam)
	for i := range sellerList {
		sellerMap[sellerList[i].SellerId] = sellerList[i]
	}

	admin := new(crm.Admin)
	sellerIds := strings.Split(req.SellerIds, ",")
	if len(sellerIds) > 2 {
		resp.Fail("最多只能选择两个销售", c)
		return
	}

	var sellers []*crm.Admin
	var pars []interface{}
	cond := ``
	if len(sellerIds) > 0 {
		cond = ` admin_id in (?) `
		pars = append(pars, sellerIds)
		sellers, e = admin.List(cond, pars)
		if e != nil {
			resp.FailMsg("获取销售信息失败", "获取销售信息失败, Err: "+e.Error(), c)
			return
		}
	}
	updateCols := []string{"CompanyName", "ProductIds", "StartDate", "EndDate", "ModifyTime"}

	//更新合同
	ob := new(fms.ContractRegister)
	//ob.ContractCode = req.ContractCode
	ob.ContractRegisterId = req.ContractRegisterId
	ob.CompanyName = req.CompanyName
	ob.ProductIds = req.ProductIds
	ob.StartDate = startDate
	ob.EndDate = endDate
	ob.ModifyTime = time.Now()
	ob.CurrencyUnit = req.List[0].CurrencyUnit
	ob.ContractType = req.ContractType
	ob.HasPayment = req.HasPayment
	if req.RegisterType == fms.ContractInvoiceTypePreMake {
		//sellerItem := sellerMap[r.SellerId]
		//if sellerItem == nil {
		//	resp.Fail("销售信息异常", c)
		//	return
		//}
		for _, v := range sellers {
			if v.DepartmentId == crm.SellerDepartmentId {
				ob.SellerId = v.AdminId
				ob.SellerName = v.AdminName
				updateCols = append(updateCols, "SellerId", "SellerName")
			} else if v.DepartmentId == crm.RaiSellerDepartmentId {
				ob.RaiSellerId = v.AdminId
				ob.RaiSellerName = v.AdminName
				updateCols = append(updateCols, "RaiSellerId", "RaiSellerName")
			}
		}
	}

	// 套餐信息
	serviceAmountMap := make(map[int]float64)
	serviceList, e := fmsService.HandleContractServiceAndDetail(req.Services, true, serviceAmountMap)
	if e != nil {
		resp.FailMsg("操作失败", "获取合同套餐详情失败, Err: "+e.Error(), c)
		return
	}
	invoiceUpdateCols := make([]string, 0)
	invoiceHandleType := 0
	invoiceList := make([]*fms.ContractInvoice, 0)
	ppList := make([]*fms.ContractPreRegister, 0)
	for _, r := range req.List {
		// 货币及汇率
		rateList, e := fmsService.GetTodayCurrencyRateList()
		if e != nil {
			resp.FailMsg("操作失败", "获取今日货币汇率失败, Err: "+e.Error(), c)
			return
		}
		var rate float64
		for i := range rateList {
			if r.CurrencyUnit == rateList[i].Code {
				rate = rateList[i].RMBRate
				break
			}
		}
		if rate <= 0 {
			resp.FailMsg("操作失败", "货币汇率信息有误", c)
			return
		}

		registerDate, e := time.Parse(utils.FormatDate, r.RegisterDate)
		if e != nil {
			resp.FailMsg("日期转换失败", "日期转换失败, Err: "+e.Error(), c)
			return
		}

		v := &fms.ContractInvoice{
			ContractInvoiceId:  r.InvoiceId,
			ContractRegisterId: ob.ContractRegisterId,
			OriginAmount:       r.Amount,
			CurrencyUnit:       r.CurrencyUnit,
			InvoiceType:        req.RegisterType,
			InvoiceDate:        registerDate,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			Remark:             r.Remark,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
			TimeBase:           base.TimeBase{},
		}
		v.TimeBase.ModifyTime = time.Now()

		a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", v.OriginAmount/rate), 64)
		v.Amount = a

		sellerItem := sellerMap[r.SellerId]
		if sellerItem == nil {
			resp.Fail("销售信息异常", c)
			return
		}

		v.SellerId = sellerItem.SellerId
		v.SellerName = sellerItem.SellerName
		v.SellerGroupId = sellerItem.GroupId
		v.SellerGroupName = sellerItem.GroupName
		v.SellerTeamId = sellerItem.TeamId
		v.SellerTeamName = sellerItem.TeamName
		invoiceUpdateCols = append(invoiceUpdateCols, "SellerId", "SellerName", "SellerGroupId",
			"SellerGroupName", "SellerTeamId", "SellerTeamName")

		// 新增开票到款记录
		if v.ContractInvoiceId != 0 {
			//更新
			invoiceHandleType = 1
			invoiceUpdateCols = append(invoiceUpdateCols, "OriginAmount", "CurrencyUnit",
				"InvoiceDate", "Remark", "ServiceProductId", "StartDate", "EndDate", "ModifyTime")
		} else {
			//新增
			invoiceHandleType = 2
		}
		invoiceList = append(invoiceList, v)

		//预登记列表
		ppUpdateCols := make([]string, 0)
		pp := &fms.ContractPreRegister{
			PreRegisterId:      r.PreRegisterId,
			ContractRegisterId: ob.ContractRegisterId,
			CompanyName:        req.CompanyName,
			InvoiceType:        req.RegisterType,
			InvoiceDate:        registerDate,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
			TimeBase:           base.TimeBase{},
		}
		pp.Set()
		pp.CurrencyUnit = r.CurrencyUnit
		pp.ContractType = req.ContractType
		pp.HasPayment = req.HasPayment
		if pp.InvoiceType == fms.ContractInvoiceTypePreMake {
			//开票走开票字段
			pp.Remark = r.Remark
			pp.InvoiceDate = registerDate
			pp.OriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.OriginAmount/rate), 64)
			pp.Amount = a

			sellerItem := sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}

			pp.SellerId = sellerItem.SellerId
			pp.SellerName = sellerItem.SellerName
			pp.SellerGroupId = sellerItem.GroupId
			pp.SellerGroupName = sellerItem.GroupName
			pp.SellerTeamId = sellerItem.TeamId
			pp.SellerTeamName = sellerItem.TeamName
			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
			ppUpdateCols = append(ppUpdateCols, "InvoiceDate", "Amount", "OriginAmount", "SellerId",
				"SellerName", "SellerGroupId", "SellerGroupName", "SellerTeamId", "SellerTeamName", "Remark",
				"PaymentSellerId", "PaymentSellerName", "PaymentSellerGroupId", "PaymentSellerGroupName", "PaymentSellerTeamId", "PaymentSellerTeamName")
		} else {
			//到款
			pp.ArriveRemark = r.Remark
			pp.ArriveDate = registerDate
			pp.ArriveOriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.ArriveOriginAmount/rate), 64)
			pp.ArriveAmount = a

			sellerItem := sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}

			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
			ppUpdateCols = append(ppUpdateCols, "ArriveRemark", "CurrencyUnit", "ArriveDate", "ArriveAmount", "ArriveOriginAmount",
				"PaymentSellerId", "PaymentSellerName", "PaymentSellerGroupId", "PaymentSellerGroupName", "PaymentSellerTeamId", "PaymentSellerTeamName")
		}

		ppUpdateCols = append(ppUpdateCols,
			"CompanyName", "AdminId", "AdminName", "ServiceProductId",
			"CurrencyUnit", "StartDate", "EndDate", "ModifyTime")

		if e = pp.Update(ppUpdateCols); e != nil {
			resp.FailMsg("操作失败", "更新预登记记录失败, Err: "+e.Error(), c)
			return
		}
		ppList = append(ppList, pp)
	}
	if e = fms.UpdateContractRegisterPre(ob, updateCols, serviceList, invoiceList, invoiceUpdateCols, invoiceHandleType, ppList); e != nil {
		resp.FailMsg("操作失败", "新增合同及套餐失败, Err: "+e.Error(), c)
		return
	}
	// 开票到款汇总
	go fmsService.SummaryInvoicePaymentByContractRegisterId(ob.ContractRegisterId)

	//预登记后更新register表开票到款合计金额
	go fmsService.CheckContractRegisterAmountAfterPre(ob.ContractRegisterId)

	resp.Ok("操作成功", c)
}

func ExportPreRegister(c *gin.Context,list []*fms.ContractPreRegisterItem) {
	//var req fms.PreRegisterListReq
	//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
	//}
	//pageSize := req.PageSize
	//pageIndex := req.Current
	//if pageSize <= 0 {
	//	pageSize = utils.PageSize20
	//}
	//if pageIndex <= 0 {
	//	pageIndex = 1
	//}
	//cond := ` invoice_type IN (3, 4) `
	//pars := make([]interface{}, 0)
	//if req.Keyword != "" {
	//	kw := "%" + req.Keyword + "%"
	//	cond += ` AND company_name LIKE ? `
	//	pars = append(pars, kw)
	//}
	// 货币列表
	currencyOB := new(fms.CurrencyUnit)
	currencyCond := `enable = 1`
	currencyPars := make([]interface{}, 0)
	currencyList, e := currencyOB.List(currencyCond, currencyPars)
	if e != nil {
		resp.FailMsg("获取失败", "获取货币列表失败, Err: "+e.Error(), c)
		return
	}
	unitMap := make(map[string]string)
	for i := range currencyList {
		unitMap[currencyList[i].Code] = currencyList[i].UnitName
	}
	//
	//page := new(base.Page)
	//page.SetPageSize(req.PageSize)
	//page.SetCurrent(req.Current)
	//sortTypeMap := map[int]bool{0: false, 1: true, 2: false}
	//page.AddOrderItem(base.OrderItem{Column: "create_time", Asc: sortTypeMap[0]})
	//
	//_, list, e := fms.GetContractPreRegisterItemPageList(page, cond, pars)
	//if e != nil {
	//	resp.FailMsg("获取失败", "获取预登记列表失败, Err: "+e.Error(), c)
	//	return
	//}
	//serviceMap := make(map[int]string, 0)
	registerIds := make([]int, 0)
	for i := range list {
		list[i].UnitName = unitMap[list[i].CurrencyUnit]
		registerIds = append(registerIds, list[i].ContractRegisterId)
	}
	// 获取小套餐品种
	cpCond := `product_id = ? AND permission_name <> ? AND enabled = 1 AND parent_id> 0 `
	cpPars := make([]interface{}, 0)
	cpPars = append(cpPars, crm.CompanyProductFicc, crm.ChartPermissionStrategyName)
	cp := new(crm.ChartPermission)
	permissionList, e := cp.List(cpCond, cpPars)
	if e != nil {
		resp.FailData("获取小套餐品种失败", "Err:"+e.Error(), c)
		return
	}
	permissionLen := len(permissionList)
	permissionNameIdMap := make(map[string]int)
	for i := range permissionList {
		permissionNameIdMap[permissionList[i].PermissionName] = permissionList[i].ChartPermissionId
	}

	// 获取所有FICC套餐服务
	serviceList, e := fms.GetContractServiceTemplateMapByProductId(crm.CompanyProductFicc)
	if e != nil {
		resp.FailData("获取套餐服务失败", "Err:"+e.Error(), c)
		return
	}
	// 除大小套餐外的其他套餐(下面的导出需要以此动态处理)
	otherService := make([]*fms.ContractServiceTemplateItem, 0)
	for i := range serviceList {
		if serviceList[i].Title != "FICC大套餐" && serviceList[i].Title != "FICC小套餐" {
			otherService = append(otherService, serviceList[i])
		}
	}
	otherServiceLen := len(otherService)

	// 获取所有权益套餐服务
	raiServiceList, e := fms.GetContractServiceTemplateAllByProductId(crm.CompanyProductRai)
	if e != nil {
		resp.FailData("获取权益套餐服务失败", "Err:"+e.Error(), c)
		return
	}
	raiServiceIdMap := make(map[int]*fms.ContractServiceTemplateItem)
	for i := range raiServiceList {
		raiServiceIdMap[raiServiceList[i].ServiceTemplateId] = raiServiceList[i]
	}

	// 除大小套餐外的其他套餐(下面的导出需要以此动态处理)
	raiOtherService := make([]*fms.ContractServiceTemplateItem, 0)
	raiServiceNotShowMap := make(map[int]struct{})
	for _, v := range raiServiceList {
		if v.Pid > 0 && raiServiceIdMap[v.Pid].Pid > 0 {
			raiServiceNotShowMap[v.Pid] = struct{}{}
			raiServiceNotShowMap[raiServiceIdMap[v.Pid].Pid] = struct{}{}
		} else if v.Pid > 0 {
			raiServiceNotShowMap[v.Pid] = struct{}{}
		}
	}
	for _, v := range raiServiceList {
		if _, ok := raiServiceNotShowMap[v.ServiceTemplateId]; !ok {
			if v.Pid > 0 {
				v.ParentTitle = raiServiceIdMap[v.Pid].Title
			}
			raiOtherService = append(raiOtherService, v)
		}
	}
	otherServiceLen += len(raiOtherService)

	//套餐金额map
	serviceAmountMap := make(map[int]map[int]*fms.ContractServiceAmount)

	// 套餐/开票/到款列表
	serviceMap := make(map[int][]*fms.ContractServiceWithParentTitle)
	serviceChartPermissionsMap := make(map[int][]int)
	invoiceMap := make(map[int][]*fms.ContractInvoice)
	paymentMap := make(map[int][]*fms.ContractInvoice)
	maxInvoice := 0
	maxPayment := 0
	if len(registerIds) > 0 {
		// 获取套餐信息
		csCond := `cv.contract_register_id IN ?`
		csPars := make([]interface{}, 0)
		csPars = append(csPars, registerIds)
		cs := new(fms.ContractService)
		serviceList, e := cs.ListWithWithParentTitle(csCond, csPars)
		if e != nil {
			resp.FailData("获取合同套餐列表失败", "Err:"+e.Error(), c)
			return
		}
		for i := range serviceList {
			cid := serviceList[i].ContractRegisterId
			if serviceMap[cid] == nil {
				serviceMap[cid] = make([]*fms.ContractServiceWithParentTitle, 0)
			}
			serviceMap[cid] = append(serviceMap[cid], serviceList[i])
			// 小套餐权限
			if serviceChartPermissionsMap[cid] == nil {
				serviceChartPermissionsMap[cid] = make([]int, 0)
			}
			if serviceList[i].ChartPermissionIds != "" {
				ids := utils.JoinStr2IntArr(serviceList[i].ChartPermissionIds, ",")
				serviceChartPermissionsMap[cid] = append(serviceChartPermissionsMap[cid], ids...)
			}
		}

		// 获取合同的套餐金额信息
		serviceAmountList, e := fms.GetContractServiceAmountByContractRegisterIds(registerIds)
		if e != nil {
			resp.FailData("获取合同的套餐金额信息失败", "Err:"+e.Error(), c)
			return
		}
		for _, v := range serviceAmountList {
			if _, ok := serviceAmountMap[v.ContractRegisterId]; !ok {
				serviceAmountMap[v.ContractRegisterId] = make(map[int]*fms.ContractServiceAmount)
			}
			serviceAmountMap[v.ContractRegisterId][v.ProductId] = v
		}
		// 获取开票/到款详情, 并取最大的开票/到款数(用于动态扩展第二列表头)
		ci := new(fms.ContractInvoice)
		csCond = `contract_register_id IN ?`
		csPars = make([]interface{}, 0)
		csPars = append(csPars, registerIds)
		invoiceList, e := ci.List(csCond, csPars, "")
		if e != nil {
			resp.FailData("获取开票/到款列表失败", "Err:"+e.Error(), c)
			return
		}
		for k := range invoiceList {
			cid := invoiceList[k].ContractRegisterId
			if invoiceMap[cid] == nil {
				invoiceMap[cid] = make([]*fms.ContractInvoice, 0)
			}
			if paymentMap[cid] == nil {
				paymentMap[cid] = make([]*fms.ContractInvoice, 0)
			}
			if invoiceList[k].InvoiceType == fms.ContractInvoiceTypeMake {
				invoiceMap[cid] = append(invoiceMap[cid], invoiceList[k])
				continue
			}
			if invoiceList[k].InvoiceType == fms.ContractInvoiceTypePay {
				paymentMap[cid] = append(paymentMap[cid], invoiceList[k])
				continue
			}
		}
		// 取最大开票/到款数
		for j := range invoiceMap {
			if len(invoiceMap[j]) > maxInvoice {
				maxInvoice = len(invoiceMap[j])
			}
		}
		for p := range paymentMap {
			if len(paymentMap[p]) > maxPayment {
				maxPayment = len(paymentMap[p])
			}
		}
	}

	// 生成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
	}

	// 1行表头
	hInt := 0
	titleRow := sheet.AddRow()
	titleRow.SetHeight(40)
	// 1行1列-右合并两格, 下合并1行
	cell1 := titleRow.AddCell()
	cell1.HMerge = 10

	cell1.VMerge = 1
	cell1.SetString("")
	cell1.SetStyle(style)

	// 右增两列空白格用于第一列合并, 否则后续单元格合并会有问题
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	hInt += 13

	titleRow.AddCell().SetString("")
	hInt += 1
	// 1行2列
	cell2 := titleRow.AddCell()
	cell2.VMerge = 1
	cell2.SetString("FICC大套餐")
	cell2.SetStyle(style)
	hInt++

	// 1行3列-右合并小套餐数

	cell3 := titleRow.AddCell()
	hInt++
	cell3.HMerge = permissionLen - 1
	cell3.VMerge = 1
	cell3.SetString("FICC小套餐")
	cell3.SetStyle(style)
	// 同上右增单元格小套餐数-1的空白单元格用于合并
	for i := 0; i < permissionLen-1; i++ {
		titleRow.AddCell().SetString("")
		hInt++
	}

	for i := range otherService {
		cellOther := titleRow.AddCell()
		cellOther.VMerge = 1
		hInt++
		cellOther.SetString(otherService[i].Title)
		cellOther.SetStyle(style)
	}

	//权益大套餐
	cell4 := titleRow.AddCell()
	cell4.HMerge = 1
	cell4.VMerge = 1
	cell4.SetString("权益大套餐")
	cell4.SetStyle(style)
	titleRow.AddCell().SetString("")
	hInt += 2

	//权益分行业套餐
	cell5 := titleRow.AddCell()
	//cell5.HMerge = 8
	cell5.SetString("权益分行业套餐")
	cell5.SetStyle(style)
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")
	titleRow.AddCell().SetString("")

	//第二行,前面几个单元格用于第一行的合并
	titleRow2 := sheet.AddRow()
	titleRow2.SetHeight(30)
	for i := 0; i < hInt; i++ {
		titleRow2.AddCell().SetString("")
	}

	//权益分行业套餐
	row2Cell1 := titleRow2.AddCell()
	row2Cell1.HMerge = 1
	row2Cell1.SetString("医药")
	row2Cell1.SetStyle(style)
	titleRow2.AddCell().SetString("")

	row2Cell2 := titleRow2.AddCell()
	row2Cell2.HMerge = 1
	row2Cell2.SetString("消费")
	row2Cell2.SetStyle(style)
	titleRow2.AddCell().SetString("")

	row2Cell3 := titleRow2.AddCell()
	row2Cell3.HMerge = 1
	row2Cell3.SetString("科技")
	row2Cell3.SetStyle(style)
	titleRow2.AddCell().SetString("")

	row2Cell4 := titleRow2.AddCell()
	row2Cell4.HMerge = 1
	row2Cell4.SetString("智造")
	row2Cell4.SetStyle(style)
	titleRow2.AddCell().SetString("")

	row2Cell5 := titleRow2.AddCell()
	row2Cell5.SetString("策略")
	row2Cell5.SetStyle(style)

	// 第三行表头
	titleRow3 := sheet.AddRow()
	titleRow3.SetHeight(60)
	row3Title := make([]string, 0)
	row3TitleParent := make([]string, 0)
	row3Title = append(row3Title, "客户名称", "约定起始日期", "约定结束日期", "合同类型", "开票日期", "开票金额", "开票换算金额", "开票销售",
		"到款日期", "到款金额", "到款换算金额", "到款销售", "开票备注", "到款备注")

	row3Title = append(row3Title, "FICC大套餐")
	for i := range permissionList {
		row3Title = append(row3Title, permissionList[i].PermissionName)
	}
	// 其他套餐
	for i := range otherService {
		row3Title = append(row3Title, otherService[i].Title)
	}
	// 定义二级套餐名称
	for i := range row3Title {
		row3TitleParent = append(row3TitleParent, row3Title[i])
	}
	// 权益三级套餐
	for i := range raiOtherService {
		row3Title = append(row3Title, raiOtherService[i].Title)
		if raiOtherService[i].ParentTitle != "" {
			row3TitleParent = append(row3TitleParent, raiOtherService[i].ParentTitle)
		} else {
			row3TitleParent = append(row3TitleParent, raiOtherService[i].Title)
		}
	}

	// 设置表头
	for i := range row3Title {
		v := titleRow3.AddCell()
		v.SetString(row3Title[i])
		v.SetStyle(style)
	}

	// 此处取第二行标题NameKeyMap, 后面的动态匹配
	row2NameKeyMap := make(map[string]int)
	for i := range row3Title {
		row2NameKeyMap[row3Title[i]] = i
	}

	for _, v := range list {
		k := -1 // 套餐匹配用
		dataRow := sheet.AddRow()
		dataRow.SetHeight(20)
		dataRow.AddCell().SetString(v.CompanyName)
		dataRow.AddCell().SetString(v.StartDate)
		dataRow.AddCell().SetString(v.EndDate)
		contractTypeString := ``
		if v.HasPayment == 1 {
			//代付
			if v.ContractType == 1 {
				contractTypeString = "代付合同(新签)"
			} else if v.ContractType == 2 {
				contractTypeString = "代付合同(续约)"
			} else {
				contractTypeString = "代付合同(补充)"
			}
		} else {
			if v.ContractType == 1 {
				contractTypeString = "自付合同(新签)"
			} else if v.ContractType == 2 {
				contractTypeString = "自付合同(续约)"
			} else {
				contractTypeString = "自付合同(补充)"
			}
		}
		dataRow.AddCell().SetString(contractTypeString)
		dataRow.AddCell().SetString(v.InvoiceDate)
		originAmount := fmt.Sprintf("%.2f", v.OriginAmount)
		dataRow.AddCell().SetString(originAmount)
		amount := fmt.Sprintf("%.2f", v.Amount)
		dataRow.AddCell().SetString(amount)
		dataRow.AddCell().SetString(v.SellerName)

		dataRow.AddCell().SetString(v.ArriveDate)
		arriveOriginAmount := fmt.Sprintf("%.2f", v.ArriveOriginAmount)
		dataRow.AddCell().SetString(arriveOriginAmount)
		arriveAmount := fmt.Sprintf("%.2f", v.ArriveAmount)
		dataRow.AddCell().SetString(arriveAmount)
		dataRow.AddCell().SetString(v.SellerName)
		dataRow.AddCell().SetString("")
		dataRow.AddCell().SetString("")
		k += 15
		svList := serviceMap[v.ContractRegisterId]

		// Ficc大套餐
		col4Name := row3Title[k]
		col4 := ""
		if svList != nil && len(svList) > 0 {
			for isv := range svList {
				if svList[isv].Title == col4Name {
					col4 = "是"
					break
				}
			}
		}
		dataRow.AddCell().SetString(col4)

		// 小套餐
		serviceChartPermissionIds := serviceChartPermissionsMap[v.ContractRegisterId]
		for i := 0; i < permissionLen; i++ {
			k += 1
			colName := row3Title[k]
			chartPermissionId := permissionNameIdMap[colName]
			if utils.InArray(chartPermissionId, serviceChartPermissionIds) {
				dataRow.AddCell().SetString("是")
			} else {
				dataRow.AddCell().SetString("")
			}
		}

		// 除大小套餐外的其他套餐(处理方式其实跟上面的大套餐一样, 只是中间隔了小套餐按照顺序要这么处理=_=!)
		for i := 0; i < otherServiceLen; i++ {
			k += 1
			otherColName := row3Title[k]
			otherCol := ""
			if svList != nil && len(svList) > 0 {
				for isv := range svList {
					if svList[isv].Title == otherColName {
						// 判断权益套餐权限时,需要同时判断父级name
						if otherColName == "主观" || otherColName == "客观" {
							if row3TitleParent[k] == svList[isv].ParentTitle {
								otherCol = "是"
								break
							}
						} else {
							otherCol = "是"
							break
						}
					}
				}
			}
			dataRow.AddCell().SetString(otherCol)
		}
	}

	// 输出文件
	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)
}