package contract import ( "encoding/json" "fmt" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "hongze/fms_api/controller/resp" "hongze/fms_api/global" "hongze/fms_api/models/base" "hongze/fms_api/models/fms" "hongze/fms_api/models/system" "hongze/fms_api/services/alarm_msg" fmsService "hongze/fms_api/services/fms" "hongze/fms_api/utils" "strconv" "time" ) // // RegisterController 合同登记 type PrePaymentController struct{} // List // @Title 到款预登记列表 // @Description 到款预登记列表 // @Param Keyword query string false "关键词" // @Param StartDate query string false "约定开始时间" // @Param EndDate query string false "约定结束时间" // @Param SortType query string true "如何排序,是正序还是倒序,枚举值:`asc 正序`,`desc 倒叙`" // @Success 200 {object} fms.ContractRegisterItem // @router /contract/pre_pay/list [get] func (rg *PrePaymentController) List(c *gin.Context) { var req fms.PrePayListReq 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 seller_name 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 (create_time BETWEEN ? AND ?)` pars = append(pars, st, ed) } 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[req.SortType]}) total, list, e := fms.GetPrePayItemPageList(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) } page.SetTotal(total) baseData := new(base.BaseData) baseData.SetPage(page) baseData.SetList(list) resp.OkData("获取成功", baseData, c) } // Add // @Title 新增到款预登记 // @Description 新增到款预登记 // @Param request body fms.PrepayAddReq true "type json string" // @Success 200 string "操作成功" // @router /contract/pre_pay/add [post] func (rg *PrePaymentController) Add(c *gin.Context) { req := new(fms.PrepayAddReq) 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 } // 货币及汇率 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 } ob := new(fms.ContractPrePayment) ob.CompanyName = req.CompanyName ob.SellerId = req.SellerId ob.SellerName = req.SellerName ob.CurrencyUnit = req.CurrencyUnit ob.StartDate = startDate ob.EndDate = endDate ob.AdminId = int(adminInfo.AdminId) ob.AdminName = adminInfo.AdminName ob.Amount = req.Amount * rate ob.OriginAmount = req.Amount ob.CurrencyUnit = req.CurrencyUnit ob.Remark = req.Remark ob.Set() // 新增合同及套餐 if e = ob.Create(); e != nil { resp.FailMsg("操作失败", "新增合同及套餐失败, Err: "+e.Error(), c) return } resp.Ok("操作成功", c) } // Edit // @Title 编辑到款预登记 // @Description 编辑到款预登记 // @Param request body fms.ContractRegisterEditReq true "type json string" // @Success 200 string "操作成功" // @router /contract/pre_pay/edit [post] func (rg *PrePaymentController) 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 } // 是否存在相同合同编号的登记 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 } originHasPayment := item.HasPayment updateCols := []string{ "ContractCode", "RelateContractCode", "CrmContractId", "ContractSource", "CompanyName", "ActualCompanyName", "SellerId", "SellerName", "ContractType", "ContractAmount", "StartDate", "EndDate", "SignDate", "AgreedPayTime", "ContractStatus", "RegisterStatus", "Remark", "ServiceRemark", "HasPayment", "NewCompany", "ModifyTime", } nowTime := time.Now().Local() item.ContractCode = req.ContractCode item.RelateContractCode = req.RelateContractCode item.CrmContractId = req.CrmContractId item.ContractSource = req.ContractSource item.CompanyName = req.CompanyName item.ActualCompanyName = req.ActualCompanyName item.SellerId = req.SellerId item.SellerName = req.SellerName 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.NewCompany = req.NewCompany item.ModifyTime = nowTime // 存在代付的直接完成登记, 且不允许进行开票/到款登记 if req.HasPayment == 1 { 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 originHasPayment == 0 && req.HasPayment == 1 { // 若从无代付修改为有代付, 则删除无代付期间新增的所有开票到款登记 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) } } // 套餐信息 serviceList, e := fmsService.HandleContractServiceAndDetail(req.ProductId, req.Services, true) if e != nil { resp.FailMsg("操作失败", "获取合同套餐详情失败, Err: "+e.Error(), c) return } // 更新合同登记、套餐、开票到款 if e = fms.UpdateContractRegister(item, updateCols, serviceList, invoiceList, invoiceUpdateCols, invoiceHandleType); e != nil { resp.FailMsg("操作失败", "更新合同及套餐失败, Err: "+e.Error(), c) return } // 校验金额-是否修改状态 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/pre_pay/del [post] func (rg *PrePaymentController) 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) }