electricity_bill_calc_service/service/calculate.go

319 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}