package fms import ( "fmt" "github.com/shopspring/decimal" "hongze/fms_api/models/crm" "hongze/fms_api/models/fms" "hongze/fms_api/services/alarm_msg" "hongze/fms_api/utils" "strconv" "time" ) // CalculateContractPaymentType 计算到款登记付款方式 // 计算公式: 到款金额 / ( 合同金额 / round( (合同结束日期 - 合同开始日期) / 365) ) func CalculateContractPaymentType(paymentAmount, contractAmount, dayDiff float64) (payEnum int) { payEnum = fms.ContractPaymentPayTypeAbnormal // 默认异常 if paymentAmount <= 0 || contractAmount <= 0 || dayDiff <= 0 { return } // 年份四舍五入 days := decimal.NewFromFloat(dayDiff) yearDays := decimal.NewFromFloat(365) yearRound := days.DivRound(yearDays, 2) if yearRound.IsZero() { return } years := yearRound.Add(decimal.NewFromFloat(0.5)).Floor() if years.IsZero() { return } // 分母 contractDec := decimal.NewFromFloat(contractAmount) contractDeno := contractDec.DivRound(years, 2) if contractDeno.IsZero() { return } paymentDec := decimal.NewFromFloat(paymentAmount) // 结果 resultDec := paymentDec.DivRound(contractDeno, 2) // 标准比例 yearPay := decimal.NewFromFloat(1) halfYearPay := decimal.NewFromFloat(0.5) quarterPay := decimal.NewFromFloat(0.25) zeroPay := decimal.NewFromFloat(0) payEnum = fms.ContractPaymentPayTypeOther // 异常 if yearPay.LessThan(resultDec) || resultDec.LessThanOrEqual(zeroPay) { payEnum = fms.ContractPaymentPayTypeAbnormal return } // 年付 if resultDec.Equal(yearPay) { payEnum = fms.ContractPaymentPayTypeYear return } // 半年付 if resultDec.Equal(halfYearPay) { payEnum = fms.ContractPaymentPayTypeHalfYear return } // 季付 if resultDec.Equal(quarterPay) { payEnum = fms.ContractPaymentPayTypeQuarter return } return } // MergeInvoiceList2InvoicePaymentCensusInfo 合同登记-合并开票到款列表 func MergeInvoiceList2InvoicePaymentCensusInfo(invoiceList []*fms.ContractInvoice, paymentList []*fms.ContractInvoice, serviceList []*fms.ContractService, serviceAmountList []*fms.ContractPaymentServiceAmount) (mergeList []*fms.InvoicePaymentCensusInfo) { invoiceLen := len(invoiceList) paymentLen := len(paymentList) if invoiceLen == 0 && paymentLen == 0 { return } // 到款套餐分配信息 amountMap := make(map[string]*fms.ContractPaymentServiceAmount) for i := range serviceAmountList { k := fmt.Sprintf("%d-%d", serviceAmountList[i].ContractPaymentId, serviceAmountList[i].ServiceTemplateId) amountMap[k] = serviceAmountList[i] } serviceAmountMap := make(map[int][]*fms.ContractPaymentServiceAmountItem) for i := range paymentList { l := make([]*fms.ContractPaymentServiceAmountItem, 0) for ii := range serviceList { v := new(fms.ContractPaymentServiceAmountItem) v.ServiceTemplateId = serviceList[ii].ServiceTemplateId v.ServiceTemplateName = serviceList[ii].Title k := fmt.Sprintf("%d-%d", paymentList[i].ContractInvoiceId, serviceList[ii].ServiceTemplateId) a := amountMap[k] if a != nil { v.ContractPaymentServiceAmountId = a.ContractPaymentServiceAmountId v.ContractPaymentId = a.ContractPaymentId v.Amount = a.Amount } l = append(l, v) } serviceAmountMap[paymentList[i].ContractInvoiceId] = l } // 开票和到款列表, 条数多的为最后的合并条数 mergeList = make([]*fms.InvoicePaymentCensusInfo, 0) if invoiceLen >= paymentLen { for i := range invoiceList { v := new(fms.InvoicePaymentCensusInfo) v.InvoiceId = invoiceList[i].ContractInvoiceId v.InvoiceDate = invoiceList[i].InvoiceDate.Format(utils.FormatDate) v.InvoiceAmount = invoiceList[i].OriginAmount v.SellerId = invoiceList[i].SellerId v.SellerName = invoiceList[i].SellerName v.SellerGroupId = invoiceList[i].SellerGroupId v.SellerGroupName = invoiceList[i].SellerGroupName // 直接取对应键的到款列表 if i+1 <= paymentLen { payItem := paymentList[i] if payItem != nil { v.PaymentId = payItem.ContractInvoiceId v.PaymentDate = payItem.InvoiceDate.Format(utils.FormatDate) v.PaymentAmount = payItem.OriginAmount v.PayType = payItem.PayType v.ServiceAmountList = serviceAmountMap[payItem.ContractInvoiceId] } } mergeList = append(mergeList, v) } return } // 到款多于开票 if paymentLen > invoiceLen { for i := range paymentList { v := new(fms.InvoicePaymentCensusInfo) v.PaymentId = paymentList[i].ContractInvoiceId v.PaymentDate = paymentList[i].InvoiceDate.Format(utils.FormatDate) v.PaymentAmount = paymentList[i].OriginAmount v.PayType = paymentList[i].PayType v.ServiceAmountList = serviceAmountMap[paymentList[i].ContractInvoiceId] // 直接取对应键的开票 if i+1 <= invoiceLen { invoiceItem := invoiceList[i] if invoiceItem != nil { v.InvoiceId = invoiceItem.ContractInvoiceId v.InvoiceDate = invoiceItem.InvoiceDate.Format(utils.FormatDate) v.InvoiceAmount = invoiceItem.OriginAmount v.SellerId = invoiceItem.SellerId v.SellerName = invoiceItem.SellerName v.SellerGroupId = invoiceList[i].SellerGroupId v.SellerGroupName = invoiceList[i].SellerGroupName } } mergeList = append(mergeList, v) } return } return } // SummaryInvoicePaymentByContractRegisterId 汇总合同登记的开票到款, 即一一进行对应存入汇总表 func SummaryInvoicePaymentByContractRegisterId(registerId int) { var err error defer func() { if err != nil { alarm_msg.SendAlarmMsg(fmt.Sprintf("汇总开票到款失败, ErrMsg: \n%s", err.Error()), 3) } }() // 获取开票到款信息 cond := `contract_register_id = ?` pars := make([]interface{}, 0) pars = append(pars, registerId) list, e := fms.GetContractInvoiceItemList(cond, pars) if e != nil { err = fmt.Errorf("获取开票到款列表失败, Err: %s", e.Error()) return } ficcInvoiceIds := make([]int, 0) ficcPaymentIds := make([]int, 0) raiInvoiceIds := make([]int, 0) raiPaymentIds := make([]int, 0) noProductPaymentIds := make([]int, 0) for i := range list { if list[i].InvoiceType == fms.ContractInvoiceTypeMake { if list[i].ServiceProductId == crm.CompanyProductFicc { ficcInvoiceIds = append(ficcInvoiceIds, list[i].ContractInvoiceId) } else if list[i].ServiceProductId == crm.CompanyProductRai { raiInvoiceIds = append(raiInvoiceIds, list[i].ContractInvoiceId) } continue } if list[i].InvoiceType == fms.ContractInvoiceTypePay { if list[i].ServiceProductId == crm.CompanyProductFicc { ficcPaymentIds = append(ficcPaymentIds, list[i].ContractInvoiceId) } else if list[i].ServiceProductId == crm.CompanyProductRai { raiPaymentIds = append(raiPaymentIds, list[i].ContractInvoiceId) } continue } if list[i].InvoiceType == fms.ContractInvoiceTypePreMake { if list[i].ServiceProductId == crm.CompanyProductFicc { ficcInvoiceIds = append(ficcInvoiceIds, list[i].ContractInvoiceId) } else if list[i].ServiceProductId == crm.CompanyProductRai { raiInvoiceIds = append(raiInvoiceIds, list[i].ContractInvoiceId) } continue } if list[i].InvoiceType == fms.ContractInvoiceTypePrePay { if list[i].ServiceProductId == crm.CompanyProductFicc { ficcPaymentIds = append(ficcPaymentIds, list[i].ContractInvoiceId) } else if list[i].ServiceProductId == crm.CompanyProductRai { raiPaymentIds = append(raiPaymentIds, list[i].ContractInvoiceId) } else { noProductPaymentIds = append(noProductPaymentIds, list[i].ContractInvoiceId) } continue } } ficcInvoiceLen := len(ficcInvoiceIds) raiInvoiceLen := len(raiInvoiceIds) ficcPaymentLen := len(ficcPaymentIds) raiPaymentLen := len(raiPaymentIds) noProductPaymentLen := len(noProductPaymentIds) // 汇总数据 nowTime := time.Now().Local() summaryList := make([]*fms.InvoicePaymentSummary, 0) // ficc if ficcInvoiceLen >= ficcPaymentLen { for i := range ficcInvoiceIds { v := new(fms.InvoicePaymentSummary) v.RegisterId = registerId v.InvoiceId = ficcInvoiceIds[i] v.ServiceProductId = crm.CompanyProductFicc v.CreateTime = nowTime v.ModifyTime = nowTime // 取对应key的到款ID if i+1 <= ficcPaymentLen { v.PaymentId = ficcPaymentIds[i] } summaryList = append(summaryList, v) } } if ficcPaymentLen > ficcInvoiceLen { for i := range ficcPaymentIds { v := new(fms.InvoicePaymentSummary) v.RegisterId = registerId v.PaymentId = ficcPaymentIds[i] v.ServiceProductId = crm.CompanyProductFicc v.CreateTime = nowTime v.ModifyTime = nowTime // 取对应key的开票ID if i+1 <= ficcInvoiceLen { v.InvoiceId = ficcInvoiceIds[i] } summaryList = append(summaryList, v) } } // rai if raiInvoiceLen >= raiPaymentLen { for i := range raiInvoiceIds { v := new(fms.InvoicePaymentSummary) v.RegisterId = registerId v.InvoiceId = raiInvoiceIds[i] v.ServiceProductId = crm.CompanyProductRai v.CreateTime = nowTime v.ModifyTime = nowTime // 取对应key的到款ID if i+1 <= raiPaymentLen { v.PaymentId = raiPaymentIds[i] } summaryList = append(summaryList, v) } } if raiPaymentLen > raiInvoiceLen { for i := range raiPaymentIds { v := new(fms.InvoicePaymentSummary) v.RegisterId = registerId v.PaymentId = raiPaymentIds[i] v.ServiceProductId = crm.CompanyProductRai v.CreateTime = nowTime v.ModifyTime = nowTime // 取对应key的开票ID if i+1 <= raiInvoiceLen { v.InvoiceId = raiInvoiceIds[i] } summaryList = append(summaryList, v) } } if noProductPaymentLen > 0 { for i := range noProductPaymentIds { v := new(fms.InvoicePaymentSummary) v.RegisterId = registerId v.PaymentId = noProductPaymentIds[i] v.CreateTime = nowTime v.ModifyTime = nowTime summaryList = append(summaryList, v) } } // 删除并新增汇总数据 summaryOB := new(fms.InvoicePaymentSummary) if e = summaryOB.DeleteAndCreate(registerId, summaryList); e != nil { err = fmt.Errorf("新增汇总数据失败, Err: %s", e.Error()) } return } // CalculatePaymentServiceAmount func CalculatePaymentServiceAmount(registerId int) (err error) { // todo 判断是否符合均分金额的条件,如果符合,需要生成金额分配记录表 // 查询所有的到款记录,如果没有到款记录则无需分配到款金额 cond := `contract_register_id = ? and invoice_type=2 and service_product_id=2` pars := make([]interface{}, 0) pars = append(pars, registerId) paymentList, err := fms.GetContractInvoiceItemList(cond, pars) if err != nil { err = fmt.Errorf("获取开票到款列表失败, Err: %s", err.Error()) return } if len(paymentList) == 0 { return } var contractPaymentIds []int for _, v := range paymentList { contractPaymentIds = append(contractPaymentIds, v.ContractInvoiceId) } // 获取服务套餐 servicesList, err := fms.GetContractServiceAndDetailList(registerId) if err != nil { err = fmt.Errorf("获取服务套餐失败, Err: " + err.Error()) return } industrySlice := []string{ "行业套餐", "医药", "消费", "科技", "智造", "策略", "主观", "客观", } unNeedAsign := false industryFlag := false servicesListMap := make(map[int]*fms.ContractServiceAndDetail) // 判断当前套餐是否符合分配规则 for _, v := range servicesList { if v.ProductId == crm.CompanyProductRai { industryFlag = true } servicesListMap[v.ServiceTemplateId] = v if v.ProductId == crm.CompanyProductRai && !utils.InArray(v.Title, industrySlice) { unNeedAsign = true } } if unNeedAsign || !industryFlag { //不符合自动分配规则,则直接删除之前的自动分配记录 err = fms.DeletePaymentServiceAmountByRegisterId(registerId) if err != nil { return } return } else { //遍历所有的到款记录,筛选出需要删除并新增的到款记录ID _, serviceFormatMap, e := GetContractServiceNameFormat([]int{registerId}) if e != nil { err = fmt.Errorf("获取合同套餐失败, Err: %s", e.Error()) return } servicesFormatList, ok := serviceFormatMap[registerId] if !ok { err = fmt.Errorf("查不到合同套餐") return } servicesFormatStr := "" length := 0 for _, v := range servicesFormatList { if servicesListMap[v.ServiceTemplateId].ProductId == crm.CompanyProductRai { length++ servicesFormatStr += fmt.Sprintf("%d_", v.ServiceTemplateId) } } if length == 0 { return } payAverageAmountMap := make(map[int]float64) for _, v := range paymentList { payAverageAmountMap[v.ContractInvoiceId] = v.Amount / float64(length) payAverageAmountMap[v.ContractInvoiceId], _ = strconv.ParseFloat(fmt.Sprintf("%.2f", payAverageAmountMap[v.ContractInvoiceId]), 64) } //查询原来的金额分配记录 serviceAmountCond := `contract_payment_id = ? and contract_payment_id in ?` serviceAmountPars := make([]interface{}, 0) serviceAmountPars = append(serviceAmountPars, registerId, contractPaymentIds) serviceAmountOB := new(fms.ContractPaymentServiceAmount) serviceAmountList, e := serviceAmountOB.List(serviceAmountCond, serviceAmountPars) if e != nil { err = fmt.Errorf("获取到款套餐分配列表失败, Err: %s", e.Error()) return } oldPaymentServiceMap := make(map[int]string) oldPaymentAmountMap := make(map[int]float64) for _, v := range serviceAmountList { oldPaymentServiceMap[v.ContractPaymentId] += fmt.Sprintf("%d_", v.ServiceTemplateId) oldPaymentAmountMap[v.ContractPaymentId] = v.Amount } var newPaymentIds []int for _, v := range paymentList { if _, ok1 := oldPaymentServiceMap[v.ContractInvoiceId]; !ok1 { newPaymentIds = append(newPaymentIds, v.ContractInvoiceId) continue } if oldPaymentServiceMap[v.ContractInvoiceId] != servicesFormatStr { newPaymentIds = append(newPaymentIds, v.ContractInvoiceId) continue } if oldPaymentAmountMap[v.ContractInvoiceId] != payAverageAmountMap[v.ContractInvoiceId] { newPaymentIds = append(newPaymentIds, v.ContractInvoiceId) continue } } // 删除旧的金额分配记录并生成新的自动分配记录 if len(newPaymentIds) == 0 { return } for _, v := range newPaymentIds { addList := make([]*fms.ContractPaymentServiceAmount, 0) for _, f := range servicesFormatList { if servicesListMap[f.ServiceTemplateId].ProductId == crm.CompanyProductRai { t := &fms.ContractPaymentServiceAmount{ ContractRegisterId: registerId, ContractPaymentId: v, ServiceTemplatePid: f.ServiceTemplatePid, ServiceTemplateId: f.ServiceTemplateId, Amount: payAverageAmountMap[v], InitType: 1, } t.Set() addList = append(addList, t) } } if e := fms.CreatePaymentServiceAmount(registerId, v, addList); e != nil { err = fmt.Errorf("新增到款套餐金额失败, Err: " + e.Error()) return } } } return } // SummaryInvoicePaymentByPreRegister 预登记时汇总 func SummaryInvoicePaymentByPreRegister(registerId int) { var err error defer func() { if err != nil { alarm_msg.SendAlarmMsg(fmt.Sprintf("汇总开票到款失败, ErrMsg: \n%s", err.Error()), 3) } }() // 获取开票到款信息 cond := `contract_register_id = ?` pars := make([]interface{}, 0) pars = append(pars, registerId) list, e := fms.GetContractPreRegisterItemList(cond, pars) if e != nil { err = fmt.Errorf("获取开票到款列表失败, Err: %s", e.Error()) return } ficcInvoiceIds := make([]int, 0) ficcPaymentIds := make([]int, 0) raiInvoiceIds := make([]int, 0) raiPaymentIds := make([]int, 0) for i := range list { if list[i].InvoiceType == fms.ContractInvoiceTypePreMake { if list[i].ServiceProductId == crm.CompanyProductFicc { ficcInvoiceIds = append(ficcInvoiceIds, list[i].PreRegisterId) } else if list[i].ServiceProductId == crm.CompanyProductRai { raiInvoiceIds = append(raiInvoiceIds, list[i].PreRegisterId) } continue } if list[i].InvoiceType == fms.ContractInvoiceTypePrePay { if list[i].ServiceProductId == crm.CompanyProductFicc { ficcPaymentIds = append(ficcPaymentIds, list[i].PreRegisterId) } else if list[i].ServiceProductId == crm.CompanyProductRai { raiPaymentIds = append(raiPaymentIds, list[i].PreRegisterId) } continue } } ficcInvoiceLen := len(ficcInvoiceIds) raiInvoiceLen := len(raiInvoiceIds) ficcPaymentLen := len(ficcPaymentIds) raiPaymentLen := len(raiPaymentIds) // 汇总数据 nowTime := time.Now().Local() summaryList := make([]*fms.InvoicePaymentSummary, 0) // ficc if ficcInvoiceLen >= ficcPaymentLen { for i := range ficcInvoiceIds { v := new(fms.InvoicePaymentSummary) v.RegisterId = registerId v.InvoiceId = ficcInvoiceIds[i] v.ServiceProductId = crm.CompanyProductFicc v.CreateTime = nowTime v.ModifyTime = nowTime // 取对应key的到款ID if i+1 <= ficcPaymentLen { v.PaymentId = ficcPaymentIds[i] } summaryList = append(summaryList, v) } } if ficcPaymentLen > ficcInvoiceLen { for i := range ficcPaymentIds { v := new(fms.InvoicePaymentSummary) v.RegisterId = registerId v.PaymentId = ficcPaymentIds[i] v.ServiceProductId = crm.CompanyProductFicc v.CreateTime = nowTime v.ModifyTime = nowTime // 取对应key的开票ID if i+1 <= ficcInvoiceLen { v.InvoiceId = ficcInvoiceIds[i] } summaryList = append(summaryList, v) } } // rai if raiInvoiceLen >= raiPaymentLen { for i := range raiInvoiceIds { v := new(fms.InvoicePaymentSummary) v.RegisterId = registerId v.InvoiceId = raiInvoiceIds[i] v.ServiceProductId = crm.CompanyProductRai v.CreateTime = nowTime v.ModifyTime = nowTime // 取对应key的到款ID if i+1 <= raiPaymentLen { v.PaymentId = raiPaymentIds[i] } summaryList = append(summaryList, v) } } if raiPaymentLen > raiInvoiceLen { for i := range raiPaymentIds { v := new(fms.InvoicePaymentSummary) v.RegisterId = registerId v.PaymentId = raiPaymentIds[i] v.ServiceProductId = crm.CompanyProductRai v.CreateTime = nowTime v.ModifyTime = nowTime // 取对应key的开票ID if i+1 <= raiInvoiceLen { v.InvoiceId = raiInvoiceIds[i] } summaryList = append(summaryList, v) } } // 删除并新增汇总数据 summaryOB := new(fms.InvoicePaymentSummary) if e = summaryOB.DeleteAndCreate(registerId, summaryList); e != nil { err = fmt.Errorf("新增汇总数据失败, Err: %s", e.Error()) } return }