package service import ( "electricity_bill_calc/cache" "electricity_bill_calc/exceptions" "electricity_bill_calc/global" "electricity_bill_calc/model" "fmt" "github.com/shopspring/decimal" "xorm.io/builder" "xorm.io/xorm/schemas" ) type _CalculateService struct{} var CalculateService _CalculateService func (_CalculateService) ComprehensivelyCalculateReport(reportId string) (err error) { // 资料准备 var reportIndex = new(model.Report) has, err := global.DBConn.ID(reportId).NoAutoCondition().Get(reportIndex) if err != nil || !has { return exceptions.NewNotFoundErrorFromError("未找到指定的公示报表", err) } var summary = new(model.ReportSummary) has, err = global.DBConn.ID(reportId).NoAutoCondition().Get(summary) if err != nil || !has { return exceptions.NewNotFoundErrorFromError("未找到指定的公示报表概览", err) } var maintenanceFeeRecords = make([]model.WillDilutedFee, 0) err = global.DBConn.Where(builder.Eq{"report_id": reportId}).Find(&maintenanceFeeRecords) if err != nil { return exceptions.NewNotFoundErrorFromError("未能获取到公示报表对应的待摊薄费用信息", err) } var endUserDetails = make([]*model.EndUserDetail, 0) err = global.DBConn.Where(builder.Eq{"report_id": reportId}).Find(&endUserDetails) if err != nil { return exceptions.NewNotFoundErrorFromError("未获取到公示报表对应的终端用户抄表信息", err) } // 综合计算 summary.CalculatePrices() // 计算维护费总计 maintenanceFeeTotal := decimal.NewFromInt(0) for _, m := range maintenanceFeeRecords { maintenanceFeeTotal = maintenanceFeeTotal.Add(m.Fee) } // 计算终端用户信息与概览中的合计 summary.PublicConsumption = decimal.NewNullDecimal(decimal.Zero) summary.PublicConsumptionCritical = decimal.NewNullDecimal(decimal.Zero) summary.PublicConsumptionPeak = decimal.NewNullDecimal(decimal.Zero) summary.PublicConsumptionFlat = decimal.NewNullDecimal(decimal.Zero) summary.PublicConsumptionValley = decimal.NewNullDecimal(decimal.Zero) summary.CustomerConsumption = decimal.NewNullDecimal(decimal.Zero) summary.CustomerConsumptionCritical = decimal.NewNullDecimal(decimal.Zero) summary.CustomerConsumptionPeak = decimal.NewNullDecimal(decimal.Zero) summary.CustomerConsumptionFlat = decimal.NewNullDecimal(decimal.Zero) summary.CustomerConsumptionValley = decimal.NewNullDecimal(decimal.Zero) for _, eu := range endUserDetails { eu.OverallFee = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2), ) eu.CriticalFee = decimal.NewNullDecimal( eu.Critical.Decimal.Mul(summary.CriticalPrice.Decimal).RoundBank(2), ) eu.PeakFee = decimal.NewNullDecimal( eu.Peak.Decimal.Mul(summary.PeakPrice.Decimal).RoundBank(2), ) eu.FlatFee = decimal.NewNullDecimal( eu.Flat.Decimal.Mul(summary.FlatPrice.Decimal).RoundBank(2), ) eu.ValleyFee = decimal.NewNullDecimal( eu.Valley.Decimal.Mul(summary.ValleyPrice.Decimal).RoundBank(2), ) if eu.IsPublicMeter && eu.WillDilute { summary.PublicConsumption.Decimal = summary.PublicConsumption.Decimal.Add(eu.Overall.Decimal) summary.PublicConsumptionCritical.Decimal = summary.PublicConsumptionCritical.Decimal.Add(eu.Critical.Decimal) summary.PublicConsumptionPeak.Decimal = summary.PublicConsumptionPeak.Decimal.Add(eu.Peak.Decimal) summary.PublicConsumptionFlat.Decimal = summary.PublicConsumptionFlat.Decimal.Add(eu.Flat.Decimal) summary.PublicConsumptionValley.Decimal = summary.PublicConsumptionValley.Decimal.Add(eu.Valley.Decimal) } else { summary.CustomerConsumption.Decimal = summary.CustomerConsumption.Decimal.Add(eu.Overall.Decimal) summary.CustomerConsumptionCritical.Decimal = summary.CustomerConsumptionCritical.Decimal.Add(eu.Critical.Decimal) summary.CustomerConsumptionPeak.Decimal = summary.CustomerConsumptionPeak.Decimal.Add(eu.Peak.Decimal) summary.CustomerConsumptionFlat.Decimal = summary.CustomerConsumptionFlat.Decimal.Add(eu.Flat.Decimal) summary.CustomerConsumptionValley.Decimal = summary.CustomerConsumptionValley.Decimal.Add(eu.Valley.Decimal) } } // 计算户表总电费和公共总电费以及相应的摊薄 summary.CustomerConsumptionFee = decimal.NewNullDecimal( summary.CustomerConsumption.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2), ) summary.CustomerConsumptionCriticalFee = decimal.NewNullDecimal( summary.CustomerConsumptionCritical.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2), ) summary.CustomerConsumptionPeakFee = decimal.NewNullDecimal( summary.CustomerConsumptionPeak.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2), ) summary.CustomerConsumptionFlatFee = decimal.NewNullDecimal( summary.CustomerConsumptionFlat.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2), ) summary.CustomerConsumptionValleyFee = decimal.NewNullDecimal( summary.CustomerConsumptionValley.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2), ) summary.PublicConsumptionFee = decimal.NewNullDecimal( summary.PublicConsumption.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2), ) summary.PublicConsumptionCriticalFee = decimal.NewNullDecimal( summary.PublicConsumptionCritical.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2), ) summary.PublicConsumptionPeakFee = decimal.NewNullDecimal( summary.PublicConsumptionPeak.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2), ) summary.PublicConsumptionFlatFee = decimal.NewNullDecimal( summary.PublicConsumptionFlat.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2), ) summary.PublicConsumptionValleyFee = decimal.NewNullDecimal( summary.PublicConsumptionValley.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2), ) if summary.Overall.Abs().GreaterThan(decimal.Zero) { summary.PublicConsumptionProportion = decimal.NewNullDecimal( summary.PublicConsumption.Decimal.Div(summary.Overall).RoundBank(15), ) } // 计算线损 summary.Loss = decimal.NewNullDecimal( summary.Overall.Sub(summary.PublicConsumption.Decimal).Sub(summary.CustomerConsumption.Decimal), ) summary.LossFee = decimal.NewNullDecimal( summary.Loss.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(8), ) if summary.Overall.Abs().GreaterThan(decimal.Zero) { summary.LossProportion = decimal.NewNullDecimal( summary.Loss.Decimal.Div(summary.Overall).RoundBank(15), ) } if summary.CustomerConsumption.Decimal.Abs().GreaterThan(decimal.Zero) { summary.LossDilutedPrice = decimal.NewNullDecimal( summary.LossFee.Decimal.Div(summary.CustomerConsumption.Decimal).RoundBank(8), ) } // 计算基本电费和调整电费等的摊薄 if summary.CustomerConsumption.Decimal.Abs().GreaterThan(decimal.Zero) { summary.BasicDilutedPrice = decimal.NewNullDecimal( summary.BasicFee.Div(summary.CustomerConsumption.Decimal).RoundBank(8), ) summary.AdjustDilutedPrice = decimal.NewNullDecimal( summary.AdjustFee.Div(summary.CustomerConsumption.Decimal).RoundBank(8), ) summary.MaintenanceDilutedPrice = decimal.NewNullDecimal( maintenanceFeeTotal.Div(summary.CustomerConsumption.Decimal).RoundBank(8), ) summary.PublicConsumptionDilutedPrice = decimal.NewNullDecimal( summary.PublicConsumptionFee.Decimal.Div(summary.CustomerConsumption.Decimal).RoundBank(8), ) } // 计算摊薄总计 summary.MaintenanceOverall = decimal.NewNullDecimal(maintenanceFeeTotal) summary.FinalDilutedOverall = decimal.NewNullDecimal( summary.BasicFee. Add(summary.AdjustFee). Add(summary.PublicConsumptionFee.Decimal). Add(maintenanceFeeTotal). Add(summary.LossFee.Decimal), ) // 计算终端用户的全部摊薄内容 for _, eu := range endUserDetails { if eu.IsPublicMeter && eu.WillDilute { // 计算需要摊薄的公共表计的摊薄内容 if summary.PublicConsumption.Decimal.Abs().GreaterThan(decimal.Zero) { eu.OverallProportion = eu.Overall.Decimal.Div(summary.PublicConsumption.Decimal).RoundBank(15) } else { eu.OverallProportion = decimal.Zero } } else { // 计算户表表计的摊薄内容 if summary.CustomerConsumption.Decimal.Abs().GreaterThan(decimal.Zero) { eu.OverallProportion = eu.Overall.Decimal.Div(summary.CustomerConsumption.Decimal).RoundBank(15) } else { eu.OverallProportion = decimal.Zero } eu.BasicFeeDiluted = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(summary.BasicDilutedPrice.Decimal).RoundBank(2), ) eu.AdjustFeeDiluted = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(summary.AdjustDilutedPrice.Decimal).RoundBank(2), ) eu.LossDiluted = decimal.NewNullDecimal( summary.Loss.Decimal.Mul(eu.OverallProportion).RoundBank(8), ) eu.LossFeeDiluted = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(summary.LossDilutedPrice.Decimal).RoundBank(8), ) eu.MaintenanceFeeDiluted = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(summary.MaintenanceDilutedPrice.Decimal).RoundBank(8), ) eu.PublicConsumptionDiluted = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(summary.PublicConsumptionDilutedPrice.Decimal).RoundBank(8), ) eu.FinalDiluted = decimal.NewNullDecimal( eu.BasicFeeDiluted.Decimal. Add(eu.AdjustFeeDiluted.Decimal). Add(eu.LossFeeDiluted.Decimal). Add(eu.MaintenanceFeeDiluted.Decimal). Add(eu.PublicConsumptionDiluted.Decimal). RoundBank(2), ) eu.FinalCharge = decimal.NewNullDecimal( eu.OverallFee.Decimal.Add(eu.FinalDiluted.Decimal).RoundBank(2), ) } } // 向数据库保存报表概况以及终端用户摊薄结果 tx := global.DBConn.NewSession() if err = tx.Begin(); err != nil { return } defer tx.Close() _, err = tx.ID(reportId).Update(summary) if err != nil { tx.Rollback() return } for _, eu := range endUserDetails { _, err = tx.ID(schemas.NewPK(eu.ReportId, eu.ParkId, eu.MeterId)).Update(eu) if err != nil { tx.Rollback() return } } err = tx.Commit() if err != nil { tx.Rollback() return } cache.AbolishRelation(fmt.Sprintf("publicity_%s", reportId)) return }