336 lines
10 KiB
Go
336 lines
10 KiB
Go
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
|
||
}
|