forked from free-lancers/electricity_bill_calc_service
		
	
		
			
				
	
	
		
			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
 | ||
| }
 |