package contract import ( "bytes" "encoding/json" "fmt" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "github.com/shopspring/decimal" "github.com/tealeg/xlsx" "hongze/fms_api/controller/resp" "hongze/fms_api/global" "hongze/fms_api/models/base" "hongze/fms_api/models/crm" "hongze/fms_api/models/fms" "hongze/fms_api/models/system" "hongze/fms_api/services/alarm_msg" crmService "hongze/fms_api/services/crm" fmsService "hongze/fms_api/services/fms" "hongze/fms_api/utils" "net/http" "os" "path" "strconv" "strings" "time" ) // RegisterController 合同登记 type RegisterController struct{} // List // @Title 合同登记列表 // @Description 合同登记列表 // @Param Keyword query string false "关键词" // @Param StartDate query string false "合同开始日期" // @Param EndDate query string false "合同结束日期" // @Param ServiceType query int false "套餐类型" // @Param ContractType query string false "合同类型" // @Param RegisterStatus query int false "登记状态" // @Success 200 {object} fms.ContractRegisterItem // @router /contract/register/list [get] func (rg *RegisterController) List(c *gin.Context) { var req fms.ContractRegisterListReq 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 } cond := `1 = 1` pars := make([]interface{}, 0) // 合同编号/客户姓名/销售/实际使用方 if req.Keyword != "" { kw := "%" + req.Keyword + "%" cond += ` AND (company_name LIKE ? OR contract_code LIKE ? OR seller_name LIKE ? OR rai_seller_name LIKE ? OR actual_company_name LIKE ?)` pars = append(pars, kw, kw, kw, kw, kw) } if req.StartDate != "" && req.EndDate != "" { st := fmt.Sprint(req.StartDate, " 00:00:00") ed := fmt.Sprint(req.EndDate, " 23:59:59") cond += ` AND (create_time BETWEEN ? AND ?)` pars = append(pars, st, ed) } if req.ContractType != "" { newCond := "" typeSlices := strings.Split(req.ContractType, ",") for _, v := range typeSlices { if v[:1] == "0" { //自付 if v[1:] == "1" { newCond += ` (contract_type = 1 AND has_payment=0) ` } else if v[1:] == "2" { newCond += ` (contract_type = 2 AND has_payment=0) ` } else { newCond += ` (contract_type = 4 AND has_payment=0) ` } } else { //代付 if v[1:] == "1" { newCond += ` (contract_type = 1 AND has_payment=1) ` } else if v[1:] == "2" { newCond += ` (contract_type = 2 AND has_payment=1) ` } else { newCond += ` (contract_type = 4 AND has_payment=1) ` } } newCond += " OR " } newCond = strings.TrimRight(newCond, "OR ") cond += " AND " + "(" + newCond + ")" } if req.RegisterStatus != 0 { cond += ` AND register_status = ?` pars = append(pars, req.RegisterStatus) } // 套餐筛选 if req.ServiceTypes != "" { serviceTypes := strings.Split(req.ServiceTypes, ",") registerIds, e := fms.GetContractRegisterIdsByTempId(serviceTypes) if e != nil { resp.FailMsg("获取失败", "获取合同登记IDs失败, Err: "+e.Error(), c) return } if len(registerIds) > 0 { cond += ` AND contract_register_id IN ?` pars = append(pars, registerIds) } else { cond += ` AND 1 = 2` } } page := new(base.Page) page.SetPageSize(req.PageSize) page.SetCurrent(req.Current) page.AddOrderItem(base.OrderItem{Column: "create_time", Asc: false}) total, list, e := fms.GetContractRegisterItemPageList(page, cond, pars) if e != nil { resp.FailMsg("获取失败", "获取合同登记列表失败, Err: "+e.Error(), c) return } registerIds := make([]int, 0) for i := range list { registerIds = append(registerIds, list[i].ContractRegisterId) } serviceMap := make(map[int]string, 0) invoiceMap := make(map[int][]*fms.ContractInvoiceItem, 0) paymentMap := make(map[int][]*fms.ContractInvoiceItem, 0) if len(registerIds) > 0 { // 获取所有的服务套餐 serviceMap, _, e = fmsService.GetContractServiceNameFormat(registerIds) if e != nil { resp.FailMsg("获取失败", e.Error(), c) return } // 获取开票/到款列表 invoiceCond := `contract_register_id IN ?` invoicePars := make([]interface{}, 0) invoicePars = append(invoicePars, registerIds) invoiceList, e := fms.GetContractInvoiceItemList(invoiceCond, invoicePars) if e != nil { resp.FailMsg("获取失败", "获取开票/到款列表失败, Err: "+e.Error(), c) return } for i := range invoiceList { if invoiceMap[invoiceList[i].ContractRegisterId] == nil { invoiceMap[invoiceList[i].ContractRegisterId] = make([]*fms.ContractInvoiceItem, 0) } if paymentMap[invoiceList[i].ContractRegisterId] == nil { paymentMap[invoiceList[i].ContractRegisterId] = make([]*fms.ContractInvoiceItem, 0) } if invoiceList[i].InvoiceType == fms.ContractInvoiceTypeMake { invoiceMap[invoiceList[i].ContractRegisterId] = append(invoiceMap[invoiceList[i].ContractRegisterId], invoiceList[i]) } if invoiceList[i].InvoiceType == fms.ContractInvoiceTypePay { paymentMap[invoiceList[i].ContractRegisterId] = append(paymentMap[invoiceList[i].ContractRegisterId], invoiceList[i]) } } } respList := make([]*fms.ContractRegisterList, 0) for i := range list { v := new(fms.ContractRegisterList) if list[i].HasPayment == 1 { //代付 if list[i].ContractType == 1 { v.ContractTypeString = "代付合同(新签)" } else if list[i].ContractType == 2 { v.ContractTypeString = "代付合同(续约)" } else { v.ContractTypeString = "代付合同(补充)" } } else { if list[i].ContractType == 1 { v.ContractTypeString = "自付合同(新签)" } else if list[i].ContractType == 2 { v.ContractTypeString = "自付合同(续约)" } else { v.ContractTypeString = "自付合同(补充)" } } v.ContractRegisterItem = list[i] v.ServicesName = serviceMap[list[i].ContractRegisterId] v.InvoiceList = invoiceMap[list[i].ContractRegisterId] v.PaymentList = paymentMap[list[i].ContractRegisterId] respList = append(respList, v) } page.SetTotal(total) baseData := new(base.BaseData) baseData.SetPage(page) baseData.SetList(respList) resp.OkData("获取成功", baseData, c) } // Add // @Title 新增合同登记 // @Description 新增合同登记 // @Param request body fms.ContractRegisterAddReq true "type json string" // @Success 200 string "操作成功" // @router /contract/register/add [post] func (rg *RegisterController) Add(c *gin.Context) { req := new(fms.ContractRegisterAddReq) 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) // 日期校验 startDate, e := time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local) if e != nil { resp.FailMsg("合同开始日期格式有误", "合同开始日期格式有误, Err: "+e.Error(), c) return } endDate, e := time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local) if e != nil { resp.FailMsg("合同结束日期格式有误", "合同结束日期格式有误, Err: "+e.Error(), c) return } signDate, _ := time.ParseInLocation(utils.FormatDate, "0000-00-00", time.Local) if req.SignDate != "" { signDateTime, e := time.ParseInLocation(utils.FormatDate, req.SignDate, time.Local) if e != nil { resp.FailMsg("合同签订日期格式有误", "合同签订日期格式有误, Err: "+e.Error(), c) return } signDate = signDateTime } // 是否存在相同合同编号的登记 ob := new(fms.ContractRegister) existCond := `contract_code = ?` existPars := make([]interface{}, 0) existPars = append(existPars, req.ContractCode) exist, e := ob.FetchByCondition(existCond, existPars) if e != nil && e != utils.ErrNoRow { resp.FailMsg("操作失败", "获取相同登记号失败, Err: "+e.Error(), c) return } if exist != nil && exist.ContractRegisterId > 0 { resp.Fail("合同编号已存在", c) return } // 货币及汇率 rateList, e := fmsService.GetTodayCurrencyRateList() if e != nil { resp.FailMsg("操作失败", "获取今日货币汇率失败, Err: "+e.Error(), c) return } var rate float64 for i := range rateList { if req.CurrencyUnit == rateList[i].Code { rate = rateList[i].RMBRate break } } if rate <= 0 { resp.FailMsg("操作失败", "货币汇率信息有误", c) return } // 查询销售信息 var ( sellerId int raiSellerId int sellerName string raiSellerName string ) if req.SellerIds != "" { admin := new(crm.Admin) sellerIds := strings.Split(req.SellerIds, ",") if len(sellerIds) > 2 { resp.Fail("最多只能选择两个销售", c) return } var pars []interface{} cond := ` admin_id in (?) ` pars = append(pars, sellerIds) sellers, e := admin.List(cond, pars) if e != nil { resp.FailMsg("获取销售信息失败", "获取销售信息失败, Err: "+e.Error(), c) return } for _, v := range sellers { if v.DepartmentId == crm.SellerDepartmentId { sellerId = v.AdminId sellerName = v.RealName } else if v.DepartmentId == crm.RaiSellerDepartmentId { raiSellerId = v.AdminId raiSellerName = v.RealName } } } //新老客户判断 /*newCompany := req.NewCompany if req.ContractType == 1 { newCompany = 1 }else if req.ContractType == 2 || req.ContractType == 3 { newCompany = 0 } if newCompany != req.NewCompany { resp.Fail("请输入正确的客户类型", c) return }*/ nowTime := time.Now().Local() ob.ContractRegisterId = req.ContractRegisterId ob.ContractCode = req.ContractCode ob.RelateContractCode = req.RelateContractCode ob.RelateContractMainCode = req.RelateContractMainCode ob.CrmContractId = req.CrmContractId ob.ContractSource = req.ContractSource ob.CompanyName = req.CompanyName ob.ProductIds = req.ProductIds ob.SellerId = sellerId ob.SellerName = sellerName ob.RaiSellerId = raiSellerId ob.RaiSellerName = raiSellerName ob.ContractType = req.ContractType ob.ContractAmount = req.ContractAmount ob.CurrencyUnit = req.CurrencyUnit ob.RMBRate = rate ob.StartDate = startDate ob.EndDate = endDate ob.SignDate = signDate ob.AgreedPayTime = req.AgreedPayTime ob.ContractStatus = req.ContractStatus ob.RegisterStatus = fms.ContractRegisterStatusIng ob.Remark = req.Remark ob.ServiceRemark = req.ServiceRemark ob.HasPayment = req.HasPayment ob.HasInvoice = req.HasInvoice ob.ActualPayCompanies = req.ActualPayCompanies ob.Set() updateCols := []string{ "ContractCode", "RelateContractCode", "RelateContractMainCode", "CrmContractId", "ContractSource", "ProductIds", "CompanyName", "SellerId", "SellerName", "StartDate", "EndDate", "RaiSellerId", "RaiSellerName", "ModifyTime", "ContractType", "ContractAmount", "CurrencyUnit", "RMBRate", "SignDate", "AgreedPayTime", "ContractStatus", "RegisterStatus", "Remark", "HasPayment", "HasInvoice", "ActualPayCompanies", } // 不需要开票到款的代付直接完成登记, 且不允许进行开票/到款登记 if req.HasInvoice == 0 || req.ContractStatus == fms.ContractStatusEnd { ob.RegisterStatus = fms.ContractRegisterStatusComplete } // 新增套餐金额详情内容 serviceAmountMap := make(map[int]float64) serviceAmountList, e := fmsService.HandleContractServiceAmount(req.ServiceAmount, serviceAmountMap, req.CurrencyUnit) if e != nil { resp.FailMsg("操作失败", "新增合同套餐金额信息失败, Err: "+e.Error(), c) return } //判断产品信息 productIds := make(map[int]struct{}) productIdsStr := "" for _, v := range serviceAmountList { productIds[v.ProductId] = struct{}{} } for proId, _ := range productIds { productIdsStr += strconv.Itoa(proId) + "," } productIdsStr = strings.Trim(productIdsStr, ",") ob.ProductIds = productIdsStr // 套餐信息 serviceList, e := fmsService.HandleContractServiceAndDetail(req.Services, true, serviceAmountMap) if e != nil { resp.FailMsg("操作失败", "获取合同套餐详情失败, Err: "+e.Error(), c) return } // 新增合同及套餐 if req.Supplement == 1 { //新增到款信息 if ob.HasInvoice == 0 { resp.Fail("合同存在代付不允许添加开票/到款登记", c) return } //修改合同信息-假合同变成真合同 if e = ob.Update(updateCols); e != nil { resp.FailMsg("操作失败", "更新合同登记失败, Err:"+e.Error(), c) return } invoiceOB := new(fms.ContractInvoice) invoiceCond := `contract_register_id = ?` invoicePars := make([]interface{}, 0) invoicePars = append(invoicePars, req.ContractRegisterId) invoiceList, e := invoiceOB.List(invoiceCond, invoicePars, "") if e != nil { resp.FailMsg("操作失败", "获取合同开票到款列表失败, Err: "+e.Error(), c) return } // 合同有效时长(计算付款方式) dayDiff := ob.EndDate.Sub(ob.StartDate).Hours() / 24 // 获取销售分组信息 sellerList, e := crmService.GetSellerDepartmentListWithGroupAndTeam() 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] } logList := make([]*fms.ContractRegisterLog, 0) for _, ppItem := range invoiceList { v := &fms.ContractInvoice{ ContractRegisterId: ob.ContractRegisterId, ContractCode: ob.ContractCode, Amount: ppItem.Amount, OriginAmount: ppItem.OriginAmount, CurrencyUnit: ppItem.CurrencyUnit, InvoiceDate: ppItem.InvoiceDate, SellerId: ppItem.SellerId, SellerName: ppItem.SellerName, SellerGroupId: ppItem.SellerGroupId, SellerGroupName: ppItem.SellerGroupName, SellerTeamId: ppItem.SellerTeamId, SellerTeamName: ppItem.SellerTeamName, AdminId: int(adminInfo.AdminId), AdminName: adminInfo.RealName, Remark: ppItem.Remark, ServiceProductId: ppItem.ServiceProductId, IsPrePay: 1, StartDate: ppItem.StartDate, EndDate: ppItem.EndDate, } if ppItem.InvoiceType == 3 { v.InvoiceType = 1 } else if ppItem.InvoiceType == 4 { v.InvoiceType = 2 } v.Set() // 到款登记-付款方式 v.PayType = fmsService.CalculateContractPaymentType(ppItem.Amount, ob.ContractAmount, dayDiff) // 新增的记录 opData := "" opDataByte, e := json.Marshal(req) if e != nil { return } opData = string(opDataByte) opType := fms.ContractRegisterOpTypePreInvoice newAmount := decimal.NewFromFloat(0).Round(2) a := decimal.NewFromFloat(v.Amount).Round(2) newAmount = newAmount.Add(a) ia, _ := newAmount.Round(2).Float64() logList = append(logList, &fms.ContractRegisterLog{ ContractRegisterId: ob.ContractRegisterId, AdminId: int(adminInfo.AdminId), AdminName: adminInfo.RealName, OpData: opData, OpType: opType, CreateTime: nowTime, AmountRemark: fmt.Sprint("新增", fms.ContractInvoiceKeyNameMap[opType], "金额", ia, "元"), }) if e := v.Create(); e != nil { resp.FailData("日期格式有误", "Err:"+e.Error(), c) return } //最后删除预到款记录 e = ppItem.Delete() if e != nil { resp.FailMsg("删除预到款记录失败", "Err:"+e.Error(), c) return } } ppOB := new(fms.ContractPreRegister) items, e := ppOB.FetchByRegisterId(req.ContractRegisterId) if e != nil { if e == utils.ErrNoRow { resp.Fail("预登记记录不存在或已被删除", c) return } resp.FailMsg("获取预登记失败", "Err:"+e.Error(), c) return } for _, item := range items { e = item.Delete() if e != nil { resp.FailMsg("删除预登记失败", "Err:"+e.Error(), c) return } } //更新合同套餐等内容 if e = fms.UpdateSupplementContractPreRegister(ob, serviceAmountList, serviceList); e != nil { resp.FailMsg("操作失败", "更新合同及套餐失败, Err: "+e.Error(), c) return } // 校验金额-是否修改状态 go fmsService.CheckContractRegisterAmount(ob.ContractRegisterId) // 开票到款汇总 go fmsService.SummaryInvoicePaymentByContractRegisterId(ob.ContractRegisterId) // 操作日志 go func() { logOB := new(fms.ContractRegisterLog) if e := logOB.AddInBatches(logList); e != nil { return } }() } else { if e = fms.CreateContractRegisterAndServices(ob, serviceList, serviceAmountList); e != nil { resp.FailMsg("操作失败", "新增合同及套餐失败, Err: "+e.Error(), c) return } } // 操作日志 go func() { opData := "" opDataByte, e := json.Marshal(req) if e != nil { return } opData = string(opDataByte) logItem := new(fms.ContractRegisterLog) logItem.ContractRegisterId = ob.ContractRegisterId logItem.AdminId = int(adminInfo.AdminId) logItem.AdminName = adminInfo.RealName logItem.OpData = opData logItem.OpType = fms.ContractRegisterOpTypeSave logItem.CreateTime = nowTime logItem.Remark = req.Remark if e = logItem.Create(); e != nil { return } }() resp.Ok("操作成功", c) } // Edit // @Title 编辑合同登记 // @Description 编辑合同登记 // @Param request body fms.ContractRegisterEditReq true "type json string" // @Success 200 string "操作成功" // @router /contract/register/edit [post] func (rg *RegisterController) Edit(c *gin.Context) { req := new(fms.ContractRegisterEditReq) 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) // 日期校验 startDate, e := time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local) if e != nil { resp.FailMsg("合同开始日期格式有误", "合同开始日期格式有误, Err: "+e.Error(), c) return } endDate, e := time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local) if e != nil { resp.FailMsg("合同结束日期格式有误", "合同结束日期格式有误, Err: "+e.Error(), c) return } signDate, _ := time.ParseInLocation(utils.FormatDate, "0000-00-00", time.Local) if req.SignDate != "" { signDateTime, e := time.ParseInLocation(utils.FormatDate, req.SignDate, time.Local) if e != nil { resp.FailMsg("合同签订日期格式有误", "合同签订日期格式有误, Err: "+e.Error(), c) return } signDate = signDateTime } 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 } // 查询销售信息 var ( sellerId int raiSellerId int sellerName string raiSellerName string ) if req.SellerIds != "" { admin := new(crm.Admin) sellerIds := strings.Split(req.SellerIds, ",") if len(sellerIds) > 2 { resp.Fail("最多只能选择两个销售", c) return } var pars []interface{} cond := ` admin_id in (?) ` pars = append(pars, sellerIds) sellers, e := admin.List(cond, pars) if e != nil { resp.FailMsg("获取销售信息失败", "获取销售信息失败, Err: "+e.Error(), c) return } for _, v := range sellers { if v.DepartmentId == crm.SellerDepartmentId { sellerId = v.AdminId sellerName = v.RealName } else if v.DepartmentId == crm.RaiSellerDepartmentId { raiSellerId = v.AdminId raiSellerName = v.RealName } } } // 是否存在相同合同编号的登记 existCond := `contract_code = ?` existPars := make([]interface{}, 0) existPars = append(existPars, req.ContractCode) exist, e := ob.FetchByCondition(existCond, existPars) if e != nil && e != utils.ErrNoRow { resp.FailMsg("操作失败", "获取相同登记号失败, Err: "+e.Error(), c) return } if exist != nil && exist.ContractRegisterId > 0 && exist.ContractRegisterId != item.ContractRegisterId { resp.Fail("合同编号已存在", c) return } originHasInvoice := item.HasInvoice updateCols := []string{ "ProductIds", "ContractCode", "RelateContractCode", "CrmContractId", "ContractSource", "CompanyName", "SellerId", "SellerName", "ContractType", "ContractAmount", "StartDate", "EndDate", "SignDate", "AgreedPayTime", "RaiSellerId", "RaiSellerName", "ContractStatus", "RegisterStatus", "Remark", "ServiceRemark", "HasPayment", "ModifyTime", "HasInvoice", "ActualPayCompanies", } nowTime := time.Now().Local() item.ProductIds = req.ProductIds item.ContractCode = req.ContractCode item.RelateContractCode = req.RelateContractCode item.RelateContractMainCode = req.RelateContractMainCode item.CrmContractId = req.CrmContractId item.ContractSource = req.ContractSource item.CompanyName = req.CompanyName item.SellerId = sellerId item.SellerName = sellerName item.RaiSellerId = raiSellerId item.RaiSellerName = raiSellerName item.ContractType = req.ContractType item.ContractAmount = req.ContractAmount item.StartDate = startDate item.EndDate = endDate item.SignDate = signDate item.AgreedPayTime = req.AgreedPayTime item.ContractStatus = req.ContractStatus item.RegisterStatus = fms.ContractRegisterStatusIng item.Remark = req.Remark item.ServiceRemark = req.ServiceRemark item.HasPayment = req.HasPayment item.HasInvoice = req.HasInvoice item.ActualPayCompanies = req.ActualPayCompanies item.ModifyTime = nowTime // 不需要开票到款的直接完成登记, 且不允许进行开票/到款登记 if req.HasInvoice == 0 { item.RegisterStatus = fms.ContractRegisterStatusComplete updateCols = append(updateCols, "RegisterStatus") } // 开票到款信息 invoiceOB := new(fms.ContractInvoice) invoiceCond := `contract_register_id = ?` invoicePars := make([]interface{}, 0) invoicePars = append(invoicePars, req.ContractRegisterId) invoiceList, e := invoiceOB.List(invoiceCond, invoicePars, "") if e != nil { resp.FailMsg("操作失败", "获取合同开票到款列表失败, Err: "+e.Error(), c) return } invoiceUpdateCols := make([]string, 0) // 开票到款操作类型: 0-无; 1-更新; 2-删除; logRemark := req.Remark invoiceHandleType := 0 if originHasInvoice == 1 && req.HasInvoice == 0 { // 若从需要开票改为无需开票, 则删除期间新增的所有开票到款登记 invoiceHandleType = 2 } else { // 修改了货币单位后,同步更新汇率及开票到款的换算金额 if req.CurrencyUnit != item.CurrencyUnit { rateList, e := fmsService.GetTodayCurrencyRateList() if e != nil { resp.FailMsg("操作失败", "获取货币列表及汇率失败, Err: "+e.Error(), c) return } var rate float64 for i := range rateList { if rateList[i].Code == req.CurrencyUnit { rate = rateList[i].RMBRate break } } if rate < 0 { resp.FailMsg("操作失败", "货币汇率有误", c) return } item.CurrencyUnit = req.CurrencyUnit item.RMBRate = rate updateCols = append(updateCols, "CurrencyUnit", "RMBRate") // 调整开票到款换算后的金额, 保留两位小数 for i := range invoiceList { invoiceList[i].CurrencyUnit = req.CurrencyUnit a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", invoiceList[i].OriginAmount/rate), 64) invoiceList[i].Amount = a } invoiceUpdateCols = append(invoiceUpdateCols, "CurrencyUnit", "Amount") invoiceHandleType = 1 logRemark = fmt.Sprintf("金额单位由%s修改为%s\n%s", item.CurrencyUnit, req.CurrencyUnit, logRemark) } } // 新增套餐金额详情内容 serviceAmountMap := make(map[int]float64) serviceAmountList, e := fmsService.HandleContractServiceAmount(req.ServiceAmount, serviceAmountMap, req.CurrencyUnit) if e != nil { resp.FailMsg("操作失败", "新增合同套餐金额信息失败, Err: "+e.Error(), c) return } //判断产品信息 productIds := make(map[int]struct{}) productIdsStr := "" for _, v := range serviceAmountList { productIds[v.ProductId] = struct{}{} } for proId, _ := range productIds { productIdsStr += strconv.Itoa(proId) + "," } productIdsStr = strings.Trim(productIdsStr, ",") item.ProductIds = productIdsStr // 套餐信息 serviceList, e := fmsService.HandleContractServiceAndDetail(req.Services, true, serviceAmountMap) if e != nil { resp.FailMsg("操作失败", "获取合同套餐详情失败, Err: "+e.Error(), c) return } // 更新合同登记、套餐、开票到款 if e = fms.UpdateContractRegister(item, updateCols, serviceList, invoiceList, invoiceUpdateCols, invoiceHandleType, serviceAmountList); e != nil { resp.FailMsg("操作失败", "更新合同及套餐失败, Err: "+e.Error(), c) return } // 自动分配套餐金额 go fmsService.CalculatePaymentServiceAmount(item.ContractRegisterId) // 校验金额-是否修改状态 go fmsService.CheckContractRegisterAmount(item.ContractRegisterId) // 操作日志 go func() { opData := "" opDataByte, e := json.Marshal(req) if e != nil { return } opData = string(opDataByte) logItem := new(fms.ContractRegisterLog) logItem.ContractRegisterId = item.ContractRegisterId logItem.AdminId = int(adminInfo.AdminId) logItem.AdminName = adminInfo.RealName logItem.OpData = opData logItem.OpType = fms.ContractRegisterOpTypeEdit logItem.CreateTime = nowTime logItem.Remark = logRemark if e = logItem.Create(); e != nil { return } }() resp.Ok("操作成功", c) } // Del // @Title 删除合同登记 // @Description 删除合同登记 // @Param request body fms.ContractRegisterDelReq true "type json string" // @Success 200 string "操作成功" // @router /contract/register/del [post] func (rg *RegisterController) Del(c *gin.Context) { req := new(fms.ContractRegisterDelReq) 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) 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 } // 删除对应的开票到款登记 go func() { if e = fms.DeleteContractInvoicesByRegisterId(item.ContractRegisterId); e != nil { alarm_msg.SendAlarmMsg(fmt.Sprintf("删除合同登记%d后, 删除开票到款记录失败, ErrMsg: %s", item.ContractRegisterId, e.Error()), 3) return } if e = fms.DeleteInvoicePaymentSummaryByRegisterId(item.ContractRegisterId); e != nil { alarm_msg.SendAlarmMsg(fmt.Sprintf("删除合同登记%d后, 删除开票到款汇总数据失败, ErrMsg: %s", item.ContractRegisterId, e.Error()), 3) return } }() // 操作日志 go func() { opData := "" opDataByte, e := json.Marshal(req) if e != nil { return } opData = string(opDataByte) logItem := new(fms.ContractRegisterLog) logItem.ContractRegisterId = req.ContractRegisterId logItem.AdminId = int(adminInfo.AdminId) logItem.AdminName = adminInfo.RealName logItem.OpData = opData logItem.OpType = fms.ContractRegisterOpTypeDel logItem.CreateTime = nowTime if e = logItem.Create(); e != nil { return } }() resp.Ok("操作成功", c) } // Detail // @Title 合同登记详情 // @Description 合同登记详情 // @Param ContractRegisterId query int false "合同登记ID" // @Success 200 {object} fms.ContractRegisterDetail // @router /contract/register/detail [get] func (rg *RegisterController) Detail(c *gin.Context) { var req fms.ContractRegisterDetailReq 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 } result := new(fms.ContractRegisterDetail) // 合同登记信息 item, e := fms.GetContractRegisterItemById(req.ContractRegisterId) if e != nil { resp.FailData("获取失败", "获取合同登记详情失败, Err:"+e.Error(), c) return } if item.SellerId != 0 { item.SellerIds = strconv.Itoa(item.SellerId) if item.RaiSellerId != 0 { item.SellerIds += "," + strconv.Itoa(item.RaiSellerId) } } else { if item.RaiSellerId != 0 { item.SellerIds = strconv.Itoa(item.RaiSellerId) } } item.SellerIds = strings.Trim(item.SellerIds, ",") result.ContractRegisterItem = item // 套餐信息 serviceAmountTempList, e := fms.GetContractServiceAmountByRegisterId(req.ContractRegisterId) if e != nil { resp.FailData("获取失败", "获取合同套餐信息失败, Err: "+e.Error(), c) return } serviceAmountList := make([]*fms.ContractServiceAmountItem, 0) for _, v := range serviceAmountTempList { tmp := &fms.ContractServiceAmountItem{ ContractRegisterId: v.ContractRegisterId, ProductId: v.ProductId, ServiceAmount: v.ServiceAmount, CurrencyUnit: v.CurrencyUnit, } serviceAmountList = append(serviceAmountList, tmp) } result.ServiceAmountList = serviceAmountList // 套餐金额信息 serviceList, e := fmsService.GetContractServiceAndDetail(req.ContractRegisterId) if e != nil { resp.FailData("获取失败", "获取合同套餐信息失败, Err: "+e.Error(), c) return } result.ServiceList = serviceList // 开票/到款信息 invoiceCond := `contract_register_id = ?` invoicePars := make([]interface{}, 0) invoicePars = append(invoicePars, req.ContractRegisterId) invoiceList, e := fms.GetContractInvoiceItemList(invoiceCond, invoicePars) if e != nil { resp.FailData("获取失败", "获取合同开票/到款信息失败, Err: "+e.Error(), c) return } result.InvoiceList = make([]*fms.ContractInvoiceItem, 0) result.PaymentList = make([]*fms.ContractInvoiceItem, 0) for i := range invoiceList { if invoiceList[i].InvoiceType == fms.ContractInvoiceTypeMake { result.InvoiceList = append(result.InvoiceList, invoiceList[i]) continue } if invoiceList[i].InvoiceType == fms.ContractInvoiceTypePay { result.PaymentList = append(result.PaymentList, invoiceList[i]) } } // 合同登记进度 logCond := `contract_register_id = ?` logPars := make([]interface{}, 0) logPars = append(logPars, req.ContractRegisterId) logList, e := fms.GetContractRegisterLogItemList(logCond, logPars) if e != nil { resp.FailData("获取失败", "获取合同登记进度失败, Err: "+e.Error(), c) return } result.Logs = logList resp.OkData("获取成功", result, c) } // UpdateStatus // @Title 修改合同状态 // @Description 修改合同状态 // @Param request body fms.ContractRegisterUpdateStatusReq true "type json string" // @Success 200 string "操作成功" // @router /contract/register/update_status [post] func (rg *RegisterController) UpdateStatus(c *gin.Context) { req := new(fms.ContractRegisterUpdateStatusReq) 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) 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.ContractStatus = req.ContractStatus item.ModifyTime = nowTime updateCols := []string{"ContractStatus", "ModifyTime"} if e = item.Update(updateCols); e != nil { resp.FailMsg("操作失败", "更新合同登记失败, Err:"+e.Error(), c) return } // 校验金额-是否修改状态 go fmsService.CheckContractRegisterAmount(req.ContractRegisterId) // 操作日志 go func() { opData := "" opDataByte, e := json.Marshal(req) if e != nil { return } opData = string(opDataByte) logItem := new(fms.ContractRegisterLog) logItem.ContractRegisterId = req.ContractRegisterId logItem.AdminId = int(adminInfo.AdminId) logItem.AdminName = adminInfo.RealName logItem.OpData = opData logItem.OpType = fms.ContractRegisterOpTypeStatus logItem.CreateTime = nowTime if e = logItem.Create(); e != nil { return } }() resp.Ok("操作成功", c) } // Invoice // @Title 开票/到款登记 // @Description 开票/到款登记 // @Param request body fms.ContractInvoiceSaveReq true "type json string" // @Success 200 string "操作成功" // @router /contract/register/invoice [post] func (rg *RegisterController) Invoice(c *gin.Context) { req := new(fms.ContractInvoiceSaveReq) 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) registerOB := new(fms.ContractRegister) item, e := registerOB.Fetch(req.ContractRegisterId) if e != nil { if e == utils.ErrNoRow { resp.Fail("合同登记不存在或已被删除", c) return } resp.FailMsg("获取合同登记失败", "Err:"+e.Error(), c) return } // 合同存在代付不允许开票/到款登记 if item.HasInvoice == 0 { resp.Fail("合同存在代付不允许添加开票/到款登记", c) return } noChangeInvoiceIds := make([]int, 0) newInvoice := make([]*fms.ContractInvoice, 0) if len(req.AmountList) > 0 { // 合同有效时长(计算付款方式) dayDiff := item.EndDate.Sub(item.StartDate).Hours() / 24 // 获取销售分组信息 sellerList, e := crmService.GetSellerDepartmentListWithGroupAndTeam() 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] } for i := range req.AmountList { if req.AmountList[i].Amount <= 0 { resp.Fail("登记金额有误", c) return } if req.AmountList[i].InvoiceDate == "" { resp.Fail("请选择日期", c) return } if req.AmountList[i].ServiceProductId != 1 && req.AmountList[i].ServiceProductId != 2 { resp.Fail("请选择套餐类型", c) return } // 开票登记销售必填 if req.InvoiceType == fms.ContractInvoiceTypeMake && req.AmountList[i].SellerId <= 0 { resp.Fail("请选择销售", c) return } t, e := time.ParseInLocation(utils.FormatDate, req.AmountList[i].InvoiceDate, time.Local) if e != nil { resp.FailData("日期格式有误", "Err:"+e.Error(), c) return } if req.AmountList[i].InvoiceId > 0 { noChangeInvoiceIds = append(noChangeInvoiceIds, req.AmountList[i].InvoiceId) continue } if req.AmountList[i].InvoiceId == 0 { v := &fms.ContractInvoice{ ContractRegisterId: req.ContractRegisterId, ContractCode: item.ContractCode, Amount: req.AmountList[i].Amount, OriginAmount: req.AmountList[i].OriginAmount, CurrencyUnit: item.CurrencyUnit, InvoiceType: req.InvoiceType, ServiceProductId: req.AmountList[i].ServiceProductId, InvoiceDate: t, AdminId: int(adminInfo.AdminId), AdminName: adminInfo.RealName, Remark: req.AmountList[i].Remark, } v.Set() // 开票登记-销售信息 if req.InvoiceType == fms.ContractInvoiceTypeMake { sellerItem := sellerMap[req.AmountList[i].SellerId] if sellerItem == nil { resp.Fail("销售信息异常", c) return } if req.AmountList[i].ServiceProductId == crm.CompanyProductFicc && sellerItem.DepartmentId != crm.SellerDepartmentId { resp.Fail("销售类型和所选套餐类型不一致", c) return } if req.AmountList[i].ServiceProductId == crm.CompanyProductRai && sellerItem.DepartmentId != crm.RaiSellerDepartmentId { 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 req.InvoiceType == fms.ContractInvoiceTypePay { v.PayType = fmsService.CalculateContractPaymentType(req.AmountList[i].Amount, item.ContractAmount, dayDiff) } newInvoice = append(newInvoice, v) } } } // 获取原有的登记信息 invoiceCond := `contract_register_id = ? AND invoice_type = ? ` invoicePars := make([]interface{}, 0) invoicePars = append(invoicePars, req.ContractRegisterId, req.InvoiceType) originInvoiceList, e := fms.GetContractInvoiceItemList(invoiceCond, invoicePars) if e != nil { resp.FailMsg("获取失败", "获取开票/到款列表失败, Err: "+e.Error(), c) return } // 比对原有和现有的登记信息 logList := make([]*fms.ContractRegisterLog, 0) opData := "" opDataByte, e := json.Marshal(req) if e != nil { return } opData = string(opDataByte) opType := fms.ContractRegisterOpTypeInvoice if req.InvoiceType == fms.ContractInvoiceTypePay { opType = fms.ContractRegisterOpTypePayment } nowTime := time.Now().Local() // 需要删除的记录 deleteInvoiceIds := make([]int, 0) for i := range originInvoiceList { if !utils.InArrayByInt(noChangeInvoiceIds, originInvoiceList[i].ContractInvoiceId) { deleteInvoiceIds = append(deleteInvoiceIds, originInvoiceList[i].ContractInvoiceId) logList = append(logList, &fms.ContractRegisterLog{ ContractRegisterId: req.ContractRegisterId, AdminId: int(adminInfo.AdminId), AdminName: adminInfo.RealName, OpData: opData, OpType: opType, CreateTime: nowTime, AmountRemark: fmt.Sprint("删除", fms.ContractInvoiceKeyNameMap[opType], "金额", originInvoiceList[i].Amount, "元"), }) } } // 新增的记录 if len(newInvoice) > 0 { newAmount := decimal.NewFromFloat(0).Round(2) for i := range newInvoice { a := decimal.NewFromFloat(newInvoice[i].Amount).Round(2) newAmount = newAmount.Add(a) } ia, _ := newAmount.Round(2).Float64() logList = append(logList, &fms.ContractRegisterLog{ ContractRegisterId: req.ContractRegisterId, AdminId: int(adminInfo.AdminId), AdminName: adminInfo.RealName, OpData: opData, OpType: opType, CreateTime: nowTime, AmountRemark: fmt.Sprint("新增", fms.ContractInvoiceKeyNameMap[opType], "金额", ia, "元"), }) } // 删除并新增登记 ob := new(fms.ContractInvoice) if e := ob.DeleteAndCreateNewInvoice(req.ContractRegisterId, req.InvoiceType, deleteInvoiceIds, newInvoice); e != nil { resp.FailData("日期格式有误", "Err:"+e.Error(), c) return } // todo 判断是否符合均分金额的条件,如果符合,需要生成金额分配记录表 if req.InvoiceType == fms.ContractInvoiceTypePay { err = fmsService.CalculatePaymentServiceAmount(req.ContractRegisterId) if err != nil { resp.FailMsg("自动分配金额失败", "自动分配金额失败, Err: "+err.Error(), c) return } } // 校验金额-是否修改状态 go fmsService.CheckContractRegisterAmount(req.ContractRegisterId) // 开票到款汇总 go fmsService.SummaryInvoicePaymentByContractRegisterId(req.ContractRegisterId) // 操作日志 go func() { logOB := new(fms.ContractRegisterLog) if e := logOB.AddInBatches(logList); e != nil { return } }() resp.Ok("操作成功", c) } // Export // @Title 合同登记-导出 // @Description 合同登记-导出 // @Param Keyword query string false "关键词" // @Param StartDate query string false "合同开始日期" // @Param EndDate query string false "合同结束日期" // @Param ServiceType query int false "套餐类型" // @Param ContractType query string false "合同类型" // @Param RegisterStatus query int false "登记状态" // @Param ListParam query int false "套餐类型: 0-全部; 1-ficc; 2-权益" // @Success 200 string "操作成功" // @router /contract/register/export [get] func (rg *RegisterController) Export(c *gin.Context) { var req fms.ContractRegisterListReq 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 } cond := `1 = 1` pars := make([]interface{}, 0) // 合同编号/客户姓名/销售/实际使用方 if req.Keyword != "" { kw := "%" + req.Keyword + "%" cond += ` AND (company_name LIKE ? OR contract_code LIKE ? OR seller_name LIKE ? OR actual_company_name LIKE ?)` pars = append(pars, kw, kw, kw, kw) } if req.StartDate != "" && req.EndDate != "" { st := fmt.Sprint(req.StartDate, " 00:00:00") ed := fmt.Sprint(req.EndDate, " 23:59:59") cond += ` AND (create_time BETWEEN ? AND ?)` pars = append(pars, st, ed) } if req.ContractType != "" { newCond := "" typeSlices := strings.Split(req.ContractType, ",") for _, v := range typeSlices { if v[:1] == "0" { //自付 if v[1:] == "1" { newCond += ` (contract_type = 1 AND has_payment=0) ` } else if v[1:] == "2" { newCond += ` (contract_type = 2 AND has_payment=0) ` } else { newCond += ` (contract_type = 4 AND has_payment=0) ` } } else { //代付 if v[1:] == "1" { newCond += ` (contract_type = 1 AND has_payment=1) ` } else if v[1:] == "2" { newCond += ` (contract_type = 2 AND has_payment=1) ` } else { newCond += ` (contract_type = 4 AND has_payment=1) ` } } newCond += " OR " } newCond = strings.TrimRight(newCond, "OR ") cond += " AND " + "(" + newCond + ")" } if req.RegisterStatus != 0 { cond += ` AND register_status = ?` pars = append(pars, req.RegisterStatus) } if req.ServiceTypes != "" { serviceTypes := strings.Split(req.ServiceTypes, ",") registerIds, e := fms.GetContractRegisterIdsByTempId(serviceTypes) if e != nil { resp.FailMsg("获取失败", "获取合同登记IDs失败, Err: "+e.Error(), c) return } if len(registerIds) > 0 { cond += ` AND contract_register_id IN ?` pars = append(pars, registerIds) } else { cond += ` AND 1 = 2` } } if req.ListParam == 1 { cond += ` AND product_ids = '1' ` } else if req.ListParam == 2 { cond += ` AND product_ids = '2' ` } // 获取列表数据 cr := new(fms.ContractRegister) list, e := cr.List(cond, pars) if e != nil { resp.FailData("获取合同列表失败", "Err:"+e.Error(), c) return } if len(list) == 0 { resp.Fail("无有效数据可导出", c) return } registerIds := make([]int, 0) for i := range list { registerIds = append(registerIds, list[i].ContractRegisterId) } // 获取小套餐品种 cpCond := `product_id = ? AND permission_name <> ?` 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]) } } } serviceProductIdMap := map[int]string{ 1: "FICC套餐", 2: "权益套餐", } // 生成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() if req.ListParam == 0 { cell1.HMerge = 8 } else { cell1.HMerge = 7 } 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("") hInt += 8 if req.ListParam == 0 { //如果是全部的话要多一格 titleRow.AddCell().SetString("") hInt += 1 } // 1行2列 if req.ListParam != 2 { cell2 := titleRow.AddCell() cell2.VMerge = 1 cell2.SetString("FICC大套餐") cell2.SetStyle(style) hInt++ } // 1行3列-右合并小套餐数 if permissionLen >= 1 && req.ListParam != 2 { 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++ } } if req.ListParam != 2 { for i := range otherService { cellOther := titleRow.AddCell() cellOther.VMerge = 1 hInt++ cellOther.SetString(otherService[i].Title) cellOther.SetStyle(style) } } if req.ListParam != 1 { //权益大套餐 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("") } if req.ListParam != 1 { //权益分行业套餐 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, "客户名称", "新客户\n0-是\n1-否", "合同类型\n0-自付合同\n1-代付合同", "合同子类型\n续约-0\n新签-1\n补充协议-2", "代付方", "关联主合同(补充协议)", "关联合同(代付合同)") if req.ListParam == 0 { row3Title = append(row3Title, "FICC销售", "权益销售", "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) } } } else if req.ListParam == 1 { row3Title = append(row3Title, "FICC销售", "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]) } } else { row3Title = append(row3Title, "权益销售") // 权益三级套餐 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) } } } row3Title = append(row3Title, "套餐备注", "开始时间", "到期时间", "金额单位") if req.ListParam == 0 { row3Title = append(row3Title, "FICC套餐总金额", "权益套餐总金额") } row3Title = append(row3Title, "约定付款时间", "签订日", "合同状态", "合同编号", "合规备注") // 设置表头 for i := range row3Title { v := titleRow3.AddCell() v.SetString(row3Title[i]) v.SetStyle(style) } // 第二行表头-开票/收款(动态添加) invoiceTitle := []string{"开票日", "开票金额", "套餐类型", "销售", "备注"} for i := 0; i < maxInvoice; i++ { n := i + 1 for ii := range invoiceTitle { c := titleRow3.AddCell() t := fmt.Sprintf("%s%d", invoiceTitle[ii], n) c.SetString(t) c.SetStyle(style) row3Title = append(row3Title, t) } } paymentTitle := []string{"到款日", "到款金额", "套餐类型", "备注"} for i := 0; i < maxPayment; i++ { n := i + 1 for ii := range paymentTitle { c := titleRow3.AddCell() t := fmt.Sprintf("%s%d", paymentTitle[ii], n) c.SetString(t) c.SetStyle(style) row3Title = append(row3Title, t) } } // 此处取第二行标题NameKeyMap, 后面的动态匹配 row2NameKeyMap := make(map[string]int) for i := range row3Title { row2NameKeyMap[row3Title[i]] = i } newCompanyMap := map[int]string{0: "1", 1: "0"} contractTMap := map[int]int{ fms.ContractTypeSelf: 0, fms.ContractTypebehalf: 1, } contractSubTMap := map[int]int{ fms.NewContractTypeNew: 0, fms.NewContractTypeRenew: 1, fms.NewContractTypePlus: 2, // 代付合同 } for _, v := range list { k := -1 // 套餐匹配用 dataRow := sheet.AddRow() dataRow.SetHeight(20) dataRow.AddCell().SetString(v.CompanyName) dataRow.AddCell().SetString(newCompanyMap[v.NewCompany]) dataRow.AddCell().SetString(fmt.Sprint(contractTMap[v.HasPayment])) dataRow.AddCell().SetString(fmt.Sprint(contractSubTMap[v.ContractType])) dataRow.AddCell().SetString(v.ActualPayCompanies) dataRow.AddCell().SetString(v.RelateContractMainCode) dataRow.AddCell().SetString(v.RelateContractCode) if req.ListParam == 0{ dataRow.AddCell().SetString(v.SellerName) dataRow.AddCell().SetString(v.RaiSellerName) } else if req.ListParam == 1{ dataRow.AddCell().SetString(v.SellerName) } else { dataRow.AddCell().SetString(v.RaiSellerName) } if req.ListParam != 0 { k += 9 } else { k += 10 } // 大套餐 col4Name := row3Title[k] svList := serviceMap[v.ContractRegisterId] 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) } // 其他信息 ficcAmount, _ := serviceAmountMap[v.ContractRegisterId][crm.CompanyProductFicc] raiAmount, _ := serviceAmountMap[v.ContractRegisterId][crm.CompanyProductRai] dataRow.AddCell().SetString(v.ServiceRemark) // 套餐备注 dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", v.StartDate)) // 开始时间 dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", v.EndDate)) // 到期时间 //dataRow.AddCell().SetString(fmt.Sprint("¥", v.ContractAmount)) // 2022年合同金额 dataRow.AddCell().SetString(v.CurrencyUnit) // 货币单位 if ficcAmount != nil { dataRow.AddCell().SetString(fmt.Sprint("¥", ficcAmount.ServiceAmount)) // FICC套餐总金额 dataRow.AddCell().SetString("") // 权益套餐总金额 } if raiAmount != nil { dataRow.AddCell().SetString("") // 权益套餐总金额 dataRow.AddCell().SetString(fmt.Sprint("¥", raiAmount.ServiceAmount)) // FICC套餐总金额 } if ficcAmount == nil && raiAmount == nil { dataRow.AddCell().SetString("") // FICC套餐总金额 dataRow.AddCell().SetString("") // 权益套餐总金额 } dataRow.AddCell().SetString(v.AgreedPayTime) // 约定付款时间 dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", v.SignDate)) // 签订日 dataRow.AddCell().SetString(fms.ContractStatusKeyNameMap[v.ContractStatus]) // 合同状态 dataRow.AddCell().SetString(v.ContractCode) // 合同编号 dataRow.AddCell().SetString(v.Remark) // 合规备注 // 开票/到款信息 ivList := invoiceMap[v.ContractRegisterId] ivListLen := len(ivList) for ia := 0; ia < maxInvoice; ia++ { if ia < ivListLen { if ivList != nil && ivList[ia] != nil { dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", ivList[ia].InvoiceDate)) // 开票日 dataRow.AddCell().SetString(fmt.Sprint(ivList[ia].OriginAmount)) // 开票金额 dataRow.AddCell().SetString(serviceProductIdMap[ivList[ia].ServiceProductId]) // 套餐类型 dataRow.AddCell().SetString(ivList[ia].SellerName) // 销售名称 dataRow.AddCell().SetString(ivList[ia].Remark) // 开票备注 continue } } // 这里要把不够的填充为空 dataRow.AddCell().SetString("") dataRow.AddCell().SetString("") dataRow.AddCell().SetString("") dataRow.AddCell().SetString("") dataRow.AddCell().SetString("") } pyList := paymentMap[v.ContractRegisterId] pyListLen := len(pyList) for ib := 0; ib < maxPayment; ib++ { if ib < pyListLen { if pyList != nil && pyList[ib] != nil { dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", pyList[ib].InvoiceDate)) // 收款日 dataRow.AddCell().SetString(fmt.Sprint(pyList[ib].OriginAmount)) // 收款金额 dataRow.AddCell().SetString(serviceProductIdMap[pyList[ib].ServiceProductId]) // 套餐类型 dataRow.AddCell().SetString(pyList[ib].Remark) // 收款备注 continue } } // 这里要把不够的填充为空 dataRow.AddCell().SetString("") dataRow.AddCell().SetString("") dataRow.AddCell().SetString("") dataRow.AddCell().SetString("") } } // 输出文件 var buffer bytes.Buffer _ = xlsxFile.Write(&buffer) content := bytes.NewReader(buffer.Bytes()) randStr := time.Now().Format(utils.FormatDateTimeUnSpace) fileName := sheetName + randStr + ".xlsx" c.Writer.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName)) c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") http.ServeContent(c.Writer, c.Request, fileName, time.Now(), content) } // InvoiceList // @Title 开票/到款列表 // @Description 开票/到款列表 // @Param InvoiceType query int false "类型: 1-开票登记; 2-到款登记" // @Param Keyword query string false "查询关键字" // @Param StartDate query string false "开始日期" // @Param EndDate query string false "结束日期" // @Param MinAmount query float64 false "开票金额区间-最小值" // @Param MaxAmount query float64 false "开票金额区间-最大值" // @Param IsExport query int false "是否导出: 0-否; 1-是" // @Success 200 {object} fms.ContractInvoiceItem // @router /contract/register/invoice_list [get] func (rg *RegisterController) InvoiceList(c *gin.Context) { var req fms.ContractInvoiceListReq 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 = ?` pars := make([]interface{}, 0) pars = append(pars, req.InvoiceType) // 搜索 if req.Keyword != "" { kw := fmt.Sprint("%", req.Keyword, "%") //pars = append(pars, kw) cond += ` AND (b.company_name LIKE ? OR a.contract_code LIKE ?)` pars = append(pars, kw, kw) } if req.StartDate != "" && req.EndDate != "" { st := fmt.Sprint(req.StartDate, " 00:00:00") ed := fmt.Sprint(req.EndDate, " 23:59:59") cond += ` AND (a.invoice_time BETWEEN ? AND ?)` pars = append(pars, st, ed) } if req.MinAmount > 0 { cond += ` AND a.amount >= ?` pars = append(pars, req.MinAmount) } if req.MaxAmount > 0 { cond += ` AND a.amount <= ?` pars = append(pars, req.MaxAmount) } // 套餐类型 if req.ServiceProductId > 0 { cond += ` AND a.service_product_id = ?` pars = append(pars, req.ServiceProductId) } // 销售 if req.SellerIds != "" { sellerIds := strings.Split(req.SellerIds, ",") cond += ` AND (a.seller_id in (?))` pars = append(pars, sellerIds) } // 货币列表 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) currencyTotals := make([]*fms.InvoiceListCurrencyTotal, 0) for i := range currencyList { unitMap[currencyList[i].Code] = currencyList[i].UnitName currencyTotals = append(currencyTotals, &fms.InvoiceListCurrencyTotal{ Name: currencyList[i].Name, UnitName: currencyList[i].UnitName, Code: currencyList[i].Code, FlagImg: currencyList[i].FlagImg, }) } page := new(base.Page) page.SetPageSize(pageSize) page.SetCurrent(pageIndex) page.AddOrderItem(base.OrderItem{Column: "invoice_time", Asc: false}) if req.IsExport == 1 { page.SetPageSize(10000) page.SetCurrent(1) } total, list, e := fms.GetContractInvoiceItemPageList(page, cond, pars) if e != nil { resp.FailMsg("获取失败", "获取合同开票/到款列表失败, Err: "+e.Error(), c) return } page.SetTotal(total) contractRegisterIds := make([]int, 0) contractStatusMap := make(map[int]int) for i := range list { list[i].UnitName = unitMap[list[i].CurrencyUnit] contractRegisterIds = append(contractRegisterIds, list[i].ContractRegisterId) } if len(contractRegisterIds) > 0 { contractRegisters, err := fms.GetContractInfoByRegisterIds(contractRegisterIds) if err != nil { resp.FailMsg("查询合同信息失败", "查询合同信息失败, Err: "+err.Error(), c) return } for _, v := range contractRegisters { contractStatusMap[v.ContractRegisterId] = v.ContractStatus } } for i := range list { list[i].ContractStatus = contractStatusMap[list[i].ContractRegisterId] } // 分币种合计金额 var amountTotal float64 sumList, e := fms.GetInvoiceListCurrencySum(cond, pars, "currency_unit") if e != nil { resp.FailMsg("获取失败", "获取开票/到款列表合计金额失败, Err: "+e.Error(), c) return } sumMap := make(map[string]float64) for i := range sumList { amountTotal += sumList[i].AmountTotal sumMap[sumList[i].CurrencyUnit] = sumList[i].OriginAmountTotal } amountTotal, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", amountTotal), 64) for i := range currencyTotals { a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", sumMap[currencyTotals[i].Code]), 64) currencyTotals[i].Amount = a } respData := &fms.InvoiceListRespData{ Page: page, List: list, AmountTotal: amountTotal, CurrencyTotal: currencyTotals, } // 是否导出 if req.IsExport == 1 { ExportInvoiceList(c, req, respData) return } resp.OkData("获取成功", respData, c) } // ExportInvoiceList 导出开票/到款列表 func ExportInvoiceList(c *gin.Context, req fms.ContractInvoiceListReq, results *fms.InvoiceListRespData) { list := make([]*fms.ContractInvoiceItem, 0) if val, ok := results.List.([]*fms.ContractInvoiceItem); ok { list = val } else { resp.Fail("列表数据有误", c) return } if len(list) == 0 { resp.Fail("列表数据为空", c) return } listName := "开票" if req.InvoiceType == fms.ContractInvoiceTypePay { listName = "到款" } // 生成Excel文件 xlsxFile := xlsx.NewFile() style := xlsx.NewStyle() alignment := xlsx.Alignment{ Horizontal: "center", Vertical: "center", WrapText: true, } style.Alignment = alignment style.ApplyAlignment = true sheet, err := xlsxFile.AddSheet(fmt.Sprintf("%s列表", listName)) if err != nil { resp.FailData("新增Sheet失败", "Err:"+err.Error(), c) return } // 前两行显示合计金额, 第三行空出与列表数据隔一行 rowA := sheet.AddRow() cellAA := rowA.AddCell() rowBData := "" if req.InvoiceType == 1 { cellAA.SetString(fmt.Sprintf("已开票合计金额(换算后):%.2f(元)", results.AmountTotal)) rowBData = "已开票金额:" } else { cellAA.SetString(fmt.Sprintf("已到款合计金额(换算后):%.2f(元)", results.AmountTotal)) rowBData = "已到款金额:" } for _, v := range results.CurrencyTotal { rowBData += fmt.Sprintf("%s%.2f(%s) ", v.Name, v.Amount, v.UnitName) } rowB := sheet.AddRow() rowB.AddCell().SetString(rowBData) sheet.AddRow() // 列表数据表头 titles := []string{"客户名称", "合同编号", "套餐类型", fmt.Sprintf("%s金额", listName), "金额单位", "换算金额(元)", fmt.Sprintf("%s日期", listName), "备注"} titleRow := sheet.AddRow() titleRow.SetHeight(40) for i := range titles { c := titleRow.AddCell() c.SetString(titles[i]) c.SetStyle(style) } ServiceTemplateStrMap := map[int]string{ crm.CompanyProductFicc: "FICC套餐", crm.CompanyProductRai: "权益套餐", } // 单元格赋值 for _, v := range list { dataRow := sheet.AddRow() dataRow.SetHeight(20) dataRow.AddCell().SetString(v.CompanyName) // 客户名称 dataRow.AddCell().SetString(v.ContractCode) // 合同编号 dataRow.AddCell().SetString(ServiceTemplateStrMap[v.ServiceProductId]) // 套餐类型 dataRow.AddCell().SetString(fmt.Sprint(v.OriginAmount)) // 开票金额 dataRow.AddCell().SetString(v.UnitName) // 金额单位 dataRow.AddCell().SetString(fmt.Sprint(v.Amount)) // 换算金额(元) dataRow.AddCell().SetString(v.InvoiceDate) // 开票日 dataRow.AddCell().SetString(v.Remark) // 备注 } // 输出文件 var buffer bytes.Buffer _ = xlsxFile.Write(&buffer) content := bytes.NewReader(buffer.Bytes()) randStr := time.Now().Format(utils.FormatDateTimeUnSpace) fileName := fmt.Sprintf("%s列表_%s.xlsx", listName, randStr) 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) } // Import // @Title 合同登记-导入 // @Description 合同登记-导入 // @Success 200 string "操作成功" // @router /contract/register/import [post] func (rg *RegisterController) Import(c *gin.Context) { h, err := c.FormFile("File") if err != nil { resp.FailData("获取文件失败", "Err:"+err.Error(), c) return } ext := path.Ext(h.Filename) if ext != ".xlsx" && ext != ".xls" { resp.Fail("请上传Excel文件", c) return } uploadDir := "static/xls" err = os.MkdirAll(uploadDir, 766) if err != nil { resp.FailData("存储目录创建失败", "Err:"+err.Error(), c) return } uploadPath := uploadDir + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + h.Filename err = c.SaveUploadedFile(h, uploadPath) if err != nil { resp.FailData("保存本地文件失败", "Err:"+err.Error(), c) return } defer func() { _ = os.Remove(uploadPath) }() xlFile, err := xlsx.OpenFile(uploadPath) if err != nil { resp.FailData("打开文件失败", "Err:"+err.Error(), c) return } // 获取所有已登记,根据合同编号去重 contractCodeArr := make([]string, 0) registerOB := new(fms.ContractRegister) registerCond := `` registerPars := make([]interface{}, 0) registerList, e := registerOB.List(registerCond, registerPars) if e != nil { resp.FailData("获取合同登记列表失败", "Err:"+e.Error(), c) return } for i := range registerList { contractCodeArr = append(contractCodeArr, registerList[i].ContractCode) } // 获取所有销售Map sellerList, e := crmService.GetSellerDepartmentListWithGroupAndTeam() if e != nil { resp.FailData("获取销售列表失败", "Err:"+e.Error(), c) return } sellerMap := make(map[string]*crm.SellerAdminWithGroupTeam) for i := range sellerList { sellerMap[sellerList[i].SellerName] = sellerList[i] } // 获取品种权限Map chartPermissionNameIdMap := make(map[string]int) cpCond := `product_id = ?` cpPars := make([]interface{}, 0) cpPars = append(cpPars, crm.CompanyProductFicc) cp := new(crm.ChartPermission) permissionList, e := cp.List(cpCond, cpPars) if e != nil { resp.FailData("获取权限列表失败", "Err:"+e.Error(), c) return } for i := range permissionList { chartPermissionNameIdMap[permissionList[i].PermissionName] = permissionList[i].ChartPermissionId } // 获取所有套餐模板 serviceTempCond := `` serviceTempPars := make([]interface{}, 0) serviceTempOB := new(fms.ContractServiceTemplate) serviceTempList, e := serviceTempOB.List(serviceTempCond, serviceTempPars) if e != nil { resp.FailData("获取套餐模板列表失败", "Err:"+e.Error(), c) return } serviceTempNameMap := make(map[string]*fms.ContractServiceTemplate) serviceTempFullNameMap := make(map[string]*fms.ContractServiceTemplate) serviceTempIdMap := make(map[int]*fms.ContractServiceTemplate) for i := range serviceTempList { serviceTempIdMap[serviceTempList[i].ServiceTemplateId] = serviceTempList[i] serviceTempNameMap[serviceTempList[i].Title] = serviceTempList[i] } for i := range serviceTempList { fullName := serviceTempList[i].Title if serviceTempList[i].Pid > 0 { parentItem := serviceTempIdMap[serviceTempList[i].Pid] fullName += "_" + parentItem.Title if parentItem.Pid > 0 { fullName += "_" + serviceTempIdMap[parentItem.Pid].Title } } serviceTempFullNameMap[fullName] = serviceTempList[i] } //权益行业套餐名称 raiIndustryMap := map[int]string{ 40: "医药", 41: "医药", 42: "消费", 43: "消费", 44: "科技", 45: "科技", 46: "智造", 48: "智造", 49: "策略", } // 获取货币列表及汇率(汇率为导入日的汇率) rateList, e := fmsService.GetTodayCurrencyRateList() if e != nil { resp.FailData("获取货币列表及汇率失败", "Err:"+e.Error(), c) return } rateMap := make(map[string]float64) for i := range rateList { rateMap[rateList[i].Code] = rateList[i].RMBRate } titleMap := make(map[int]string) newIds := make([]int, 0) newCompanyArr := []string{"0", "1"} newCompanyMap := map[string]int{"0": 1, "1": 0} contractTypeArr := []string{"0", "1"} contractTMap := map[string]int{ "0": fms.ContractTypeSelf, "1": fms.ContractTypebehalf, } contractSubTypeArr := []string{"0", "1", "2"} contractSubTMap := map[string]int{ "1": fms.NewContractTypeNew, "0": fms.NewContractTypeRenew, "2": fms.NewContractTypePlus, } // 更新登记状态 defer func() { if len(newIds) > 0 { go func() { for i := range newIds { fmsService.CheckContractRegisterAmount(newIds[i]) fmsService.SummaryInvoicePaymentByContractRegisterId(newIds[i]) } }() } }() invoiceMax := 3 checkDate := time.Date(1900, 1, 1, 0, 0, 0, 0, time.Local) for _, sheet := range xlFile.Sheets { // 遍历行读取 maxRow := sheet.MaxRow for i := 0; i < maxRow; i++ { // 第三行开始读取表头 if i == 2 { row := sheet.Row(i) cells := row.Cells for k, cell := range cells { text := cell.String() titleMap[k] = text // 只检验前面部分表头, 后面很多动态列 if k == 0 { if text != "客户名称" { resp.Fail("【客户名称】列名称有误, 请参考模板导入", c) return } continue } else if k == 1 { if !strings.Contains(text, "新客户") { resp.Fail("【新客户】列名称有误, 请参考模板导入", c) return } continue } else if k == 2 { if !strings.Contains(text, "合同类型") { resp.Fail("【合同类型】列名称有误, 请参考模板导入", c) return } continue } else if k == 3 { if !strings.Contains(text, "合同子类型") { resp.Fail("【合同子类型】列名称有误, 请参考模板导入", c) return } continue } else if k == 4 { if text != "代付方" { resp.Fail("【代付方】列名称有误, 请参考模板导入", c) return } continue } else if k == 5 { if !strings.Contains(text, "关联主合同") { resp.Fail("【关联主合同】列名称有误, 请参考模板导入", c) return } continue } else if k == 6 { if !strings.Contains(text, "关联合同") { resp.Fail("【关联合同】列名称有误, 请参考模板导入", c) return } continue } else if k == 7 { if text != "FICC销售" { resp.Fail("【FICC销售】列名称有误, 请参考模板导入", c) return } continue } else if k == 8 { if text != "权益销售" { resp.Fail("【权益销售】列名称有误, 请参考模板导入", c) return } continue } else if k == 9 { if text != "FICC大套餐" { resp.Fail("【FICC大套餐】列名称有误, 请参考模板导入", c) return } continue } } } else if i >= 3 { // 数据行 row := sheet.Row(i) cells := row.Cells // 登记信息 rowRegister := new(fms.ContractRegister) // 套餐 rowServices := make([]*fms.ContractService, 0) // 套餐金额 rowServiceAmount := make([]*fms.ContractServiceAmount, 0) // 开票/到款 rowInvoices := make([]*fms.ContractInvoice, 0) for ir := 0; ir < invoiceMax; ir++ { rowInvoices = append(rowInvoices, new(fms.ContractInvoice)) } rowPayments := make([]*fms.ContractInvoice, 0) for ir := 0; ir < invoiceMax; ir++ { rowPayments = append(rowPayments, new(fms.ContractInvoice)) } // 小套餐权限 rowChartPermissionIdArr := make([]string, 0) productIds := make(map[int]struct{}) isSkip := false for k, cell := range cells { fmt.Println("k:", k) fmt.Println("cell:", cell.Value) v := utils.TrimStr(cell.String()) // 客户名称 if k == 0 { if v == "" { resp.Fail(fmt.Sprintf("第%d行客户名称不可为空, 请按模板导入", i+1), c) return } rowRegister.CompanyName = v continue } // 是否新客户 if k == 1 { if !utils.InArrayByStr(newCompanyArr, v) { resp.Fail(fmt.Sprintf("第%d行新客户有误, 请按模板导入", i+1), c) return } rowRegister.NewCompany = newCompanyMap[v] continue } // 合同类型 if k == 2 { if !utils.InArrayByStr(contractTypeArr, v) { resp.Fail(fmt.Sprintf("第%d行合同类型有误, 请按模板导入", i+1), c) return } rowRegister.HasPayment = contractTMap[v] continue } if k == 3 { if !utils.InArrayByStr(contractSubTypeArr, v) { resp.Fail(fmt.Sprintf("第%d行合同类型有误, 请按模板导入", i+1), c) return } rowRegister.ContractType = contractSubTMap[v] if rowRegister.ContractType == 0 { resp.Fail(fmt.Sprintf("第%d行合同子类型匹配有误, 请按模板导入", i+1), c) return } continue } if k == 4 { rowRegister.ActualPayCompanies = v continue } if k == 5 { rowRegister.RelateContractMainCode = v continue } if k == 6 { rowRegister.RelateContractCode = v continue } // FICC销售 if k == 7 { if v != "" { /*resp.Fail(fmt.Sprintf("第%d行销售名称不可为空, 请按模板导入", i+1), c) return*/ sellerItem := sellerMap[v] if sellerItem == nil { resp.Fail(fmt.Sprintf("第%d行销售名称与系统销售不匹配, 请核对名称后导入", i+1), c) return } rowRegister.SellerId = sellerItem.SellerId rowRegister.SellerName = sellerItem.SellerName } continue } // 权益销售 if k == 8 { if v == "" && rowRegister.SellerName == "" { resp.Fail(fmt.Sprintf("第FICC销售名称和权益销售名称不可都为空, 请按模板导入", i+1), c) return } sellerItem := sellerMap[v] if sellerItem == nil { resp.Fail(fmt.Sprintf("第%d行权益销售名称与系统销售不匹配, 请核对名称后导入", i+1), c) return } rowRegister.RaiSellerId = sellerItem.SellerId rowRegister.RaiSellerName = sellerItem.SellerName continue } // FICC大套餐 if k == 9 { if v == "是" { tempItem := serviceTempNameMap[titleMap[k]] if tempItem == nil { resp.Fail(fmt.Sprintf("第%d行%d列套餐名称不匹配, 请按模板导入", i+1, k+1), c) return } cs := &fms.ContractService{ ProductId: crm.CompanyProductFicc, ServiceTemplateId: tempItem.ServiceTemplateId, Title: tempItem.Title, Value: tempItem.Value, TableValue: tempItem.TableValue, ChartPermissionId: tempItem.ChartPermissionId, } cs.Set() rowServices = append(rowServices, cs) productIds[crm.CompanyProductFicc] = struct{}{} } continue } // FICC小套餐 if k >= 10 && k <= 30 { // 小套餐权限 if v == "是" { rowChartPermissionIdArr = append(rowChartPermissionIdArr, strconv.Itoa(chartPermissionNameIdMap[titleMap[k]])) productIds[crm.CompanyProductFicc] = struct{}{} } continue } // 其他类型套餐 if k >= 31 && k <= 37 { if v == "是" { tempItem := serviceTempNameMap[titleMap[k]] if tempItem == nil { resp.Fail(fmt.Sprintf("第%d行%d列套餐名称不匹配, 请按模板导入", i+1, k+1), c) return } cs := &fms.ContractService{ ProductId: crm.CompanyProductFicc, ServiceTemplateId: tempItem.ServiceTemplateId, Title: tempItem.Title, Value: tempItem.Value, TableValue: tempItem.TableValue, ChartPermissionId: tempItem.ChartPermissionId, } cs.Set() rowServices = append(rowServices, cs) productIds[crm.CompanyProductFicc] = struct{}{} } continue } if k >= 38 && k <= 48 { if v == "是" { // 权益大套餐 if k <= 41 { //新增 parentName := "权益大套餐" tempItem := serviceTempNameMap[titleMap[k]] if tempItem == nil { resp.Fail(fmt.Sprintf("第%d行%d列套餐名称不匹配, 请按模板导入", i+1, k+1), c) return } cs := &fms.ContractService{ ProductId: crm.CompanyProductRai, ServiceTemplateId: tempItem.ServiceTemplateId, Title: tempItem.Title, Value: tempItem.Value, TableValue: tempItem.TableValue, ChartPermissionId: tempItem.ChartPermissionId, } rowServices = append(rowServices, cs) tempItem = serviceTempNameMap[parentName] if tempItem == nil { resp.Fail(fmt.Sprintf("第%d行%d列套餐名称不匹配, 请按模板导入", i+1, k+1), c) return } cs = &fms.ContractService{ ProductId: crm.CompanyProductRai, ServiceTemplateId: tempItem.ServiceTemplateId, Title: tempItem.Title, Value: tempItem.Value, TableValue: tempItem.TableValue, ChartPermissionId: tempItem.ChartPermissionId, } rowServices = append(rowServices, cs) } else { rootName := "行业套餐" // 新增三条套餐信息 parentName, _ := raiIndustryMap[k] childName := titleMap[k] fullName := childName + "_" + parentName + "_" + rootName if fullName != "" { //增加三级权限 tempItem := serviceTempFullNameMap[fullName] fmt.Println("fullName:", fullName) fmt.Println("serviceTempFullNameMap:", serviceTempFullNameMap) if tempItem == nil { resp.Fail(fmt.Sprintf("第%d行%d列套餐名称不匹配, 请按模板导入", i+1, k+1), c) return } cs := &fms.ContractService{ ProductId: crm.CompanyProductRai, ServiceTemplateId: tempItem.ServiceTemplateId, Title: tempItem.Title, Value: tempItem.Value, TableValue: tempItem.TableValue, ChartPermissionId: tempItem.ChartPermissionId, } rowServices = append(rowServices, cs) //增加二级权限 tempItem = serviceTempFullNameMap[parentName+"_"+rootName] if tempItem == nil { resp.Fail(fmt.Sprintf("第%d行%d列套餐名称不匹配, 请按模板导入", i+1, k+1), c) return } cs = &fms.ContractService{ ProductId: crm.CompanyProductRai, ServiceTemplateId: tempItem.ServiceTemplateId, Title: tempItem.Title, Value: tempItem.Value, TableValue: tempItem.TableValue, ChartPermissionId: tempItem.ChartPermissionId, } rowServices = append(rowServices, cs) //增加一级权限 tempItem = serviceTempFullNameMap[rootName] if tempItem == nil { resp.Fail(fmt.Sprintf("第%d行%d列套餐名称不匹配, 请按模板导入", i+1, k+1), c) return } cs = &fms.ContractService{ ProductId: crm.CompanyProductRai, ServiceTemplateId: tempItem.ServiceTemplateId, Title: tempItem.Title, Value: tempItem.Value, TableValue: tempItem.TableValue, ChartPermissionId: tempItem.ChartPermissionId, } rowServices = append(rowServices, cs) } } productIds[crm.CompanyProductRai] = struct{}{} } continue } // 权益研选等套餐 if k >= 49 && k <= 53 { if v == "是" { tempItem := serviceTempNameMap[titleMap[k]] if tempItem == nil { resp.Fail(fmt.Sprintf("第%d行%d列套餐名称不匹配, 请按模板导入", i+1, k+1), c) return } cs := &fms.ContractService{ ProductId: crm.CompanyProductRai, ServiceTemplateId: tempItem.ServiceTemplateId, Title: tempItem.Title, Value: tempItem.Value, TableValue: tempItem.TableValue, ChartPermissionId: tempItem.ChartPermissionId, } cs.Set() rowServices = append(rowServices, cs) productIds[crm.CompanyProductRai] = struct{}{} } continue } // 套餐备注 if k == 54 { rowRegister.ServiceRemark = v continue } // 开始时间/到期时间 if k == 57 { // 转换失败可能是因为格式为Excel日期格式, 读取出来会是一串数字, 将其转换成日期字符串再处理 va := cell.Value if va == "" { resp.Fail(fmt.Sprintf("第%d行%d列开始时间不可为空, 请按模板导入", i+1, k+1), c) return } startDate, e := time.ParseInLocation("2006/01/02", va, time.Local) if e != nil { d := utils.ConvertToFormatDay(va, "2006/01/02") startDate, e = time.ParseInLocation("2006/01/02", d, time.Local) if e != nil { resp.Fail(fmt.Sprintf("第%d行开始时间格式转换有误, 请按模板导入", i+1), c) return } } // 转换后的日期小于1900-01-01表示当前生成的日期是有问题的 if startDate.Before(checkDate) { resp.Fail(fmt.Sprintf("第%d行开始时间格式有误, 请按模板导入", i+1), c) return } rowRegister.StartDate = startDate continue } if k == 58 { va := cell.Value if va == "" { resp.Fail(fmt.Sprintf("第%d行到期时间不可为空, 请按模板导入", i+1), c) return } endDate, e := time.ParseInLocation("2006/01/02", va, time.Local) if e != nil { d := utils.ConvertToFormatDay(va, "2006/01/02") endDate, e = time.ParseInLocation("2006/01/02", d, time.Local) if e != nil { resp.Fail(fmt.Sprintf("第%d行到期时间格式转换有误, 请按模板导入", i+1), c) return } } if endDate.Before(checkDate) { resp.Fail(fmt.Sprintf("第%d行到期时间格式有误, 请按模板导入", i+1), c) return } rowRegister.EndDate = endDate continue } // 合同金额 if k == 59 { amountStr := v amount, e := strconv.ParseFloat(amountStr, 64) if e != nil { resp.Fail(fmt.Sprintf("第%d行合同金额有误, 请按模板导入", i+1), c) return } rowRegister.ContractAmount = amount continue } // 金额单位 if k == 60 { rate := rateMap[v] if rate <= 0 { resp.Fail(fmt.Sprintf("第%d行金额单位有误, 请按模板导入", i+1), c) return } rowRegister.CurrencyUnit = v rowRegister.RMBRate = rate continue } // FICC 套餐总金额 if k == 61 { amountStr := v amount, e := strconv.ParseFloat(amountStr, 64) if e != nil { resp.Fail(fmt.Sprintf("第%d行FICC套餐总金额有误, 请按模板导入", i+1), c) return } if amount > 0 { tmp := &fms.ContractServiceAmount{ ProductId: crm.CompanyProductFicc, ServiceAmount: amount, CurrencyUnit: rowRegister.CurrencyUnit, TimeBase: base.TimeBase{}, } rowServiceAmount = append(rowServiceAmount, tmp) } continue } // 权益套餐总金额 if k == 62 { amountStr := v amount, e := strconv.ParseFloat(amountStr, 64) if e != nil { resp.Fail(fmt.Sprintf("第%d行权益套餐总金额有误, 请按模板导入", i+1), c) return } if amount > 0 { tmp := &fms.ContractServiceAmount{ ProductId: crm.CompanyProductRai, ServiceAmount: amount, CurrencyUnit: rowRegister.CurrencyUnit, TimeBase: base.TimeBase{}, } rowServiceAmount = append(rowServiceAmount, tmp) } continue } // 约定付款日期 if k == 63 { rowRegister.AgreedPayTime = v continue } // 签订日 if k == 64 { va := cell.Value if va == "" { continue } signDate, e := time.ParseInLocation("2006/01/02", va, time.Local) if e != nil { d := utils.ConvertToFormatDay(va, "2006/01/02") signDate, e = time.ParseInLocation("2006/01/02", d, time.Local) if e != nil { resp.Fail(fmt.Sprintf("第%d行签订日格式转换有误, 请按模板导入", i+1), c) return } } if signDate.Before(checkDate) { resp.Fail(fmt.Sprintf("第%d行签订日格式有误, 请按模板导入", i+1), c) return } rowRegister.SignDate = signDate continue } // 合同状态 if k == 65 { rowRegister.ContractStatus = fms.ContractStatusNameKeyMap[v] if rowRegister.ContractStatus == 0 { resp.Fail(fmt.Sprintf("第%d行合同状态不匹配, 请按模板导入", i+1), c) return } continue } // 合同编号 if k == 66 { rowContractCode := v if rowContractCode == "" { resp.Fail(fmt.Sprintf("第%d行合同编号不可为空, 请按模板导入", i+1), c) return } if utils.InArrayByStr(contractCodeArr, rowContractCode) { // 此合同已登记, 跳过本行的读取 isSkip = true break } rowRegister.ContractCode = rowContractCode continue } // 合规备注 if k == 67 { rowRegister.Remark = v continue } // 开票列表 k2 := 67 for ir := 0; ir < invoiceMax; ir++ { n := ir + 1 // 开票日 k2 += 1 if k == k2 { if v != "" { va := cell.Value invoiceDate, e := time.ParseInLocation("2006/01/02", va, time.Local) if e != nil { d := utils.ConvertToFormatDay(va, "2006/01/02") invoiceDate, e = time.ParseInLocation("2006/01/02", d, time.Local) if e != nil { resp.Fail(fmt.Sprintf("第%d行开票时间%d格式转换有误, 请按模板导入", i+1, n), c) return } } if invoiceDate.Before(checkDate) { resp.Fail(fmt.Sprintf("第%d行开票时间%d格式有误, 请按模板导入", i+1, n), c) return } rowInvoices[ir].InvoiceDate = invoiceDate rowInvoices[ir].ContractCode = rowRegister.ContractCode rowInvoices[ir].InvoiceType = fms.ContractInvoiceTypeMake } continue } // 开票金额 k2 += 1 if k == k2 { if v != "" { amountStr := v amount, e := strconv.ParseFloat(amountStr, 64) if e != nil { resp.Fail(fmt.Sprintf("第%d行开票金额%d有误, 请按模板导入", i+1, n), c) return } if rowRegister.RMBRate <= 0 { resp.Fail(fmt.Sprintf("第%d行开票金额换算%d有误, 请按模板导入金额单位", i+1, n), c) return } a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", amount/rowRegister.RMBRate), 64) rowInvoices[ir].OriginAmount = amount rowInvoices[ir].Amount = a } continue } // 开票套餐类型 k2 += 1 if k == k2 { if v != "" { if v == "FICC套餐" { rowInvoices[ir].ServiceProductId = crm.CompanyProductFicc } else if v == "权益套餐" { rowInvoices[ir].ServiceProductId = crm.CompanyProductRai } else { resp.Fail(fmt.Sprintf("第%d行开票套餐类型%d:%s有误, 请按模板导入", i+1, n, v), c) return } } continue } // 开票销售 k2 += 1 if k == k2 { if v != "" { sellerItem := sellerMap[v] if sellerItem == nil { resp.Fail(fmt.Sprintf("第%d行开票销售名称与系统销售不匹配, 请核对名称后导入", i+1), c) return } rowInvoices[ir].SellerId = sellerItem.SellerId rowInvoices[ir].SellerName = sellerItem.SellerName rowInvoices[ir].SellerGroupId = sellerItem.GroupId rowInvoices[ir].SellerGroupName = sellerItem.GroupName rowInvoices[ir].SellerTeamId = sellerItem.TeamId rowInvoices[ir].SellerTeamName = sellerItem.TeamName } continue } // 备注 k2 += 1 if k == k2 { if v != "" { rowInvoices[ir].Remark = v } continue } } // 到款列表 for ir := 0; ir < invoiceMax; ir++ { n := ir + 1 // 到款日 k2 += 1 if k == k2 { if v != "" { va := cell.Value invoiceDate, e := time.ParseInLocation("2006/01/02", va, time.Local) if e != nil { d := utils.ConvertToFormatDay(va, "2006/01/02") invoiceDate, e = time.ParseInLocation("2006/01/02", d, time.Local) if e != nil { resp.Fail(fmt.Sprintf("第%d行到款时间%d格式转换有误, 请按模板导入", i+1, n), c) return } } if invoiceDate.Before(checkDate) { resp.Fail(fmt.Sprintf("第%d行到款时间%d格式有误, 请按模板导入", i+1, n), c) return } rowPayments[ir].InvoiceDate = invoiceDate rowPayments[ir].ContractCode = rowRegister.ContractCode rowPayments[ir].InvoiceType = fms.ContractInvoiceTypePay } continue } // 到款金额 k2 += 1 if k == k2 { if v != "" { amountStr := v amount, e := strconv.ParseFloat(amountStr, 64) if e != nil { resp.Fail(fmt.Sprintf("第%d行到款金额%d有误, 请按模板导入", i+1, n), c) return } if rowRegister.RMBRate <= 0 { resp.Fail(fmt.Sprintf("第%d行到款金额换算%d有误, 请按模板导入金额单位", i+1, n), c) return } // 付款方式 dayDiff := rowRegister.EndDate.Sub(rowRegister.StartDate).Hours() / 24 contractAmount := rowRegister.ContractAmount payType := fmsService.CalculateContractPaymentType(amount, contractAmount, dayDiff) rowPayments[ir].PayType = payType rowPayments[ir].OriginAmount = amount a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", amount/rowRegister.RMBRate), 64) rowPayments[ir].Amount = a } continue } // 到款套餐类型 k2 += 1 if k == k2 { if v != "" { if v == "FICC套餐" { rowPayments[ir].ServiceProductId = crm.CompanyProductFicc } else if v == "权益套餐" { rowPayments[ir].ServiceProductId = crm.CompanyProductRai } else { resp.Fail(fmt.Sprintf("第%d行到款套餐类型%d:%s有误, 请按模板导入", i+1, n, v), c) return } } continue } // 备注 k2 += 1 if k == k2 { if v != "" { rowPayments[ir].Remark = v } continue } } } if isSkip { continue } // 小套餐 if len(rowChartPermissionIdArr) > 0 { // 说明有小套餐 tempItem := serviceTempNameMap["FICC小套餐"] if tempItem == nil { resp.Fail(fmt.Sprintf("第%d行小套餐名称不匹配, 请按模板导入", i+1), c) return } rowChartPermissionIds := strings.Join(rowChartPermissionIdArr, ",") cs := &fms.ContractService{ ProductId: crm.CompanyProductFicc, ServiceTemplateId: tempItem.ServiceTemplateId, Title: tempItem.Title, Value: tempItem.Value, TableValue: tempItem.TableValue, ChartPermissionId: tempItem.ChartPermissionId, ChartPermissionIds: rowChartPermissionIds, } cs.Set() rowServices = append(rowServices, cs) } // 如果导入的最后一条合同编号为空并且合同编号之后的字段均为空 // excel这个包读行的时候不会再往后面没数据的地方读取, 所以此处需要重新判断一次 if rowRegister.ContractCode == "" { resp.Fail(fmt.Sprintf("第%d行合同编号为空", i+1), c) return } rowRegister.RegisterStatus = fms.ContractRegisterStatusIng rowInvoiceList := make([]*fms.ContractInvoice, 0) // 过滤信息不完整的开票到款 for l := range rowInvoices { if rowInvoices[l].ContractCode != "" { if rowInvoices[l].OriginAmount <= 0 || rowInvoices[l].SellerId == 0 { resp.Fail(fmt.Sprintf("第%d行开票信息必填项不完整", i+1), c) return } rowInvoiceList = append(rowInvoiceList, rowInvoices[l]) } } for l := range rowPayments { if rowPayments[l].ContractCode != "" { if rowPayments[l].OriginAmount <= 0 { resp.Fail(fmt.Sprintf("第%d行到款信息必填项不完整", i+1), c) return } rowInvoiceList = append(rowInvoiceList, rowPayments[l]) } } // 新增登记、套餐、开票到款信息 for proId, _ := range productIds { rowRegister.ProductIds += strconv.Itoa(proId) + "," } rowRegister.ProductIds = strings.Trim(rowRegister.ProductIds, ",") newId, e := fms.CreateImportContractRegister(rowRegister, rowServices, rowInvoiceList, rowServiceAmount) if e != nil { resp.FailData(fmt.Sprintf("第%d行导入失败", i+1), "新增导入登记失败, Err: "+e.Error(), c) return } // 自动分配套餐金额 go fmsService.CalculatePaymentServiceAmount(newId) newIds = append(newIds, newId) } } } resp.Ok("操作成功", c) } // CurrencyList // @Title 货币单位列表 // @Description 货币单位列表 // @Success 200 {object} fms.CurrencyUnitItem // @router /contract/register/currency_list [get] func (rg *RegisterController) CurrencyList(c *gin.Context) { list, e := fmsService.GetTodayCurrencyRateList() if e != nil { resp.FailData("获取失败", "获取今日货币汇率列表失败, Err: "+e.Error(), c) return } resp.OkData("获取成功", list, c) } // CheckContractName // @Title 货币单位列表 // @Description 货币单位列表 // @Success 200 {object} fms.CheckContractNameResp // @router /contract/register/check_contract_code [get] func (rg *RegisterController) CheckContractName(c *gin.Context) { var req fms.CheckContractNameReq 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 } existCond := "" existPars := make([]interface{}, 0) if req.CompanyName != "" { // 是否存在相同的合同名称的登记 existCond = ` company_name = ?` existPars = append(existPars, req.CompanyName) } if req.StartDate != "" && req.EndDate != "" { // 日期校验 startDate, e := time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local) if e != nil { resp.FailMsg("合同开始日期格式有误", "合同开始日期格式有误, Err: "+e.Error(), c) return } endDate, e := time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local) if e != nil { resp.FailMsg("合同结束日期格式有误", "合同结束日期格式有误, Err: "+e.Error(), c) return } if existCond != "" { existCond += ` AND (start_date =? and end_date=?)` } else { existCond = ` start_date = ? and end_date=?` } existPars = append(existPars, startDate, endDate) } if req.SellerIds != "" { admin := new(crm.Admin) sellerIds := strings.Split(req.SellerIds, ",") if len(sellerIds) > 2 { resp.Fail("最多只能选择两个销售", c) return } var pars []interface{} cond := ` admin_id in (?) ` pars = append(pars, sellerIds) sellers, e := admin.List(cond, pars) if e != nil { resp.FailMsg("获取销售信息失败", "获取销售信息失败, Err: "+e.Error(), c) return } var sellerId, raiSellerId int for _, v := range sellers { if v.DepartmentId == crm.SellerDepartmentId { sellerId = v.AdminId } else if v.DepartmentId == crm.RaiSellerDepartmentId { raiSellerId = v.AdminId } } existCond += ` AND (seller_id =? and rai_seller_id=?)` existPars = append(existPars, sellerId, raiSellerId) } if existCond == "" { resp.Fail("请输入合同名称或者合同有效期", c) return } // 是否存在相同合同名称的登记 ob := new(fms.ContractRegister) data := fms.CheckContractNameResp{ Exist: 0, } _, e := ob.FetchByCondition(existCond, existPars) if e != nil { if e == utils.ErrNoRow { resp.OkData("查询成功", data, c) return } resp.FailMsg("查询失败", "查询相同登记号失败, Err: "+e.Error(), c) return } data.Exist = 1 resp.OkData("查询成功", data, c) return }