feat(report):完成电费公示报表的计算功能。
This commit is contained in:
parent
4919c7152f
commit
4aa7221158
|
@ -37,6 +37,7 @@ func InitializeReportController(router *gin.Engine) {
|
|||
router.POST("/report/:rid/publish", security.EnterpriseAuthorize, publishReport)
|
||||
router.GET("/reports", security.MustAuthenticated, searchReports)
|
||||
router.GET("/report/:rid", security.MustAuthenticated, fetchReportPublicity)
|
||||
router.POST("/report/:rid/calculate", security.EnterpriseAuthorize, calculateReport)
|
||||
}
|
||||
|
||||
func ensureReportBelongs(c *gin.Context, result *response.Result, requestReportId string) bool {
|
||||
|
@ -461,3 +462,17 @@ func fetchReportPublicity(c *gin.Context) {
|
|||
}
|
||||
result.Success("已经取得指定公示报表的发布版本。", tools.ConvertStructToMap(publicity))
|
||||
}
|
||||
|
||||
func calculateReport(c *gin.Context) {
|
||||
result := response.NewResult(c)
|
||||
requestReportId := c.Param("rid")
|
||||
if !ensureReportBelongs(c, result, requestReportId) {
|
||||
return
|
||||
}
|
||||
err := service.CalculateService.ComprehensivelyCalculateReport(requestReportId)
|
||||
if err != nil {
|
||||
result.Error(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
result.Success("指定公示报表中的数据已经计算完毕。")
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ type EndUserDetail struct {
|
|||
AdjustValley decimal.Decimal `xorm:"numeric(14,2) not null default 0" json:"adjustValley"`
|
||||
Overall decimal.NullDecimal `xorm:"numeric(14,2)" json:"overall"`
|
||||
OverallFee decimal.NullDecimal `xorm:"numeric(14,2)" json:"overallFee"`
|
||||
OverallProporttion decimal.Decimal `xorm:"numeric(16,15) not null default 0" json:"-"`
|
||||
OverallProportion decimal.Decimal `xorm:"numeric(16,15) not null default 0" json:"-"`
|
||||
Critical decimal.NullDecimal `xorm:"numeric(14,2)" json:"critical"`
|
||||
CriticalFee decimal.NullDecimal `xorm:"numeric(18,8)" json:"criticalFee"`
|
||||
Peak decimal.NullDecimal `xorm:"numeric(14,2)" json:"peak"`
|
||||
|
|
|
@ -26,7 +26,7 @@ type PaidPart struct {
|
|||
type EndUserOverallPart struct {
|
||||
Overall decimal.Decimal `json:"overall"`
|
||||
OverallPrice decimal.Decimal `json:"overallPrice"`
|
||||
OverallFee decimal.Decimal `json:"overallFee"`
|
||||
OverallFee decimal.Decimal `json:"consumptionFee"`
|
||||
Critical decimal.NullDecimal `json:"critical"`
|
||||
CriticalPrice decimal.NullDecimal `json:"criticalPrice"`
|
||||
CriticalFee decimal.NullDecimal `json:"criticalFee"`
|
||||
|
@ -107,7 +107,7 @@ type Publicity struct {
|
|||
EndUser EndUserOverallPart `json:"endUserSum"`
|
||||
Loss LossPart `json:"loss"`
|
||||
PublicConsumptionOverall PublicConsumptionOverallPart `json:"public"`
|
||||
OtherCollections OtherShouldCollectionPart `json:"other"`
|
||||
OtherCollections OtherShouldCollectionPart `json:"others"`
|
||||
Maintenance MaintenancePart `json:"maintenance"`
|
||||
EndUserDetails []EndUserSummary `json:"endUser"`
|
||||
}
|
||||
|
|
|
@ -76,7 +76,11 @@ func (s ReportSummary) Validate() (bool, error) {
|
|||
|
||||
func (s *ReportSummary) CalculatePrices() {
|
||||
s.ConsumptionFee = decimal.NewNullDecimal(s.OverallFee.Sub(s.BasicFee).Sub(s.AdjustFee))
|
||||
s.OverallPrice = decimal.NewNullDecimal(s.ConsumptionFee.Decimal.Div(s.Overall).RoundBank(8))
|
||||
if s.Overall.GreaterThan(decimal.Zero) {
|
||||
s.OverallPrice = decimal.NewNullDecimal(s.ConsumptionFee.Decimal.Div(s.Overall).RoundBank(8))
|
||||
} else {
|
||||
s.OverallPrice = decimal.NewNullDecimal(decimal.Zero)
|
||||
}
|
||||
if s.Critical.GreaterThan(decimal.Zero) {
|
||||
s.CriticalPrice = decimal.NewNullDecimal(s.CriticalFee.Div(s.Critical).RoundBank(8))
|
||||
} else {
|
||||
|
|
245
service/calculate.go
Normal file
245
service/calculate.go
Normal file
|
@ -0,0 +1,245 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"electricity_bill_calc/exceptions"
|
||||
"electricity_bill_calc/global"
|
||||
"electricity_bill_calc/model"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm/schemas"
|
||||
)
|
||||
|
||||
type _CalculateService struct{}
|
||||
|
||||
var CalculateService _CalculateService
|
||||
|
||||
func (_CalculateService) ComprehensivelyCalculateReport(reportId string) (err error) {
|
||||
// 资料准备
|
||||
var reportIndex = new(model.Report)
|
||||
has, err := global.DBConn.ID(reportId).NoAutoCondition().Get(reportIndex)
|
||||
if err != nil || !has {
|
||||
return exceptions.NewNotFoundErrorFromError("未找到指定的公示报表", err)
|
||||
}
|
||||
var summary = new(model.ReportSummary)
|
||||
has, err = global.DBConn.ID(reportId).NoAutoCondition().Get(summary)
|
||||
if err != nil || !has {
|
||||
return exceptions.NewNotFoundErrorFromError("未找到指定的公示报表概览", err)
|
||||
}
|
||||
var maintenanceFeeRecords = make([]model.WillDilutedFee, 0)
|
||||
err = global.DBConn.Where(builder.Eq{"report_id": reportId}).Find(&maintenanceFeeRecords)
|
||||
if err != nil {
|
||||
return exceptions.NewNotFoundErrorFromError("未能获取到公示报表对应的待摊薄费用信息", err)
|
||||
}
|
||||
var endUserDetails = make([]*model.EndUserDetail, 0)
|
||||
err = global.DBConn.Where(builder.Eq{"report_id": reportId}).Find(&endUserDetails)
|
||||
if err != nil {
|
||||
return exceptions.NewNotFoundErrorFromError("未获取到公示报表对应的终端用户抄表信息", err)
|
||||
}
|
||||
|
||||
// 综合计算
|
||||
summary.CalculatePrices()
|
||||
|
||||
// 计算维护费总计
|
||||
maintenanceFeeTotal := decimal.NewFromInt(0)
|
||||
for _, m := range maintenanceFeeRecords {
|
||||
maintenanceFeeTotal = maintenanceFeeTotal.Add(m.Fee)
|
||||
}
|
||||
|
||||
// 计算终端用户信息与概览中的合计
|
||||
summary.PublicConsumption = decimal.NewNullDecimal(decimal.Zero)
|
||||
summary.PublicConsumptionCritical = decimal.NewNullDecimal(decimal.Zero)
|
||||
summary.PublicConsumptionPeak = decimal.NewNullDecimal(decimal.Zero)
|
||||
summary.PublicConsumptionFlat = decimal.NewNullDecimal(decimal.Zero)
|
||||
summary.PublicConsumptionValley = decimal.NewNullDecimal(decimal.Zero)
|
||||
summary.CustomerConsumption = decimal.NewNullDecimal(decimal.Zero)
|
||||
summary.CustomerConsumptionCritical = decimal.NewNullDecimal(decimal.Zero)
|
||||
summary.CustomerConsumptionPeak = decimal.NewNullDecimal(decimal.Zero)
|
||||
summary.CustomerConsumptionFlat = decimal.NewNullDecimal(decimal.Zero)
|
||||
summary.CustomerConsumptionValley = decimal.NewNullDecimal(decimal.Zero)
|
||||
for _, eu := range endUserDetails {
|
||||
eu.OverallFee = decimal.NewNullDecimal(
|
||||
eu.Overall.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
eu.CriticalFee = decimal.NewNullDecimal(
|
||||
eu.Critical.Decimal.Mul(summary.CriticalPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
eu.PeakFee = decimal.NewNullDecimal(
|
||||
eu.Peak.Decimal.Mul(summary.PeakPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
eu.FlatFee = decimal.NewNullDecimal(
|
||||
eu.Flat.Decimal.Mul(summary.FlatPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
eu.ValleyFee = decimal.NewNullDecimal(
|
||||
eu.Valley.Decimal.Mul(summary.ValleyPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
if eu.IsPublicMeter && eu.WillDilute {
|
||||
summary.PublicConsumption.Decimal = summary.PublicConsumption.Decimal.Add(eu.Overall.Decimal)
|
||||
summary.PublicConsumptionCritical.Decimal = summary.PublicConsumptionCritical.Decimal.Add(eu.Critical.Decimal)
|
||||
summary.PublicConsumptionPeak.Decimal = summary.PublicConsumptionPeak.Decimal.Add(eu.Peak.Decimal)
|
||||
summary.PublicConsumptionFlat.Decimal = summary.PublicConsumptionPeak.Decimal.Add(eu.Flat.Decimal)
|
||||
summary.PublicConsumptionValley.Decimal = summary.PublicConsumptionValley.Decimal.Add(eu.Valley.Decimal)
|
||||
} else {
|
||||
summary.CustomerConsumption.Decimal = summary.CustomerConsumption.Decimal.Add(eu.Overall.Decimal)
|
||||
summary.CustomerConsumptionCritical.Decimal = summary.CustomerConsumptionCritical.Decimal.Add(eu.Critical.Decimal)
|
||||
summary.CustomerConsumptionPeak.Decimal = summary.CustomerConsumptionPeak.Decimal.Add(eu.Peak.Decimal)
|
||||
summary.CustomerConsumptionFlat.Decimal = summary.CustomerConsumptionPeak.Decimal.Add(eu.Flat.Decimal)
|
||||
summary.CustomerConsumptionValley.Decimal = summary.CustomerConsumptionValley.Decimal.Add(eu.Valley.Decimal)
|
||||
}
|
||||
}
|
||||
|
||||
// 计算户表总电费和公共总电费以及相应的摊薄
|
||||
summary.CustomerConsumptionFee = decimal.NewNullDecimal(
|
||||
summary.CustomerConsumption.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
summary.CustomerConsumptionCriticalFee = decimal.NewNullDecimal(
|
||||
summary.CustomerConsumptionCritical.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
summary.CustomerConsumptionPeakFee = decimal.NewNullDecimal(
|
||||
summary.CustomerConsumptionPeak.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
summary.CustomerConsumptionFlatFee = decimal.NewNullDecimal(
|
||||
summary.CustomerConsumptionFlat.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
summary.CustomerConsumptionValleyFee = decimal.NewNullDecimal(
|
||||
summary.CustomerConsumptionValley.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
summary.PublicConsumptionFee = decimal.NewNullDecimal(
|
||||
summary.PublicConsumption.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
summary.PublicConsumptionCriticalFee = decimal.NewNullDecimal(
|
||||
summary.PublicConsumptionCritical.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
summary.PublicConsumptionPeakFee = decimal.NewNullDecimal(
|
||||
summary.PublicConsumptionPeak.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
summary.PublicConsumptionFlatFee = decimal.NewNullDecimal(
|
||||
summary.PublicConsumptionFlat.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
summary.PublicConsumptionValleyFee = decimal.NewNullDecimal(
|
||||
summary.PublicConsumptionValley.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
if summary.Overall.Abs().GreaterThan(decimal.Zero) {
|
||||
summary.PublicConsumptionProportion = decimal.NewNullDecimal(
|
||||
summary.PublicConsumption.Decimal.Div(summary.Overall).RoundBank(15),
|
||||
)
|
||||
}
|
||||
|
||||
// 计算线损
|
||||
summary.Loss = decimal.NewNullDecimal(
|
||||
summary.Overall.Sub(summary.PublicConsumption.Decimal).Sub(summary.CustomerConsumption.Decimal),
|
||||
)
|
||||
summary.LossFee = decimal.NewNullDecimal(
|
||||
summary.Loss.Decimal.Mul(summary.OverallPrice.Decimal).RoundBank(8),
|
||||
)
|
||||
if summary.Overall.Abs().GreaterThan(decimal.Zero) {
|
||||
summary.LossProportion = decimal.NewNullDecimal(
|
||||
summary.Loss.Decimal.Div(summary.Overall).RoundBank(15),
|
||||
)
|
||||
}
|
||||
if summary.CustomerConsumption.Decimal.Abs().GreaterThan(decimal.Zero) {
|
||||
summary.LossDilutedPrice = decimal.NewNullDecimal(
|
||||
summary.LossFee.Decimal.Div(summary.CustomerConsumption.Decimal).RoundBank(8),
|
||||
)
|
||||
}
|
||||
|
||||
// 计算基本电费和调整电费等的摊薄
|
||||
if summary.CustomerConsumption.Decimal.Abs().GreaterThan(decimal.Zero) {
|
||||
summary.BasicDilutedPrice = decimal.NewNullDecimal(
|
||||
summary.BasicFee.Div(summary.CustomerConsumption.Decimal).RoundBank(8),
|
||||
)
|
||||
summary.AdjustDilutedPrice = decimal.NewNullDecimal(
|
||||
summary.AdjustFee.Div(summary.CustomerConsumption.Decimal).RoundBank(8),
|
||||
)
|
||||
summary.MaintenanceDilutedPrice = decimal.NewNullDecimal(
|
||||
maintenanceFeeTotal.Div(summary.CustomerConsumption.Decimal).RoundBank(8),
|
||||
)
|
||||
summary.PublicConsumptionDilutedPrice = decimal.NewNullDecimal(
|
||||
summary.PublicConsumptionFee.Decimal.Div(summary.CustomerConsumption.Decimal).RoundBank(8),
|
||||
)
|
||||
}
|
||||
|
||||
// 计算摊薄总计
|
||||
summary.FinalDilutedOverall = decimal.NewNullDecimal(
|
||||
summary.BasicFee.
|
||||
Add(summary.AdjustFee).
|
||||
Add(summary.PublicConsumptionFee.Decimal).
|
||||
Add(maintenanceFeeTotal).
|
||||
Add(summary.LossFee.Decimal),
|
||||
)
|
||||
|
||||
// 计算终端用户的全部摊薄内容
|
||||
for _, eu := range endUserDetails {
|
||||
if eu.IsPublicMeter && eu.WillDilute {
|
||||
// 计算需要摊薄的公共表计的摊薄内容
|
||||
if summary.PublicConsumption.Decimal.Abs().GreaterThan(decimal.Zero) {
|
||||
eu.OverallProportion = eu.Overall.Decimal.Div(summary.PublicConsumption.Decimal).RoundBank(15)
|
||||
} else {
|
||||
eu.OverallProportion = decimal.Zero
|
||||
}
|
||||
} else {
|
||||
// 计算户表表计的摊薄内容
|
||||
if summary.CustomerConsumption.Decimal.Abs().GreaterThan(decimal.Zero) {
|
||||
eu.OverallProportion = eu.Overall.Decimal.Div(summary.CustomerConsumption.Decimal).RoundBank(15)
|
||||
} else {
|
||||
eu.OverallProportion = decimal.Zero
|
||||
}
|
||||
eu.BasicFeeDiluted = decimal.NewNullDecimal(
|
||||
eu.Overall.Decimal.Mul(summary.BasicDilutedPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
eu.AdjustFeeDiluted = decimal.NewNullDecimal(
|
||||
eu.Overall.Decimal.Mul(summary.AdjustDilutedPrice.Decimal).RoundBank(2),
|
||||
)
|
||||
eu.LossDiluted = decimal.NewNullDecimal(
|
||||
summary.Loss.Decimal.Mul(eu.OverallProportion).RoundBank(8),
|
||||
)
|
||||
eu.LossDiluted = decimal.NewNullDecimal(
|
||||
eu.Overall.Decimal.Mul(summary.LossDilutedPrice.Decimal).RoundBank(8),
|
||||
)
|
||||
eu.MaintenanceFeeDiluted = decimal.NewNullDecimal(
|
||||
eu.Overall.Decimal.Mul(summary.MaintenanceDilutedPrice.Decimal).RoundBank(8),
|
||||
)
|
||||
eu.PublicConsumptionDiluted = decimal.NewNullDecimal(
|
||||
eu.Overall.Decimal.Mul(summary.PublicConsumptionDilutedPrice.Decimal).RoundBank(8),
|
||||
)
|
||||
eu.FinalDiluted = decimal.NewNullDecimal(
|
||||
eu.BasicFeeDiluted.Decimal.
|
||||
Add(eu.AdjustFeeDiluted.Decimal).
|
||||
Add(eu.LossFeeDiluted.Decimal).
|
||||
Add(eu.MaintenanceFeeDiluted.Decimal).
|
||||
Add(eu.PublicConsumptionDiluted.Decimal).
|
||||
RoundBank(2),
|
||||
)
|
||||
eu.FinalCharge = decimal.NewNullDecimal(
|
||||
eu.OverallFee.Decimal.Add(eu.FinalDiluted.Decimal).RoundBank(2),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 向数据库保存报表概况以及终端用户摊薄结果
|
||||
tx := global.DBConn.NewSession()
|
||||
if err = tx.Begin(); err != nil {
|
||||
return
|
||||
}
|
||||
defer tx.Close()
|
||||
|
||||
_, err = tx.ID(reportId).Update(summary)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
for _, eu := range endUserDetails {
|
||||
_, err = tx.ID(schemas.NewPK(eu.ReportId, eu.ParkId, eu.MeterId)).Update(eu)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
Loading…
Reference in New Issue
Block a user