143 lines
4.7 KiB
Go
143 lines
4.7 KiB
Go
package calculate
|
||
|
||
import (
|
||
"electricity_bill_calc/model"
|
||
"electricity_bill_calc/model/calculate"
|
||
"errors"
|
||
"github.com/shopspring/decimal"
|
||
|
||
"fmt"
|
||
)
|
||
|
||
// 计算已经启用的商铺面积和
|
||
func TotalConsumptionCalculate(tenements []calculate.PrimaryTenementStatistics, summary calculate.Summary) decimal.Decimal {
|
||
var areaMaters []calculate.Meter
|
||
for _, t := range tenements {
|
||
areaMaters = append(areaMaters, t.Meters...)
|
||
}
|
||
|
||
areaMaters = removeDuplicates(areaMaters)
|
||
|
||
var areaTotal float64
|
||
for _, m := range areaMaters {
|
||
areaTotal += m.Detail.Area.Decimal.InexactFloat64()
|
||
}
|
||
|
||
areaTotal += summary.OverallArea.InexactFloat64()
|
||
|
||
return decimal.NewFromFloat(areaTotal)
|
||
|
||
}
|
||
|
||
func removeDuplicates(meters []calculate.Meter) []calculate.Meter {
|
||
result := make([]calculate.Meter, 0, len(meters))
|
||
seen := make(map[string]bool)
|
||
for _, meter := range meters {
|
||
if !seen[meter.Code] {
|
||
seen[meter.Code] = true
|
||
result = append(result, meter)
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
// 计算线损以及调整线损
|
||
func LossCalculate(report *model.ReportIndex, Public []calculate.Meter,
|
||
publicTotal *decimal.Decimal, summary *calculate.Summary) error {
|
||
summary.Loss = summary.Overall.Amount.Sub(summary.TotalConsumption)
|
||
|
||
var summaryAmount decimal.Decimal
|
||
if summary.Overall.Amount == decimal.Zero {
|
||
summaryAmount = decimal.NewFromFloat(1.0)
|
||
} else {
|
||
summaryAmount = summary.Overall.Amount
|
||
}
|
||
|
||
summary.LossProportion = summary.Loss.Div(summaryAmount)
|
||
|
||
var authorizedLossRate decimal.Decimal
|
||
// TODO: 2023.08.04 在此发现reportIndex结构体与数据库中的report表字段不对应缺少两个相应字段,在此添加的,如在其他地方有错误优先查找这里
|
||
if summary.LossProportion.InexactFloat64() > report.AuthorizedLossRate {
|
||
authorizedLossRate = summary.LossProportion
|
||
} else {
|
||
return errors.New(fmt.Sprintf("经过核算园区的线损率为:{%.8f}, 核定线损率为:{%.8f}", summary.LossProportion.InexactFloat64(), authorizedLossRate.InexactFloat64()))
|
||
}
|
||
|
||
summary.AuthoizeLoss = model.ConsumptionUnit{
|
||
Amount: decimal.NewFromFloat(summary.Overall.Amount.InexactFloat64() * authorizedLossRate.InexactFloat64()),
|
||
Fee: decimal.NewFromFloat((summary.Overall.Amount.InexactFloat64() * authorizedLossRate.InexactFloat64()) * summary.Overall.Price.InexactFloat64()),
|
||
Price: summary.Overall.Price,
|
||
Proportion: authorizedLossRate,
|
||
}
|
||
|
||
differentialLoss := summary.LossDilutedPrice.Sub(summary.AuthoizeLoss.Amount)
|
||
|
||
fmt.Println(publicTotal.InexactFloat64())
|
||
if publicTotal.InexactFloat64() <= decimal.Zero.InexactFloat64() {
|
||
return errors.New("园区公共表计的电量总和为非正值,或者园区未设置公共表计,无法计算核定线损")
|
||
}
|
||
|
||
if Public == nil {
|
||
return nil
|
||
}
|
||
for _, meter := range Public {
|
||
amountProportion := meter.Overall.Amount.InexactFloat64() / publicTotal.InexactFloat64()
|
||
adjustAmount := differentialLoss.InexactFloat64() * decimal.NewFromFloat(-1.0).InexactFloat64()
|
||
meter.AdjustLoss = model.ConsumptionUnit{
|
||
Amount: decimal.NewFromFloat(adjustAmount),
|
||
Fee: decimal.NewFromFloat(adjustAmount * summary.LossDilutedPrice.InexactFloat64()),
|
||
Price: summary.LossDilutedPrice,
|
||
Proportion: decimal.NewFromFloat(amountProportion),
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// 计算已经启用的商铺面积和
|
||
func EnabledAreaCalculate(tenements *[]calculate.PrimaryTenementStatistics,
|
||
summary *calculate.Summary) (*decimal.Decimal, error) {
|
||
var areaMeters []calculate.Meter
|
||
for _, t := range *tenements {
|
||
areaMeters = append(areaMeters, t.Meters...)
|
||
}
|
||
// 去重
|
||
uniqueAreaMeters := make(map[string]calculate.Meter)
|
||
for _, meter := range areaMeters {
|
||
uniqueAreaMeters[meter.Code] = meter
|
||
}
|
||
var areaTotal decimal.Decimal
|
||
for _, meter := range uniqueAreaMeters {
|
||
areaTotal = areaTotal.Add(meter.Detail.Area.Decimal)
|
||
}
|
||
if summary != nil {
|
||
summary.OverallArea = areaTotal
|
||
} else {
|
||
return nil, errors.New("summary is nil")
|
||
}
|
||
return &areaTotal, nil
|
||
}
|
||
|
||
// =================================================================================
|
||
// / 计算基本电费分摊、调整电费分摊以及电费摊薄单价。
|
||
// /
|
||
// / - `summary`:核算报表的摘要信息
|
||
func CalculatePrices(summary *calculate.Summary) error {
|
||
if summary.TotalConsumption.IsZero() {
|
||
return nil
|
||
}
|
||
summary.BasicPooledPriceConsumption = summary.BasicFee.Div(summary.TotalConsumption)
|
||
if summary.OverallArea.IsZero() {
|
||
summary.BasicPooledPriceArea = decimal.Zero
|
||
} else {
|
||
summary.BasicPooledPriceArea = summary.BasicFee.Div(summary.OverallArea)
|
||
}
|
||
summary.AdjustPooledPriceConsumption = summary.AdjustFee.Div(summary.TotalConsumption)
|
||
if summary.OverallArea.IsZero() {
|
||
summary.AdjustPooledPriceArea = decimal.Zero
|
||
} else {
|
||
summary.AdjustPooledPriceArea = summary.AdjustFee.Div(summary.OverallArea)
|
||
}
|
||
return nil
|
||
|
||
}
|