package service import ( "database/sql" "electricity_bill_calc/cache" "electricity_bill_calc/exceptions" "electricity_bill_calc/global" "electricity_bill_calc/model" "fmt" "github.com/shopspring/decimal" ) type _CalculateService struct{} var CalculateService _CalculateService func (_CalculateService) ComprehensivelyCalculateReport(reportId string) (err error) { ctx, cancel := global.TimeoutContext(12) defer cancel() // 资料准备 var report = new(model.Report) err = global.DB.NewSelect().Model(report). Relation("Summary"). Relation("WillDilutedFees"). Relation("EndUsers"). Where("r.id = ?", reportId). Scan(ctx) if err != nil || report == nil { return exceptions.NewNotFoundErrorFromError("未找到指定的公示报表", err) } // 综合计算 report.Summary.CalculatePrices() // 计算维护费总计 maintenanceFeeTotal := decimal.NewFromInt(0) for _, m := range report.WillDilutedFees { maintenanceFeeTotal = maintenanceFeeTotal.Add(m.Fee) } // 计算终端用户信息与概览中的合计 report.Summary.Customers = model.NewConsumptions() report.Summary.Publics = model.NewConsumptions() report.Summary.Diluteds = model.NewConsumptions() for _, eu := range report.EndUsers { eu.OverallFee = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) eu.CriticalFee = decimal.NewNullDecimal( eu.Critical.Decimal.Mul(report.Summary.CriticalPrice.Decimal).RoundBank(2), ) eu.PeakFee = decimal.NewNullDecimal( eu.Peak.Decimal.Mul(report.Summary.PeakPrice.Decimal).RoundBank(2), ) eu.FlatFee = decimal.NewNullDecimal( eu.Flat.Decimal.Mul(report.Summary.FlatPrice.Decimal).RoundBank(2), ) eu.ValleyFee = decimal.NewNullDecimal( eu.Valley.Decimal.Mul(report.Summary.ValleyPrice.Decimal).RoundBank(2), ) if eu.IsPublicMeter { report.Summary.Publics.Consumption.Decimal = report.Summary.Publics.Consumption.Decimal.Add(eu.Overall.Decimal) report.Summary.Publics.Critical.Decimal = report.Summary.Publics.Critical.Decimal.Add(eu.Critical.Decimal) report.Summary.Publics.Peak.Decimal = report.Summary.Publics.Peak.Decimal.Add(eu.Peak.Decimal) report.Summary.Publics.Flat.Decimal = report.Summary.Publics.Flat.Decimal.Add(eu.Flat.Decimal) report.Summary.Publics.Valley.Decimal = report.Summary.Publics.Valley.Decimal.Add(eu.Valley.Decimal) if eu.WillDilute { report.Summary.Diluteds.Consumption.Decimal = report.Summary.Diluteds.Consumption.Decimal.Add(eu.Overall.Decimal) report.Summary.Diluteds.Critical.Decimal = report.Summary.Diluteds.Critical.Decimal.Add(eu.Critical.Decimal) report.Summary.Diluteds.Peak.Decimal = report.Summary.Diluteds.Peak.Decimal.Add(eu.Peak.Decimal) report.Summary.Diluteds.Flat.Decimal = report.Summary.Diluteds.Flat.Decimal.Add(eu.Flat.Decimal) report.Summary.Diluteds.Valley.Decimal = report.Summary.Diluteds.Valley.Decimal.Add(eu.Valley.Decimal) } } else { report.Summary.Customers.Consumption.Decimal = report.Summary.Customers.Consumption.Decimal.Add(eu.Overall.Decimal) report.Summary.Customers.Critical.Decimal = report.Summary.Customers.Critical.Decimal.Add(eu.Critical.Decimal) report.Summary.Customers.Peak.Decimal = report.Summary.Customers.Peak.Decimal.Add(eu.Peak.Decimal) report.Summary.Customers.Flat.Decimal = report.Summary.Customers.Flat.Decimal.Add(eu.Flat.Decimal) report.Summary.Customers.Valley.Decimal = report.Summary.Customers.Valley.Decimal.Add(eu.Valley.Decimal) } } // 计算户表总电费和公共总电费以及相应的摊薄 if report.SubmeterType == model.CUSTOMER_METER_NON_PV { // 计算终端用户部分 report.Summary.Customers.ConsumptionFee = decimal.NewNullDecimal( report.Summary.Customers.Consumption.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Customers.CriticalFee = decimal.NewNullDecimal( report.Summary.Customers.Critical.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Customers.PeakFee = decimal.NewNullDecimal( report.Summary.Customers.Peak.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Customers.FlatFee = decimal.NewNullDecimal( report.Summary.Customers.Flat.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Customers.ValleyFee = decimal.NewNullDecimal( report.Summary.Customers.Valley.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) // 计算公共区域部分 report.Summary.Publics.ConsumptionFee = decimal.NewNullDecimal( report.Summary.Publics.Consumption.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Publics.CriticalFee = decimal.NewNullDecimal( report.Summary.Publics.Critical.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Publics.PeakFee = decimal.NewNullDecimal( report.Summary.Publics.Peak.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Publics.FlatFee = decimal.NewNullDecimal( report.Summary.Publics.Flat.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Publics.ValleyFee = decimal.NewNullDecimal( report.Summary.Publics.Valley.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) // 计算摊薄总计部分 report.Summary.Diluteds.ConsumptionFee = decimal.NewNullDecimal( report.Summary.Diluteds.Consumption.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Diluteds.CriticalFee = decimal.NewNullDecimal( report.Summary.Diluteds.Critical.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Diluteds.PeakFee = decimal.NewNullDecimal( report.Summary.Diluteds.Peak.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Diluteds.FlatFee = decimal.NewNullDecimal( report.Summary.Diluteds.Flat.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Diluteds.ValleyFee = decimal.NewNullDecimal( report.Summary.Diluteds.Valley.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) } if report.SubmeterType == model.CUSTOMER_METER_PV { // 计算终端用户部分 report.Summary.Customers.ConsumptionFee = decimal.NewNullDecimal( report.Summary.Customers.Consumption.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Customers.CriticalFee = decimal.NewNullDecimal( report.Summary.Customers.Critical.Decimal.Mul(report.Summary.CriticalPrice.Decimal).RoundBank(2), ) report.Summary.Customers.PeakFee = decimal.NewNullDecimal( report.Summary.Customers.Peak.Decimal.Mul(report.Summary.PeakPrice.Decimal).RoundBank(2), ) report.Summary.Customers.FlatFee = decimal.NewNullDecimal( report.Summary.Customers.Flat.Decimal.Mul(report.Summary.FlatPrice.Decimal).RoundBank(2), ) report.Summary.Customers.ValleyFee = decimal.NewNullDecimal( report.Summary.Customers.Valley.Decimal.Mul(report.Summary.ValleyPrice.Decimal).RoundBank(2), ) // 计算公共区域部分 report.Summary.Publics.ConsumptionFee = decimal.NewNullDecimal( report.Summary.Publics.Consumption.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Publics.CriticalFee = decimal.NewNullDecimal( report.Summary.Publics.Critical.Decimal.Mul(report.Summary.CriticalPrice.Decimal).RoundBank(2), ) report.Summary.Publics.PeakFee = decimal.NewNullDecimal( report.Summary.Publics.Peak.Decimal.Mul(report.Summary.PeakPrice.Decimal).RoundBank(2), ) report.Summary.Publics.FlatFee = decimal.NewNullDecimal( report.Summary.Publics.Flat.Decimal.Mul(report.Summary.FlatPrice.Decimal).RoundBank(2), ) report.Summary.Publics.ValleyFee = decimal.NewNullDecimal( report.Summary.Publics.Valley.Decimal.Mul(report.Summary.ValleyPrice.Decimal).RoundBank(2), ) // 计算摊薄部分 report.Summary.Diluteds.ConsumptionFee = decimal.NewNullDecimal( report.Summary.Diluteds.Consumption.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2), ) report.Summary.Diluteds.CriticalFee = decimal.NewNullDecimal( report.Summary.Diluteds.Critical.Decimal.Mul(report.Summary.CriticalPrice.Decimal).RoundBank(2), ) report.Summary.Diluteds.PeakFee = decimal.NewNullDecimal( report.Summary.Diluteds.Peak.Decimal.Mul(report.Summary.PeakPrice.Decimal).RoundBank(2), ) report.Summary.Diluteds.FlatFee = decimal.NewNullDecimal( report.Summary.Diluteds.Flat.Decimal.Mul(report.Summary.FlatPrice.Decimal).RoundBank(2), ) report.Summary.Diluteds.ValleyFee = decimal.NewNullDecimal( report.Summary.Diluteds.Valley.Decimal.Mul(report.Summary.ValleyPrice.Decimal).RoundBank(2), ) } if report.Summary.Overall.Abs().GreaterThan(decimal.Zero) { report.Summary.Customers.Proportion = decimal.NewNullDecimal( report.Summary.Customers.Consumption.Decimal.Div(report.Summary.Overall).RoundBank(15), ) report.Summary.Publics.Proportion = decimal.NewNullDecimal( report.Summary.Publics.Consumption.Decimal.Div(report.Summary.Overall).RoundBank(15), ) report.Summary.Diluteds.Proportion = decimal.NewNullDecimal( report.Summary.Diluteds.Consumption.Decimal.Div(report.Summary.Overall).RoundBank(15), ) } // 计算线损 report.Summary.Loss = decimal.NewNullDecimal( report.Summary.Overall.Sub(report.Summary.Publics.Consumption.Decimal).Sub(report.Summary.Customers.Consumption.Decimal), ) report.Summary.LossFee = decimal.NewNullDecimal( report.Summary.Loss.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(8), ) if report.Summary.Overall.Abs().GreaterThan(decimal.Zero) { report.Summary.LossProportion = decimal.NewNullDecimal( report.Summary.Loss.Decimal.Div(report.Summary.Overall).RoundBank(15), ) } if report.Summary.Customers.Consumption.Decimal.Abs().GreaterThan(decimal.Zero) { report.Summary.LossDilutedPrice = decimal.NewNullDecimal( report.Summary.LossFee.Decimal.Div(report.Summary.Customers.Consumption.Decimal).RoundBank(8), ) } // 计算基本电费和调整电费等的摊薄 if report.Summary.Customers.Consumption.Decimal.Abs().GreaterThan(decimal.Zero) { report.Summary.BasicDilutedPrice = decimal.NewNullDecimal( report.Summary.BasicFee.Div(report.Summary.Customers.Consumption.Decimal).RoundBank(8), ) report.Summary.AdjustDilutedPrice = decimal.NewNullDecimal( report.Summary.AdjustFee.Div(report.Summary.Customers.Consumption.Decimal).RoundBank(8), ) report.Summary.MaintenanceDilutedPrice = decimal.NewNullDecimal( maintenanceFeeTotal.Div(report.Summary.Customers.Consumption.Decimal).RoundBank(8), ) // ! 这里需要注意的是,在原始设计中PublicConsumptionDilutedPrice就是表示公共摊薄价格, // ! 而不是所有公共设施合计数据,所以要使用Diluteds部分数据。 report.Summary.PublicConsumptionDilutedPrice = decimal.NewNullDecimal( report.Summary.Diluteds.ConsumptionFee.Decimal.Div(report.Summary.Customers.Consumption.Decimal).RoundBank(8), ) } // 计算摊薄总计 report.Summary.MaintenanceOverall = decimal.NewNullDecimal(maintenanceFeeTotal) report.Summary.FinalDilutedOverall = decimal.NewNullDecimal( report.Summary.BasicFee. Add(report.Summary.AdjustFee). Add(report.Summary.Diluteds.ConsumptionFee.Decimal). Add(maintenanceFeeTotal). Add(report.Summary.LossFee.Decimal), ) // 计算终端用户的全部摊薄内容 for _, eu := range report.EndUsers { if eu.IsPublicMeter && eu.WillDilute { // 计算需要摊薄的公共表计的摊薄内容 if report.Summary.Diluteds.Consumption.Decimal.Abs().GreaterThan(decimal.Zero) { eu.OverallProportion = eu.Overall.Decimal.Div(report.Summary.Diluteds.Consumption.Decimal).RoundBank(15) } else { eu.OverallProportion = decimal.Zero } } else { // 计算户表表计的摊薄内容 if report.Summary.Customers.Consumption.Decimal.Abs().GreaterThan(decimal.Zero) { eu.OverallProportion = eu.Overall.Decimal.Div(report.Summary.Customers.Consumption.Decimal).RoundBank(15) } else { eu.OverallProportion = decimal.Zero } eu.BasicFeeDiluted = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(report.Summary.BasicDilutedPrice.Decimal).RoundBank(2), ) eu.AdjustFeeDiluted = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(report.Summary.AdjustDilutedPrice.Decimal).RoundBank(2), ) eu.LossDiluted = decimal.NewNullDecimal( report.Summary.Loss.Decimal.Mul(eu.OverallProportion).RoundBank(8), ) eu.LossFeeDiluted = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(report.Summary.LossDilutedPrice.Decimal).RoundBank(8), ) eu.MaintenanceFeeDiluted = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(report.Summary.MaintenanceDilutedPrice.Decimal).RoundBank(8), ) eu.PublicConsumptionDiluted = decimal.NewNullDecimal( eu.Overall.Decimal.Mul(report.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, err := global.DB.BeginTx(ctx, &sql.TxOptions{}) if err != nil { return } _, err = tx.NewUpdate().Model(report.Summary).WherePK().Exec(ctx) if err != nil { tx.Rollback() return } for _, eu := range report.EndUsers { _, err = tx.NewUpdate().Model(eu).WherePK().Exec(ctx) if err != nil { tx.Rollback() return } } err = tx.Commit() if err != nil { tx.Rollback() return } cache.AbolishRelation(fmt.Sprintf("publicity:%s", reportId)) return }