electricity_bill_calc_service/service/calculate/meters.go

336 lines
10 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"
"electricity_bill_calc/repository"
"errors"
"fmt"
"github.com/shopspring/decimal"
"log"
)
func CollectMeters(tenements []calculate.PrimaryTenementStatistics, poolings []calculate.Meter, publics []calculate.Meter) (MeterMap, error) {
meters := make(MeterMap)
// Collect tenement meters
for _, t := range tenements {
for _, m := range t.Meters {
log.Println("m000000000000000000000000000", m.Code)
key := Key{TenementID: t.Tenement.Id, Code: m.Code}
meters[key] = m
}
}
// Collect poolings
for _, m := range poolings {
log.Println("m111111111111111111111111", m.Code)
key := Key{TenementID: "", Code: m.Code}
meters[key] = m
}
// Collect publics
for _, m := range publics {
log.Println("m222222222222222222222222222", m.Code)
key := Key{TenementID: "", Code: m.Code}
meters[key] = m
}
log.Println("m33333333333333333333333333333333333333", meters[Key{Code: "yq00001"}])
return meters, nil
}
// / 计算基本电费摊薄
func CalculateBasicPooling(report *model.ReportIndex, summary *calculate.Summary, meters *MeterMap) error {
switch report.BasisPooled {
case model.POOLING_MODE_AREA:
if summary.OverallArea.IsZero() {
return fmt.Errorf("园区中表计覆盖总面积为零,无法按面积摊薄")
}
for _, meter := range *meters {
meterFee := meter.Overall.Amount.InexactFloat64() * summary.BasicPooledPriceArea.InexactFloat64()
meter.PooledBasic = model.ConsumptionUnit{
Amount: meter.Overall.Amount,
Fee: decimal.NewFromFloat(meterFee),
Price: summary.BasicPooledPriceArea,
Proportion: summary.BasicFee,
}
}
case model.POOLING_MODE_CONSUMPTION:
for _, meter := range *meters {
meterFee := meter.Overall.Amount.InexactFloat64() * summary.BasicPooledPriceConsumption.InexactFloat64()
meter.PooledBasic = model.ConsumptionUnit{
Amount: meter.Overall.Amount,
Fee: decimal.NewFromFloat(meterFee),
Price: summary.BasicPooledPriceConsumption,
Proportion: summary.BasicFee,
}
}
default:
}
return nil
}
/// 计算调整电费摊薄
func CalculateAdjustPooling(report model.ReportIndex, summary calculate.Summary, meters MeterMap) error {
var p decimal.Decimal
switch report.AdjustPooled {
case model.POOLING_MODE_AREA:
if summary.OverallArea.IsZero() {
return fmt.Errorf("园区中表计覆盖总面积为零,无法按面积摊薄")
}
for _, meter := range meters {
meterFee := meter.Overall.Amount.Mul(summary.AdjustPooledPriceArea)
if summary.AdjustFee.IsZero() {
p = decimal.Zero
} else {
p = meterFee.Div(summary.AdjustFee)
}
meter.PooledAdjust = model.ConsumptionUnit{
Amount: meter.Overall.Amount,
Fee: meterFee,
Price: summary.AdjustPooledPriceArea,
Proportion: p,
}
}
case model.POOLING_MODE_CONSUMPTION:
for _, meter := range meters {
meterFee := meter.Overall.Amount.Mul(summary.AdjustPooledPriceConsumption)
if summary.AdjustFee.IsZero() {
p = decimal.Zero
} else {
p = meterFee.Div(summary.AdjustFee)
}
meter.PooledAdjust = model.ConsumptionUnit{
Amount: meter.Overall.Amount,
Fee: meterFee,
Price: summary.AdjustPooledPriceConsumption,
Proportion: p,
}
}
default:
}
return nil
}
// 除数问题
func CalculateLossPooling(report model.ReportIndex, summary calculate.Summary, meters MeterMap) error {
switch report.LossPooled {
case model.POOLING_MODE_AREA:
if summary.OverallArea.IsZero() {
return fmt.Errorf("园区中表计覆盖总面积为零,无法按面积摊薄")
}
for _, meter := range meters {
pooledLossAmount1 := meter.Detail.Area.Decimal.Div(summary.OverallArea)
pooledLossAmount := pooledLossAmount1.Mul(summary.AuthoizeLoss.Amount)
meter.PooledLoss = model.ConsumptionUnit{
Amount: pooledLossAmount,
Fee: pooledLossAmount.Mul(summary.LossDilutedPrice),
Price: summary.LossDilutedPrice,
Proportion: meter.Detail.Area.Decimal.Div(summary.OverallArea),
}
}
case model.POOLING_MODE_CONSUMPTION:
for _, meter := range meters {
pooledLossAmount1 := meter.Detail.Area.Decimal.Div(summary.OverallArea)
pooledLossAmount := pooledLossAmount1.Mul(summary.AuthoizeLoss.Amount)
meter.PooledLoss = model.ConsumptionUnit{
Amount: pooledLossAmount,
Fee: pooledLossAmount.Mul(summary.LossDilutedPrice),
Price: summary.LossDilutedPrice,
Proportion: meter.Overall.Amount.Div(summary.Overall.Amount),
}
}
default:
// 其他情况下不做处理
}
return nil
}
/// 计算所有商户类型表计的全周期电量。
func CalculateTenementConsumptions(meters MeterMap) (map[string]decimal.Decimal, error) {
consumptions := make(map[string]decimal.Decimal)
for _, meter := range meters {
if meter.Detail.MeterType == model.METER_INSTALLATION_TENEMENT {
amount, ok := consumptions[meter.Code]
if !ok {
amount = decimal.Decimal{}
}
amount.Add(meter.Overall.Amount).Add(amount)
consumptions[meter.Code] = amount
}
}
for _, meter := range meters {
if meter.Detail.MeterType == model.METER_INSTALLATION_TENEMENT {
amount, ok := consumptions[meter.Code]
if !ok {
return nil, errors.New("meter code not found in consumptions")
}
if amount.GreaterThan(decimal.Zero) {
meter.SharedPoolingProportion = meter.Overall.Amount.Div(amount)
} else if amount.IsZero() {
meter.SharedPoolingProportion = decimal.NewFromFloat(1.0)
} else {
meter.SharedPoolingProportion = decimal.NewFromFloat(1.0)
}
}
}
return consumptions, nil
}
// 计算商户表计的公摊分摊
func CalculateTenementPoolings(report model.ReportIndex, summary calculate.Summary, meters MeterMap, meterRelations []model.MeterRelation) error {
switch report.PublicPooled {
case model.POOLING_MODE_AREA:
for _, meter := range meters {
if meter.Detail.MeterType != model.METER_INSTALLATION_TENEMENT {
var pooleds []struct {
PooledAmount decimal.Decimal
ParentAmount decimal.Decimal
ParentCode string
}
for _, relation := range meterRelations {
if relation.SlaveMeter == meter.Code {
key := Key{
Code: relation.MasterMeter,
}
parentMeter, ok := meters[key]
if !ok {
// 处理未找到父级表计的情况
continue
}
// 计算分摊电量和父级表电量
pooledAmount := meter.Detail.Area.Decimal.Div(parentMeter.CoveredArea).Mul(parentMeter.Overall.Amount).Mul(meter.SharedPoolingProportion)
pooleds = append(pooleds, struct {
PooledAmount decimal.Decimal
ParentAmount decimal.Decimal
ParentCode string
}{
PooledAmount: pooledAmount,
ParentAmount: parentMeter.Overall.Amount,
ParentCode: parentMeter.Code,
})
}
}
// 计算总分摊电量和总父级电量
var consumptions, total decimal.Decimal
for _, p := range pooleds {
consumptions = consumptions.Add(p.PooledAmount)
total = total.Add(p.ParentAmount)
}
// 计算并更新公摊分摊信息
for _, p := range pooleds {
poolingAmount := p.PooledAmount
proportion := p.PooledAmount.Div(p.ParentAmount)
fee := poolingAmount.Mul(summary.Overall.Price)
// 更新父级表计的公摊分摊信息
key := Key{
Code: p.ParentCode,
}
parentMeter := meters[key]
parentMeter.PooledPublic.Amount = consumptions
parentMeter.PooledPublic.Fee = consumptions.Mul(summary.Overall.Price)
parentMeter.PooledPublic.Proportion = consumptions.Div(total)
meters[Key{Code: p.ParentCode}] = parentMeter
// 创建并更新分摊信息
pooling := calculate.Pooling{
Code: p.ParentCode,
Detail: model.ConsumptionUnit{
Amount: poolingAmount,
Fee: fee,
Price: summary.Overall.Price,
Proportion: proportion,
},
}
meter.Poolings = append(meter.Poolings, &pooling)
}
}
}
case model.POOLING_MODE_CONSUMPTION:
for _, meter := range meters {
if meter.Detail.MeterType == model.METER_INSTALLATION_TENEMENT {
var pooled []struct {
PooledAmount decimal.Decimal
ParentAmount decimal.Decimal
ParentCode string
}
for _, relation := range meterRelations {
if relation.SlaveMeter == meter.Code {
parentMeter, ok := meters[Key{Code: relation.MasterMeter}]
if !ok {
// 处理未找到父级表计的情况
continue
}
// 计算分摊电量和父级电量
var pooledAmount decimal.Decimal
if parentMeter.Overall.Amount.IsZero() {
relations, err := repository.MeterRepository.ListPooledMeterRelations(report.Park, meter.Code)
if err != nil {
return err
}
//此处rust版本有误更新后的解决办法
pooledAmount = meter.Overall.Amount.Div(decimal.NewFromInt(int64(len(relations)))).Mul(parentMeter.Overall.Amount)
}
pooled = append(pooled, struct {
PooledAmount decimal.Decimal
ParentAmount decimal.Decimal
ParentCode string
}{
PooledAmount: pooledAmount,
ParentAmount: parentMeter.Overall.Amount,
ParentCode: parentMeter.Code,
})
}
}
// 计算总分摊电量和总父级表记电量
var consumptions, total decimal.Decimal
for _, p := range pooled {
consumptions = consumptions.Add(p.PooledAmount)
total = total.Add(p.ParentAmount)
}
// 计算并更新公摊分摊信息
for _, p := range pooled {
poolingAmount := p.PooledAmount
proportion := p.PooledAmount.Div(p.ParentAmount)
fee := poolingAmount.Mul(summary.Overall.Price)
// 更新父级表计的公摊分摊信息
parentMeter := meters[Key{Code: p.ParentCode}]
parentMeter.PooledPublic.Amount = consumptions
parentMeter.PooledPublic.Fee = consumptions.Mul(summary.Overall.Price)
parentMeter.PooledPublic.Proportion = consumptions.Div(total)
meters[Key{Code: p.ParentCode}] = parentMeter
// 创建并更新分摊信息
pooling := calculate.Pooling{
Code: p.ParentCode,
Detail: model.ConsumptionUnit{
Amount: poolingAmount,
Fee: fee,
Price: summary.Overall.Price,
Proportion: proportion,
},
}
meter.Poolings = append(meter.Poolings, &pooling)
}
}
}
default:
// 处理其他分摊模式
}
return nil
}