90 lines
3.0 KiB
Go
90 lines
3.0 KiB
Go
package calculate
|
||
|
||
import (
|
||
"electricity_bill_calc/model"
|
||
"electricity_bill_calc/model/calculate"
|
||
"errors"
|
||
"fmt"
|
||
"github.com/shopspring/decimal"
|
||
)
|
||
|
||
// 计算已经启用的商铺面积和
|
||
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
|
||
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)
|
||
|
||
if publicTotal.InexactFloat64() <= decimal.Zero.InexactFloat64() {
|
||
return errors.New("园区公共表计的电量总和为非正值,或者园区未设置公共表计,无法计算核定线损")
|
||
}
|
||
|
||
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
|
||
}
|