222 lines
8.1 KiB
Go
222 lines
8.1 KiB
Go
package calculate
|
|
|
|
import (
|
|
"electricity_bill_calc/model"
|
|
"electricity_bill_calc/model/calculate"
|
|
"errors"
|
|
"github.com/shopspring/decimal"
|
|
"math/big"
|
|
)
|
|
|
|
// / 计算各个商户的合计信息,并归总与商户关联的表计记录
|
|
func CalculateTenementCharge(tenements []calculate.PrimaryTenementStatistics, summary calculate.Summary, meters MeterMap, relations []model.MeterRelation) ([]calculate.TenementCharge, error) {
|
|
tenementCharges := make([]calculate.TenementCharge, 0)
|
|
for _, tenement := range tenements {
|
|
relatedMeters := make([]calculate.Meter, 0)
|
|
for _, meter := range tenement.Meters {
|
|
code := meter.Code
|
|
if meter.Detail.MeterType == model.METER_INSTALLATION_TENEMENT {
|
|
code = meter.Detail.Code
|
|
}
|
|
relatedMeter, ok := meters[Key{Code: code}]
|
|
if !ok {
|
|
return nil, errors.New("related meter not found")
|
|
}
|
|
relatedMeters = append(relatedMeters, relatedMeter)
|
|
}
|
|
|
|
// Calculate overall, critical, peak, flat, valley, etc.
|
|
//var overall, critical, peak, flat, valley model.ConsumptionUnit
|
|
basicPooled, adjustPooled, lossPooled, publicPooled := new(big.Rat), new(big.Rat), new(big.Rat), new(big.Rat)
|
|
lossAmount := new(big.Rat)
|
|
for _, meter := range relatedMeters {
|
|
overall.Add(overall, meter.Overall)
|
|
critical.Add(critical, meter.Critical)
|
|
peak.Add(peak, meter.Peak)
|
|
flat.Add(flat, meter.Flat)
|
|
valley.Add(valley, meter.Valley)
|
|
basicPooled.Add(basicPooled, meter.PooledBasic.Fee)
|
|
adjustPooled.Add(adjustPooled, meter.PooledAdjust.Fee)
|
|
lossAmount.Add(lossAmount, meter.AdjustLoss.Amount)
|
|
lossPooled.Add(lossPooled, meter.PooledLoss.Fee)
|
|
publicPooled.Add(publicPooled, meter.PooledPublic.Fee)
|
|
}
|
|
|
|
// Update proportions and other data for related meters
|
|
for _, meter := range relatedMeters {
|
|
meter.Overall.Proportion = new(big.Rat).Quo(meter.Overall.Amount, overall.Amount)
|
|
meter.Critical.Proportion = new(big.Rat).Quo(meter.Critical.Amount, critical.Amount)
|
|
meter.Peak.Proportion = new(big.Rat).Quo(meter.Peak.Amount, peak.Amount)
|
|
meter.Flat.Proportion = new(big.Rat).Quo(meter.Flat.Amount, flat.Amount)
|
|
meter.Valley.Proportion = new(big.Rat).Quo(meter.Valley.Amount, valley.Amount)
|
|
meter.PooledBasic.Proportion = new(big.Rat).Quo(meter.PooledBasic.Fee, basicPooled)
|
|
meter.PooledAdjust.Proportion = new(big.Rat).Quo(meter.PooledAdjust.Fee, adjustPooled)
|
|
meter.PooledLoss.Proportion = new(big.Rat).Quo(meter.PooledLoss.Fee, lossPooled)
|
|
meter.PooledPublic.Proportion = new(big.Rat).Quo(meter.PooledPublic.Fee, publicPooled)
|
|
}
|
|
|
|
tenementCharges = append(tenementCharges, TenementCharges{
|
|
Tenement: tenement.Tenement.ID,
|
|
Overall: ConsumptionUnit{
|
|
Amount: overall.Amount,
|
|
Fee: new(big.Rat).Mul(overall.Amount, summary.Overall.Price),
|
|
Price: summary.Overall.Price,
|
|
Proportion: new(big.Rat).Quo(overall.Amount, summary.Overall.Amount),
|
|
},
|
|
Critical: ConsumptionUnit{
|
|
Amount: critical.Amount,
|
|
Fee: new(big.Rat).Mul(critical.Amount, summary.Critical.Price),
|
|
Price: summary.Critical.Price,
|
|
Proportion: new(big.Rat).Quo(critical.Amount, summary.Critical.Amount),
|
|
},
|
|
Peak: ConsumptionUnit{
|
|
Amount: peak.Amount,
|
|
Fee: new(big.Rat).Mul(peak.Amount, summary.Peak.Price),
|
|
Price: summary.Peak.Price,
|
|
Proportion: new(big.Rat).Quo(peak.Amount, summary.Peak.Amount),
|
|
},
|
|
Flat: ConsumptionUnit{
|
|
Amount: flat.Amount,
|
|
Fee: new(big.Rat).Mul(flat.Amount, summary.Flat.Price),
|
|
Price: summary.Flat.Price,
|
|
Proportion: new(big.Rat).Quo(flat.Amount, summary.Flat.Amount),
|
|
},
|
|
Valley: ConsumptionUnit{
|
|
Amount: valley.Amount,
|
|
Fee: new(big.Rat).Mul(valley.Amount, summary.Valley.Price),
|
|
Price: summary.Valley.Price,
|
|
Proportion: new(big.Rat).Quo(valley.Amount, summary.Valley.Amount),
|
|
},
|
|
Loss: ConsumptionUnit{
|
|
Amount: lossAmount,
|
|
Fee: new(big.Rat).Mul(lossPooled, summary.AuthorizeLoss.Price),
|
|
Price: summary.AuthorizeLoss.Price,
|
|
Proportion: new(big.Rat).Quo(lossAmount, summary.AuthorizeLoss.Amount),
|
|
},
|
|
BasicFee: basicPooled,
|
|
AdjustFee: adjustPooled,
|
|
LossPooled: lossPooled,
|
|
PublicPooled: publicPooled,
|
|
// ... 其他字段的初始化
|
|
})
|
|
}
|
|
|
|
return tenementCharges, nil
|
|
}
|
|
func calculateTenementCharge(
|
|
tenements []*PrimaryTenementStatistics,
|
|
summary *Summary,
|
|
meters MeterMap,
|
|
_relations []MeterRelation,
|
|
) ([]TenementCharges, error) {
|
|
var tenementCharges []TenementCharges
|
|
|
|
for _, t := range tenements {
|
|
meterCodes := make([]string, len(t.Meters))
|
|
for i, m := range t.Meters {
|
|
meterCodes[i] = m.Code
|
|
}
|
|
|
|
relatedMeters := make([]*Meter, len(meterCodes))
|
|
for i, code := range meterCodes {
|
|
relatedMeter, ok := meters[Key{Code: code, TenementID: t.Tenement.ID}]
|
|
if !ok {
|
|
// 处理未找到相关表计的情况
|
|
continue
|
|
}
|
|
relatedMeters[i] = relatedMeter
|
|
}
|
|
|
|
var overall, critical, peak, flat, valley ConsumptionUnit
|
|
var basicPooled, adjustPooled, lossAmount, lossPooled, publicPooled decimal.Decimal
|
|
|
|
for _, meter := range relatedMeters {
|
|
overall.Amount = overall.Amount.Add(meter.Overall.Amount)
|
|
overall.Fee = overall.Fee.Add(meter.Overall.Fee)
|
|
|
|
critical.Amount = critical.Amount.Add(meter.Critical.Amount)
|
|
critical.Fee = critical.Fee.Add(meter.Critical.Fee)
|
|
|
|
peak.Amount = peak.Amount.Add(meter.Peak.Amount)
|
|
peak.Fee = peak.Fee.Add(meter.Peak.Fee)
|
|
|
|
flat.Amount = flat.Amount.Add(meter.Flat.Amount)
|
|
flat.Fee = flat.Fee.Add(meter.Flat.Fee)
|
|
|
|
valley.Amount = valley.Amount.Add(meter.Valley.Amount)
|
|
valley.Fee = valley.Fee.Add(meter.Valley.Fee)
|
|
|
|
basicPooled = basicPooled.Add(meter.PooledBasic.Fee)
|
|
adjustPooled = adjustPooled.Add(meter.PooledAdjust.Fee)
|
|
|
|
lossAmount = lossAmount.Add(meter.AdjustLoss.Amount)
|
|
lossPooled = lossPooled.Add(meter.PooledLoss.Fee)
|
|
|
|
publicPooled = publicPooled.Add(meter.PooledPublic.Fee)
|
|
}
|
|
|
|
// 反写商户表计的统计数据
|
|
for _, meter := range relatedMeters {
|
|
meter.Overall.Proportion = meter.Overall.Amount.Div(overall.Amount)
|
|
meter.Critical.Proportion = meter.Critical.Amount.Div(critical.Amount)
|
|
meter.Peak.Proportion = meter.Peak.Amount.Div(peak.Amount)
|
|
meter.Flat.Proportion = meter.Flat.Amount.Div(flat.Amount)
|
|
meter.Valley.Proportion = meter.Valley.Amount.Div(valley.Amount)
|
|
meter.PooledBasic.Proportion = meter.PooledBasic.Fee.Div(basicPooled)
|
|
meter.PooledAdjust.Proportion = meter.PooledAdjust.Fee.Div(adjustPooled)
|
|
meter.PooledLoss.Proportion = meter.PooledLoss.Fee.Div(lossPooled)
|
|
meter.PooledPublic.Proportion = meter.PooledPublic.Fee.Div(publicPooled)
|
|
}
|
|
|
|
// 构造并添加商户的合计信息
|
|
tenementCharges = append(tenementCharges, TenementCharges{
|
|
Tenement: t.Tenement.ID,
|
|
Overall: ConsumptionUnit{
|
|
Price: summary.Overall.Price,
|
|
Proportion: overall.Amount.Div(summary.Overall.Amount),
|
|
Amount: overall.Amount,
|
|
Fee: overall.Fee,
|
|
},
|
|
Critical: ConsumptionUnit{
|
|
Price: summary.Critical.Price,
|
|
Proportion: critical.Amount.Div(summary.Critical.Amount),
|
|
Amount: critical.Amount,
|
|
Fee: critical.Fee,
|
|
},
|
|
Peak: ConsumptionUnit{
|
|
Price: summary.Peak.Price,
|
|
Proportion: peak.Amount.Div(summary.Peak.Amount),
|
|
Amount: peak.Amount,
|
|
Fee: peak.Fee,
|
|
},
|
|
Flat: ConsumptionUnit{
|
|
Price: summary.Flat.Price,
|
|
Proportion: flat.Amount.Div(summary.Flat.Amount),
|
|
Amount: flat.Amount,
|
|
Fee: flat.Fee,
|
|
},
|
|
Valley: ConsumptionUnit{
|
|
Price: summary.Valley.Price,
|
|
Proportion: valley.Amount.Div(summary.Valley.Amount),
|
|
Amount: valley.Amount,
|
|
Fee: valley.Fee,
|
|
},
|
|
Loss: ConsumptionUnit{
|
|
Price: summary.AuthorizeLoss.Price,
|
|
Proportion: lossAmount.Div(summary.AuthorizeLoss.Amount),
|
|
Amount: lossAmount,
|
|
Fee: lossPooled,
|
|
},
|
|
BasicFee: basicPooled,
|
|
AdjustFee: adjustPooled,
|
|
LossPooled: lossPooled,
|
|
PublicPooled: publicPooled,
|
|
FinalCharges: overall.Fee.Add(basicPooled).Add(adjustPooled).Add(lossPooled).Add(publicPooled),
|
|
Submeters: relatedMeters,
|
|
Poolings: make([]Meter, 0), // TODO: Add pooling logic here
|
|
})
|
|
}
|
|
|
|
return tenementCharges, nil
|
|
}
|