diff --git a/controller/report.go b/controller/report.go index 804acbc..5e31558 100644 --- a/controller/report.go +++ b/controller/report.go @@ -36,6 +36,7 @@ func InitializeReportController(router *gin.Engine) { router.PUT("/report/:rid/step/meter/register", security.EnterpriseAuthorize, progressEndUserRegister) router.POST("/report/:rid/publish", security.EnterpriseAuthorize, publishReport) router.GET("/reports", security.MustAuthenticated, searchReports) + router.GET("/report/:rid", security.MustAuthenticated, fetchReportPublicity) } func ensureReportBelongs(c *gin.Context, result *response.Result, requestReportId string) bool { @@ -444,3 +445,19 @@ func searchReports(c *gin.Context) { gin.H{"reports": records}, ) } + +func fetchReportPublicity(c *gin.Context) { + result := response.NewResult(c) + requestReportId := c.Param("rid") + publicity, err := service.ReportService.AssembleReportPublicity(requestReportId) + if err != nil { + if nfErr, ok := err.(exceptions.NotFoundError); ok { + result.NotFound(nfErr.Error()) + return + } else { + result.Error(http.StatusInternalServerError, err.Error()) + return + } + } + result.Success("已经取得指定公示报表的发布版本。", tools.ConvertStructToMap(publicity)) +} diff --git a/exceptions/not_found.go b/exceptions/not_found.go index eb9053a..14065ba 100644 --- a/exceptions/not_found.go +++ b/exceptions/not_found.go @@ -1,5 +1,7 @@ package exceptions +import "fmt" + type NotFoundError struct { Message string } @@ -8,6 +10,10 @@ func NewNotFoundError(msg string) *NotFoundError { return &NotFoundError{Message: msg} } +func NewNotFoundErrorFromError(msg string, err error) *NotFoundError { + return &NotFoundError{Message: fmt.Sprintf("%s,%v", msg, err)} +} + func (e NotFoundError) Error() string { return e.Message } diff --git a/model/publicity.go b/model/publicity.go new file mode 100644 index 0000000..e8ae92f --- /dev/null +++ b/model/publicity.go @@ -0,0 +1,113 @@ +package model + +import "github.com/shopspring/decimal" + +type PaidPart struct { + Overall decimal.Decimal `json:"overall"` + OverallPrice decimal.Decimal `json:"overallPrice"` + ConsumptionFee decimal.Decimal `json:"consumptionFee"` + OverallFee decimal.Decimal `json:"overallFee"` + Critical decimal.NullDecimal `json:"critical"` + CriticalPrice decimal.NullDecimal `json:"criticalPrice"` + CriticalFee decimal.NullDecimal `json:"criticalFee"` + Peak decimal.NullDecimal `json:"peak"` + PeakPrice decimal.NullDecimal `json:"peakPrice"` + PeakFee decimal.NullDecimal `json:"peakFee"` + Flat decimal.NullDecimal `json:"flat"` + FlatPrice decimal.NullDecimal `json:"flatPrice"` + FlatFee decimal.NullDecimal `json:"flatFee"` + Valley decimal.NullDecimal `json:"valley"` + ValleyPrice decimal.NullDecimal `json:"valleyPrice"` + ValleyFee decimal.NullDecimal `json:"valleyFee"` + BasicFee decimal.Decimal `json:"basicFee"` + AdjustFee decimal.Decimal `json:"adjustFee"` +} + +type EndUserOverallPart struct { + Overall decimal.Decimal `json:"overall"` + OverallPrice decimal.Decimal `json:"overallPrice"` + OverallFee decimal.Decimal `json:"overallFee"` + Critical decimal.NullDecimal `json:"critical"` + CriticalPrice decimal.NullDecimal `json:"criticalPrice"` + CriticalFee decimal.NullDecimal `json:"criticalFee"` + Peak decimal.NullDecimal `json:"peak"` + PeakPrice decimal.NullDecimal `json:"peakPrice"` + PeakFee decimal.NullDecimal `json:"peakFee"` + Flat decimal.NullDecimal `json:"flat"` + FlatPrice decimal.NullDecimal `json:"flatPrice"` + FlatFee decimal.NullDecimal `json:"flatFee"` + Valley decimal.NullDecimal `json:"valley"` + ValleyPrice decimal.NullDecimal `json:"valleyPrice"` + ValleyFee decimal.NullDecimal `json:"valleyFee"` +} + +type PublicConsumptionOverallPart struct { + Overall decimal.Decimal `json:"overall"` + OverallPrice decimal.Decimal `json:"overallPrice"` + ConsumptionFee decimal.Decimal `json:"consumptionFee"` + OverallFee decimal.Decimal `json:"overallFee"` + Critical decimal.NullDecimal `json:"critical"` + CriticalPrice decimal.NullDecimal `json:"criticalPrice"` + CriticalFee decimal.NullDecimal `json:"criticalFee"` + Peak decimal.NullDecimal `json:"peak"` + PeakPrice decimal.NullDecimal `json:"peakPrice"` + PeakFee decimal.NullDecimal `json:"peakFee"` + Flat decimal.NullDecimal `json:"flat"` + FlatPrice decimal.NullDecimal `json:"flatPrice"` + FlatFee decimal.NullDecimal `json:"flatFee"` + Valley decimal.NullDecimal `json:"valley"` + ValleyPrice decimal.NullDecimal `json:"valleyPrice"` + ValleyFee decimal.NullDecimal `json:"valleyFee"` + Proportion decimal.Decimal `json:"proportion"` +} + +type LossPart struct { + Quantity decimal.Decimal `json:"quantity"` + Price decimal.Decimal `json:"price"` + ConsumptionFee decimal.Decimal `json:"consumptionFee"` + Proportion decimal.Decimal `json:"proportion"` +} + +type OtherShouldCollectionPart struct { + MaintenanceFee decimal.NullDecimal `json:"maintenanceFee"` + BasicFees decimal.Decimal `json:"basicFees"` +} + +type MaintenancePart struct { + BasicFees decimal.Decimal `json:"basicFees"` + LossFee decimal.Decimal `json:"lossFee"` + PublicConsumptionFee decimal.Decimal `json:"publicConsumptionFee"` + MaintenanceFee decimal.Decimal `json:"maintenanceFee"` + FinalMaintenance decimal.Decimal `json:"finalMaintenance"` + MaintenanceProportion decimal.Decimal `json:"maintenanceProportion"` + MaintenancePrice decimal.Decimal `json:"maintenancePrice"` + PriceRatio decimal.Decimal `json:"priceRatio"` +} + +type EndUserSummary struct { + CustomerName *string `json:"customerName"` + Address *string `json:"address"` + MeterId string `json:"meterId"` + Overall decimal.Decimal `json:"overall"` + OverallFee decimal.Decimal `json:"overallFee"` + Critical decimal.NullDecimal `json:"critical"` + CriticalFee decimal.NullDecimal `json:"criticalFee"` + Peak decimal.NullDecimal `json:"peak"` + PeakFee decimal.NullDecimal `json:"peakFee"` + Valley decimal.NullDecimal `json:"valley"` + ValleyFee decimal.NullDecimal `json:"valleyFee"` + Maintenance decimal.Decimal `json:"maintenance"` +} + +type Publicity struct { + Report Report `json:"index"` + User UserDetail `json:"enterprise"` + Park Park `json:"park"` + Paid PaidPart `json:"paid"` + EndUser EndUserOverallPart `json:"endUserSum"` + Loss LossPart `json:"loss"` + PublicConsumptionOverall PublicConsumptionOverallPart `json:"public"` + OtherCollections OtherShouldCollectionPart `json:"other"` + Maintenance MaintenancePart `json:"maintenance"` + EndUserDetails []EndUserSummary `json:"endUser"` +} diff --git a/service/report.go b/service/report.go index 14d637c..ee1ab8b 100644 --- a/service/report.go +++ b/service/report.go @@ -430,3 +430,156 @@ func (_ReportService) SearchReport(requestUser, requestPark, requestKeyword stri Find(&records) return records, total, err } + +func (_ReportService) AssembleReportPublicity(reportId string) (*model.Publicity, error) { + // 资料准备 + var reportIndex = new(model.Report) + has, err := global.DBConn.ID(reportId).NoAutoCondition().Get(reportIndex) + if err != nil || !has { + return nil, exceptions.NewNotFoundErrorFromError("未找到指定的公示报表", err) + } + var summary = new(model.ReportSummary) + has, err = global.DBConn.ID(reportId).NoAutoCondition().Get(summary) + if err != nil || !has { + return nil, exceptions.NewNotFoundErrorFromError("未找到指定的公示报表概览", err) + } + var maintenanceFeeRecords = make([]model.WillDilutedFee, 0) + err = global.DBConn.Where(builder.Eq{"report_id": reportId}).Find(&maintenanceFeeRecords) + if err != nil { + return nil, exceptions.NewNotFoundErrorFromError("未能获取到公示报表对应的待摊薄费用信息", err) + } + var endUserDetails = make([]model.EndUserDetail, 0) + err = global.DBConn.Where(builder.Eq{"report_id": reportId}).Find(&endUserDetails) + if err != nil { + return nil, exceptions.NewNotFoundErrorFromError("未获取到公示报表对应的终端用户抄表信息", err) + } + parkDetail, err := ParkService.FetchParkDetail(reportIndex.ParkId) + if err != nil { + return nil, exceptions.NewNotFoundErrorFromError("未找到公示报表对应的园区信息", err) + } + userDetail, err := UserService.retreiveUserDetail(parkDetail.UserId) + if err != nil { + return nil, exceptions.NewNotFoundErrorFromError("未找到公示报表对应的企业信息", err) + } + + // 组合数据 + paidPart := model.PaidPart{ + Overall: summary.Overall, + OverallPrice: summary.OverallPrice.Decimal, + ConsumptionFee: summary.ConsumptionFee.Decimal, + OverallFee: summary.OverallFee, + Critical: decimal.NewNullDecimal(summary.Critical), + CriticalPrice: summary.CriticalPrice, + CriticalFee: decimal.NewNullDecimal(summary.CriticalFee), + Peak: decimal.NewNullDecimal(summary.Peak), + PeakPrice: summary.PeakPrice, + PeakFee: decimal.NewNullDecimal(summary.PeakFee), + Flat: decimal.NewNullDecimal(summary.Flat), + FlatPrice: summary.FlatPrice, + FlatFee: decimal.NewNullDecimal(summary.FlatFee), + Valley: decimal.NewNullDecimal(summary.Valley), + ValleyPrice: summary.ValleyPrice, + ValleyFee: decimal.NewNullDecimal(summary.ValleyFee), + BasicFee: summary.BasicFee, + AdjustFee: summary.AdjustFee, + } + endUserSummary := model.EndUserOverallPart{ + Overall: summary.CustomerConsumption.Decimal, + OverallPrice: summary.OverallPrice.Decimal, + OverallFee: summary.CustomerConsumptionFee.Decimal, + Critical: summary.CustomerConsumptionCritical, + CriticalPrice: summary.CriticalPrice, + CriticalFee: summary.CustomerConsumptionCriticalFee, + Peak: summary.CustomerConsumptionPeak, + PeakPrice: summary.PeakPrice, + PeakFee: summary.CustomerConsumptionPeakFee, + Flat: summary.CustomerConsumptionFlat, + FlatPrice: summary.FlatPrice, + FlatFee: summary.CustomerConsumptionFlatFee, + Valley: summary.CustomerConsumptionValley, + ValleyPrice: summary.ValleyPrice, + ValleyFee: summary.CustomerConsumptionValleyFee, + } + lossPart := model.LossPart{ + Quantity: summary.Loss.Decimal, + Price: summary.OverallPrice.Decimal, + ConsumptionFee: summary.LossFee.Decimal, + Proportion: summary.LossProportion.Decimal, + } + publicSummary := model.PublicConsumptionOverallPart{ + Overall: summary.PublicConsumption.Decimal, + OverallPrice: summary.OverallPrice.Decimal, + OverallFee: summary.PublicConsumptionFee.Decimal, + Critical: summary.PublicConsumptionCritical, + CriticalPrice: summary.CriticalPrice, + CriticalFee: summary.PublicConsumptionCriticalFee, + Peak: summary.PublicConsumptionPeak, + PeakPrice: summary.PeakPrice, + PeakFee: summary.PublicConsumptionPeakFee, + Flat: summary.PublicConsumptionFlat, + FlatPrice: summary.FlatPrice, + FlatFee: summary.PublicConsumptionFlatFee, + Valley: summary.PublicConsumptionValley, + ValleyPrice: summary.ValleyPrice, + ValleyFee: summary.PublicConsumptionValleyFee, + } + otherCollection := model.OtherShouldCollectionPart{ + MaintenanceFee: summary.FinalDilutedOverall, + BasicFees: summary.BasicFee.Add(summary.AdjustFee), + } + finalMaintenance := lossPart.ConsumptionFee.Add(publicSummary.ConsumptionFee).Add(otherCollection.MaintenanceFee.Decimal).Add(otherCollection.BasicFees) + var maintenancePrice = decimal.Zero + if !endUserSummary.Overall.Equal(decimal.Zero) { + maintenancePrice = finalMaintenance.Div(endUserSummary.Overall).RoundBank(8) + } + var maintenanceProportion = decimal.Zero + if !paidPart.OverallFee.Equal(decimal.Zero) || !otherCollection.MaintenanceFee.Decimal.Equal(decimal.Zero) { + maintenanceProportion = finalMaintenance.Div(paidPart.OverallFee.Add(otherCollection.MaintenanceFee.Decimal)).RoundBank(8) + } + var priceRatio = decimal.Zero + if !summary.OverallPrice.Decimal.Equal(decimal.Zero) { + priceRatio = maintenancePrice.Div(summary.OverallPrice.Decimal).RoundBank(8) + } + maintenanceFees := model.MaintenancePart{ + BasicFees: otherCollection.BasicFees, + LossFee: lossPart.ConsumptionFee, + PublicConsumptionFee: publicSummary.ConsumptionFee, + MaintenanceFee: otherCollection.MaintenanceFee.Decimal, + FinalMaintenance: finalMaintenance, + MaintenanceProportion: maintenanceProportion, + MaintenancePrice: maintenancePrice, + PriceRatio: priceRatio, + } + endUsers := lo.Map( + endUserDetails, + func(elem model.EndUserDetail, index int) model.EndUserSummary { + return model.EndUserSummary{ + CustomerName: elem.CustomerName, + Address: elem.Address, + MeterId: elem.MeterId, + Overall: elem.Overall.Decimal, + OverallFee: elem.OverallFee.Decimal, + Critical: elem.Critical, + CriticalFee: elem.CriticalFee, + Peak: elem.Peak, + PeakFee: elem.PeakFee, + Valley: elem.Valley, + ValleyFee: elem.ValleyFee, + Maintenance: elem.FinalDiluted.Decimal, + } + }, + ) + + return &model.Publicity{ + Report: *reportIndex, + Park: *parkDetail, + User: *userDetail, + Paid: paidPart, + EndUser: endUserSummary, + Loss: lossPart, + PublicConsumptionOverall: publicSummary, + OtherCollections: otherCollection, + Maintenance: maintenanceFees, + EndUserDetails: endUsers, + }, nil +}