275 lines
12 KiB
Go
275 lines
12 KiB
Go
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.PublicConsumption = decimal.NewNullDecimal(decimal.Zero)
|
|
report.Summary.PublicConsumptionCritical = decimal.NewNullDecimal(decimal.Zero)
|
|
report.Summary.PublicConsumptionPeak = decimal.NewNullDecimal(decimal.Zero)
|
|
report.Summary.PublicConsumptionFlat = decimal.NewNullDecimal(decimal.Zero)
|
|
report.Summary.PublicConsumptionValley = decimal.NewNullDecimal(decimal.Zero)
|
|
report.Summary.CustomerConsumption = decimal.NewNullDecimal(decimal.Zero)
|
|
report.Summary.CustomerConsumptionCritical = decimal.NewNullDecimal(decimal.Zero)
|
|
report.Summary.CustomerConsumptionPeak = decimal.NewNullDecimal(decimal.Zero)
|
|
report.Summary.CustomerConsumptionFlat = decimal.NewNullDecimal(decimal.Zero)
|
|
report.Summary.CustomerConsumptionValley = decimal.NewNullDecimal(decimal.Zero)
|
|
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 && eu.WillDilute {
|
|
report.Summary.PublicConsumption.Decimal = report.Summary.PublicConsumption.Decimal.Add(eu.Overall.Decimal)
|
|
report.Summary.PublicConsumptionCritical.Decimal = report.Summary.PublicConsumptionCritical.Decimal.Add(eu.Critical.Decimal)
|
|
report.Summary.PublicConsumptionPeak.Decimal = report.Summary.PublicConsumptionPeak.Decimal.Add(eu.Peak.Decimal)
|
|
report.Summary.PublicConsumptionFlat.Decimal = report.Summary.PublicConsumptionFlat.Decimal.Add(eu.Flat.Decimal)
|
|
report.Summary.PublicConsumptionValley.Decimal = report.Summary.PublicConsumptionValley.Decimal.Add(eu.Valley.Decimal)
|
|
} else {
|
|
report.Summary.CustomerConsumption.Decimal = report.Summary.CustomerConsumption.Decimal.Add(eu.Overall.Decimal)
|
|
report.Summary.CustomerConsumptionCritical.Decimal = report.Summary.CustomerConsumptionCritical.Decimal.Add(eu.Critical.Decimal)
|
|
report.Summary.CustomerConsumptionPeak.Decimal = report.Summary.CustomerConsumptionPeak.Decimal.Add(eu.Peak.Decimal)
|
|
report.Summary.CustomerConsumptionFlat.Decimal = report.Summary.CustomerConsumptionFlat.Decimal.Add(eu.Flat.Decimal)
|
|
report.Summary.CustomerConsumptionValley.Decimal = report.Summary.CustomerConsumptionValley.Decimal.Add(eu.Valley.Decimal)
|
|
}
|
|
}
|
|
|
|
// 计算户表总电费和公共总电费以及相应的摊薄
|
|
if report.SubmeterType == model.CUSTOMER_METER_NON_PV {
|
|
report.Summary.CustomerConsumptionFee = decimal.NewNullDecimal(
|
|
report.Summary.CustomerConsumption.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.CustomerConsumptionCriticalFee = decimal.NewNullDecimal(
|
|
report.Summary.CustomerConsumptionCritical.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.CustomerConsumptionPeakFee = decimal.NewNullDecimal(
|
|
report.Summary.CustomerConsumptionPeak.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.CustomerConsumptionFlatFee = decimal.NewNullDecimal(
|
|
report.Summary.CustomerConsumptionFlat.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.CustomerConsumptionValleyFee = decimal.NewNullDecimal(
|
|
report.Summary.CustomerConsumptionValley.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.PublicConsumptionFee = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumption.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.PublicConsumptionCriticalFee = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumptionCritical.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.PublicConsumptionPeakFee = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumptionPeak.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.PublicConsumptionFlatFee = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumptionFlat.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.PublicConsumptionValleyFee = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumptionValley.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
}
|
|
if report.SubmeterType == model.CUSTOMER_METER_PV {
|
|
report.Summary.CustomerConsumptionFee = decimal.NewNullDecimal(
|
|
report.Summary.CustomerConsumption.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.CustomerConsumptionCriticalFee = decimal.NewNullDecimal(
|
|
report.Summary.CustomerConsumptionCritical.Decimal.Mul(report.Summary.CriticalPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.CustomerConsumptionPeakFee = decimal.NewNullDecimal(
|
|
report.Summary.CustomerConsumptionPeak.Decimal.Mul(report.Summary.PeakPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.CustomerConsumptionFlatFee = decimal.NewNullDecimal(
|
|
report.Summary.CustomerConsumptionFlat.Decimal.Mul(report.Summary.FlatPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.CustomerConsumptionValleyFee = decimal.NewNullDecimal(
|
|
report.Summary.CustomerConsumptionValley.Decimal.Mul(report.Summary.ValleyPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.PublicConsumptionFee = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumption.Decimal.Mul(report.Summary.OverallPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.PublicConsumptionCriticalFee = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumptionCritical.Decimal.Mul(report.Summary.CriticalPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.PublicConsumptionPeakFee = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumptionPeak.Decimal.Mul(report.Summary.PeakPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.PublicConsumptionFlatFee = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumptionFlat.Decimal.Mul(report.Summary.FlatPrice.Decimal).RoundBank(2),
|
|
)
|
|
report.Summary.PublicConsumptionValleyFee = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumptionValley.Decimal.Mul(report.Summary.ValleyPrice.Decimal).RoundBank(2),
|
|
)
|
|
}
|
|
if report.Summary.Overall.Abs().GreaterThan(decimal.Zero) {
|
|
report.Summary.PublicConsumptionProportion = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumption.Decimal.Div(report.Summary.Overall).RoundBank(15),
|
|
)
|
|
}
|
|
|
|
// 计算线损
|
|
report.Summary.Loss = decimal.NewNullDecimal(
|
|
report.Summary.Overall.Sub(report.Summary.PublicConsumption.Decimal).Sub(report.Summary.CustomerConsumption.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.CustomerConsumption.Decimal.Abs().GreaterThan(decimal.Zero) {
|
|
report.Summary.LossDilutedPrice = decimal.NewNullDecimal(
|
|
report.Summary.LossFee.Decimal.Div(report.Summary.CustomerConsumption.Decimal).RoundBank(8),
|
|
)
|
|
}
|
|
|
|
// 计算基本电费和调整电费等的摊薄
|
|
if report.Summary.CustomerConsumption.Decimal.Abs().GreaterThan(decimal.Zero) {
|
|
report.Summary.BasicDilutedPrice = decimal.NewNullDecimal(
|
|
report.Summary.BasicFee.Div(report.Summary.CustomerConsumption.Decimal).RoundBank(8),
|
|
)
|
|
report.Summary.AdjustDilutedPrice = decimal.NewNullDecimal(
|
|
report.Summary.AdjustFee.Div(report.Summary.CustomerConsumption.Decimal).RoundBank(8),
|
|
)
|
|
report.Summary.MaintenanceDilutedPrice = decimal.NewNullDecimal(
|
|
maintenanceFeeTotal.Div(report.Summary.CustomerConsumption.Decimal).RoundBank(8),
|
|
)
|
|
report.Summary.PublicConsumptionDilutedPrice = decimal.NewNullDecimal(
|
|
report.Summary.PublicConsumptionFee.Decimal.Div(report.Summary.CustomerConsumption.Decimal).RoundBank(8),
|
|
)
|
|
}
|
|
|
|
// 计算摊薄总计
|
|
report.Summary.MaintenanceOverall = decimal.NewNullDecimal(maintenanceFeeTotal)
|
|
report.Summary.FinalDilutedOverall = decimal.NewNullDecimal(
|
|
report.Summary.BasicFee.
|
|
Add(report.Summary.AdjustFee).
|
|
Add(report.Summary.PublicConsumptionFee.Decimal).
|
|
Add(maintenanceFeeTotal).
|
|
Add(report.Summary.LossFee.Decimal),
|
|
)
|
|
|
|
// 计算终端用户的全部摊薄内容
|
|
for _, eu := range report.EndUsers {
|
|
if eu.IsPublicMeter && eu.WillDilute {
|
|
// 计算需要摊薄的公共表计的摊薄内容
|
|
if report.Summary.PublicConsumption.Decimal.Abs().GreaterThan(decimal.Zero) {
|
|
eu.OverallProportion = eu.Overall.Decimal.Div(report.Summary.PublicConsumption.Decimal).RoundBank(15)
|
|
} else {
|
|
eu.OverallProportion = decimal.Zero
|
|
}
|
|
} else {
|
|
// 计算户表表计的摊薄内容
|
|
if report.Summary.CustomerConsumption.Decimal.Abs().GreaterThan(decimal.Zero) {
|
|
eu.OverallProportion = eu.Overall.Decimal.Div(report.Summary.CustomerConsumption.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
|
|
}
|