electricity_bill_calc_service/service/calculate/summary.go

143 lines
4.7 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 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
}