forked from free-lancers/electricity_bill_calc_service
745 lines
24 KiB
Go
745 lines
24 KiB
Go
package service
|
|
|
|
import (
|
|
"database/sql"
|
|
"electricity_bill_calc/cache"
|
|
"electricity_bill_calc/config"
|
|
"electricity_bill_calc/exceptions"
|
|
"electricity_bill_calc/global"
|
|
"electricity_bill_calc/logger"
|
|
"electricity_bill_calc/model"
|
|
"electricity_bill_calc/tools"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/fufuok/utils"
|
|
"github.com/google/uuid"
|
|
"github.com/samber/lo"
|
|
"github.com/shopspring/decimal"
|
|
"github.com/uptrace/bun"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type _ReportService struct {
|
|
l *zap.Logger
|
|
}
|
|
|
|
var ReportService = _ReportService{
|
|
l: logger.Named("Service", "Report"),
|
|
}
|
|
|
|
func (_ReportService) FetchParksWithNewestReport(uid string) ([]model.ParkNewestReport, error) {
|
|
if cachedParks, _ := cache.RetreiveSearch[[]model.ParkNewestReport]("park_newest_report", uid); cachedParks != nil {
|
|
return *cachedParks, nil
|
|
}
|
|
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
parks := make([]model.Park, 0)
|
|
err := global.DB.NewSelect().Model(&parks).Relation("Reports").
|
|
Where("user_id = ?", uid).
|
|
Where("enabled = ?", true).
|
|
Order("created_at asc").
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return make([]model.ParkNewestReport, 0), err
|
|
}
|
|
|
|
reducedParks := lo.Reduce(
|
|
parks,
|
|
func(acc map[string]model.ParkNewestReport, elem model.Park, index int) map[string]model.ParkNewestReport {
|
|
if _, ok := acc[elem.Id]; !ok {
|
|
newestReport := lo.MaxBy(elem.Reports, func(a, b *model.Report) bool {
|
|
return a.Period.After(b.Period)
|
|
})
|
|
acc[elem.Id] = model.ParkNewestReport{
|
|
Report: newestReport,
|
|
Park: elem,
|
|
}
|
|
}
|
|
return acc
|
|
},
|
|
make(map[string]model.ParkNewestReport, 0),
|
|
)
|
|
relations := lo.Map(parks, func(r model.Park, _ int) string {
|
|
return fmt.Sprintf("park:%s", r.Id)
|
|
})
|
|
relations = append(relations, "park", "report")
|
|
cache.CacheSearch(reducedParks, relations, "park_newest_report", uid)
|
|
return lo.Values(reducedParks), nil
|
|
}
|
|
|
|
func (_ReportService) IsNewPeriodValid(uid, pid string, period time.Time) (bool, error) {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
reports := make([]model.Report, 0)
|
|
if cachedReport, _ := cache.RetreiveSearch[[]model.Report]("report", "user", uid, "park", pid); cachedReport != nil {
|
|
reports = *cachedReport
|
|
} else {
|
|
err := global.DB.NewSelect().Model(&reports).Relation("Park").
|
|
Where("park.user_id = ?", uid).
|
|
Where("r.park_id = ?", pid).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
cache.CacheSearch(reports, []string{"report", "park"}, "park", "user", uid, "park", pid)
|
|
}
|
|
// 检查给定的期数在目前的记录中是否已经存在
|
|
exists := lo.Reduce(
|
|
reports,
|
|
func(acc bool, elem model.Report, index int) bool {
|
|
if elem.Period.Equal(period) {
|
|
return acc || true
|
|
} else {
|
|
return acc || false
|
|
}
|
|
},
|
|
false,
|
|
)
|
|
if exists {
|
|
return false, nil
|
|
}
|
|
// 检查给定的期数与目前已发布的最大期数的关系
|
|
maxPublished := lo.Reduce(
|
|
reports,
|
|
func(acc *time.Time, elem model.Report, index int) *time.Time {
|
|
if elem.Published {
|
|
if acc == nil || (acc != nil && elem.Period.After(*acc)) {
|
|
return &elem.Period
|
|
}
|
|
}
|
|
return acc
|
|
},
|
|
nil,
|
|
)
|
|
// 检查给定的期数与目前未发布的最大期数的关系
|
|
maxUnpublished := lo.Reduce(
|
|
reports,
|
|
func(acc *time.Time, elem model.Report, index int) *time.Time {
|
|
if acc == nil || (acc != nil && elem.Period.After(*acc)) {
|
|
return &elem.Period
|
|
}
|
|
return acc
|
|
},
|
|
nil,
|
|
)
|
|
if maxUnpublished == nil {
|
|
return true, nil
|
|
}
|
|
if maxPublished != nil && maxUnpublished.Equal(*maxPublished) {
|
|
// 此时不存在未发布的报表
|
|
return tools.IsNextMonth(*maxPublished, period), nil
|
|
} else {
|
|
// 存在未发布的报表
|
|
return false, nil
|
|
}
|
|
}
|
|
|
|
func (_ReportService) InitializeNewReport(parkId string, period time.Time) (string, error) {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
periods := make([]model.Report, 0)
|
|
err := global.DB.NewSelect().Model(&periods).
|
|
Where("park_id = ?", parkId).
|
|
Where("published = ?", true).
|
|
Order("period asc").
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
// 获取上一期的报表索引信息
|
|
maxPublishedReport := lo.Reduce(
|
|
periods,
|
|
func(acc *model.Report, elem model.Report, index int) *model.Report {
|
|
if acc == nil || (acc != nil && elem.Period.After(acc.Period)) {
|
|
return &elem
|
|
}
|
|
return acc
|
|
},
|
|
nil,
|
|
)
|
|
var indexedLastPeriodCustomers map[string]model.EndUserDetail
|
|
if maxPublishedReport != nil {
|
|
// 获取上一期的所有户表信息,并获取当前已启用的所有用户
|
|
lastPeriodCustomers := make([]model.EndUserDetail, 0)
|
|
err = global.DB.NewSelect().Model(&lastPeriodCustomers).
|
|
Where("report_id = ?", maxPublishedReport.Id).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
indexedLastPeriodCustomers = lo.Reduce(
|
|
lastPeriodCustomers,
|
|
func(acc map[string]model.EndUserDetail, elem model.EndUserDetail, index int) map[string]model.EndUserDetail {
|
|
acc[elem.MeterId] = elem
|
|
return acc
|
|
},
|
|
make(map[string]model.EndUserDetail, 0),
|
|
)
|
|
} else {
|
|
indexedLastPeriodCustomers = make(map[string]model.EndUserDetail, 0)
|
|
}
|
|
currentActivatedCustomers := make([]model.Meter04KV, 0)
|
|
err = global.DB.NewSelect().Model(¤tActivatedCustomers).
|
|
Where("park_id = ?", parkId).
|
|
Where("enabled = ?", true).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var parkInfo = new(model.Park)
|
|
err = global.DB.NewSelect().Model(parkInfo).
|
|
Where("id = ?", parkId).
|
|
Scan(ctx)
|
|
if err != nil || parkInfo == nil {
|
|
return "", exceptions.NewNotFoundError(fmt.Sprintf("指定园区未找到, %v", err))
|
|
}
|
|
// 生成新一期的报表
|
|
tx, err := global.DB.BeginTx(ctx, &sql.TxOptions{})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
// 插入已经生成的报表索引信息和园区概况信息
|
|
newReport := model.Report{
|
|
Id: uuid.New().String(),
|
|
ParkId: parkId,
|
|
Period: period,
|
|
Category: parkInfo.Category,
|
|
SubmeterType: parkInfo.SubmeterType,
|
|
StepState: model.NewSteps(),
|
|
Published: false,
|
|
Withdraw: model.REPORT_NOT_WITHDRAW,
|
|
}
|
|
newReportSummary := model.ReportSummary{
|
|
ReportId: newReport.Id,
|
|
}
|
|
_, err = tx.NewInsert().Model(&newReport).Exec(ctx)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return "", err
|
|
}
|
|
_, err = tx.NewInsert().Model(&newReportSummary).Exec(ctx)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return "", err
|
|
}
|
|
// 生成并插入户表信息
|
|
for _, customer := range currentActivatedCustomers {
|
|
newEndUser := model.EndUserDetail{
|
|
ReportId: newReport.Id,
|
|
ParkId: parkId,
|
|
MeterId: customer.Code,
|
|
Seq: customer.Seq,
|
|
Ratio: customer.Ratio,
|
|
Address: customer.Address,
|
|
CustomerName: customer.CustomerName,
|
|
ContactName: customer.ContactName,
|
|
ContactPhone: customer.ContactPhone,
|
|
IsPublicMeter: customer.IsPublicMeter,
|
|
WillDilute: customer.WillDilute,
|
|
LastPeriodOverall: decimal.Zero,
|
|
LastPeriodCritical: decimal.Zero,
|
|
LastPeriodPeak: decimal.Zero,
|
|
LastPeriodFlat: decimal.Zero,
|
|
LastPeriodValley: decimal.Zero,
|
|
}
|
|
if lastPeriod, ok := indexedLastPeriodCustomers[customer.Code]; ok {
|
|
newEndUser.LastPeriodOverall = lastPeriod.CurrentPeriodOverall
|
|
newEndUser.LastPeriodCritical = lastPeriod.CurrentPeriodCritical
|
|
newEndUser.LastPeriodPeak = lastPeriod.CurrentPeriodPeak
|
|
newEndUser.LastPeriodFlat = lastPeriod.CurrentPeriodFlat
|
|
newEndUser.LastPeriodValley = lastPeriod.CurrentPeriodValley
|
|
}
|
|
_, err = tx.NewInsert().Model(&newEndUser).Exec(ctx)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return "", err
|
|
}
|
|
}
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return "", err
|
|
}
|
|
cache.AbolishRelation("report")
|
|
return newReport.Id, nil
|
|
}
|
|
|
|
func (_ReportService) RetreiveReportIndex(rid string) (*model.Report, error) {
|
|
if cachedReport, _ := cache.RetreiveEntity[model.Report]("report", rid); cachedReport != nil {
|
|
return cachedReport, nil
|
|
}
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
var report = new(model.Report)
|
|
err := global.DB.NewSelect().Model(report).
|
|
Where("id = ?", rid).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cache.CacheEntity(report, []string{fmt.Sprintf("report:%s", rid), "park"}, "report", rid)
|
|
return report, nil
|
|
}
|
|
|
|
func (_ReportService) RetreiveReportSummary(rid string) (*model.ReportSummary, error) {
|
|
if cachedSummary, _ := cache.RetreiveEntity[model.ReportSummary]("report_summary", rid); cachedSummary != nil {
|
|
return cachedSummary, nil
|
|
}
|
|
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
var summary = new(model.ReportSummary)
|
|
err := global.DB.NewSelect().Model(summary).
|
|
Where("report_id = ?", rid).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cache.CacheEntity(summary, []string{fmt.Sprintf("report:%s", rid), "park"}, "report_summary", rid)
|
|
return summary, nil
|
|
}
|
|
|
|
func (_ReportService) UpdateReportSummary(summary *model.ReportSummary) error {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
_, err := global.DB.NewUpdate().Model(summary).
|
|
WherePK().
|
|
Column("overall", "overall_fee", "critical", "critical_fee", "peak", "peak_fee", "valley", "valley_fee", "basic_fee", "adjust_fee").
|
|
Exec(ctx)
|
|
if err == nil {
|
|
cache.AbolishRelation(fmt.Sprintf("report:%s", summary.ReportId))
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (_ReportService) CalculateSummaryAndFinishStep(reportId string) error {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
var report = new(model.Report)
|
|
err := global.DB.NewSelect().Model(report).Relation("Summary").
|
|
Where("r.id = ?", reportId).
|
|
Scan(ctx)
|
|
if err != nil || report == nil {
|
|
return exceptions.NewNotFoundErrorFromError("未找到指定报表", err)
|
|
}
|
|
|
|
tx, err := global.DB.BeginTx(ctx, &sql.TxOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
report.Summary.CalculatePrices()
|
|
_, err = tx.NewUpdate().Model(report.Summary).
|
|
WherePK().
|
|
Column("overall_price", "critical_price", "peak_price", "flat", "flat_fee", "flat_price", "valley_price", "consumption_fee").
|
|
Exec(ctx)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
report.StepState.Summary = true
|
|
_, err = tx.NewUpdate().Model(report).
|
|
WherePK().
|
|
Column("step_state").
|
|
Exec(ctx)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
cache.AbolishRelation(fmt.Sprintf("report:%s", reportId))
|
|
return nil
|
|
}
|
|
|
|
func (_ReportService) FetchWillDulutedMaintenanceFees(reportId string) ([]model.WillDilutedFee, error) {
|
|
if cachedFees, _ := cache.RetreiveSearch[[]model.WillDilutedFee]("will_diluted_fee", "report", reportId); cachedFees != nil {
|
|
return *cachedFees, nil
|
|
}
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
fees := make([]model.WillDilutedFee, 0)
|
|
err := global.DB.NewSelect().Model(&fees).
|
|
Where("report_id = ?", reportId).
|
|
Order("created_at asc").
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return make([]model.WillDilutedFee, 0), nil
|
|
}
|
|
relations := lo.Map(fees, func(f model.WillDilutedFee, _ int) string {
|
|
return fmt.Sprintf("will_diluted_fee:%s", f.Id)
|
|
})
|
|
relations = append(relations, fmt.Sprintf("report:will_diluted_fee:%s", reportId), fmt.Sprintf("report:%s", reportId), "park")
|
|
cache.CacheSearch(fees, relations, "will_diluted_fee", "report", reportId)
|
|
return fees, nil
|
|
}
|
|
|
|
func (_ReportService) CreateTemporaryWillDilutedMaintenanceFee(fee model.WillDilutedFee) error {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
fee.Id = utils.UUIDString()
|
|
_, err := global.DB.NewInsert().Model(&fee).Exec(ctx)
|
|
cache.AbolishRelation(fmt.Sprintf("report:will_diluted_fee:%s", fee.ReportId))
|
|
return err
|
|
}
|
|
|
|
func (_ReportService) BatchSaveMaintenanceFee(reportId string, fees []model.WillDilutedFee) error {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
tx, err := global.DB.BeginTx(ctx, &sql.TxOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// 首先删除所有预定义的部分,条件是指定报表ID,SourceID不为空。
|
|
_, err = tx.NewDelete().Model((*model.WillDilutedFee)(nil)).
|
|
Where("report_id = ?", reportId).
|
|
Where("source_id is not null").
|
|
Exec(ctx)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
// 然后插入新的记录
|
|
_, err = tx.NewInsert().Model(&fees).Exec(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
cache.AbolishRelation(fmt.Sprintf("report:will_diluted_fee:%s", reportId))
|
|
return nil
|
|
}
|
|
|
|
func (_ReportService) UpdateMaintenanceFee(feeId string, updates map[string]interface{}) (err error) {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
updates["last_modified_at"] = lo.ToPtr(time.Now())
|
|
_, err = global.DB.NewUpdate().Model(&updates).TableExpr("will_diluted_fee").
|
|
Where("id = ?", feeId).
|
|
Exec(ctx)
|
|
cache.AbolishRelation(fmt.Sprintf("will_diluted_fee:%s", feeId))
|
|
return
|
|
}
|
|
|
|
func (_ReportService) DeleteWillDilutedFee(fee string) (err error) {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
_, err = global.DB.NewDelete().Model((*model.WillDilutedFee)(nil)).
|
|
Where("id = ?", fee).
|
|
Exec(ctx)
|
|
cache.AbolishRelation(fmt.Sprintf("will_diluted_fee:%s", fee))
|
|
return
|
|
}
|
|
|
|
func (_ReportService) ProgressReportWillDilutedFee(report model.Report) (err error) {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
report.StepState.WillDiluted = true
|
|
_, err = global.DB.NewUpdate().Model(&report).
|
|
WherePK().
|
|
Column("step_state").
|
|
Exec(ctx)
|
|
cache.AbolishRelation(fmt.Sprintf("report:%s", report.Id))
|
|
return
|
|
}
|
|
|
|
func (_ReportService) ProgressReportRegisterEndUser(report model.Report) (err error) {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
report.StepState.Submeter = true
|
|
_, err = global.DB.NewUpdate().Model(&report).
|
|
WherePK().
|
|
Column("step_state").
|
|
Exec(ctx)
|
|
cache.AbolishRelation(fmt.Sprintf("report:%s", report.Id))
|
|
return
|
|
}
|
|
|
|
func (_ReportService) ProgressReportCalculate(report model.Report) (err error) {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
report.StepState.Calculate = true
|
|
_, err = global.DB.NewUpdate().Model(&report).
|
|
WherePK().
|
|
Column("step_state").
|
|
Exec(ctx)
|
|
cache.AbolishRelation(fmt.Sprintf("report:%s", report.Id))
|
|
return
|
|
}
|
|
|
|
func (_ReportService) RetreiveParkEndUserMeterType(reportId string) (int, error) {
|
|
if cachedType, _ := cache.RetreiveEntity[int]("park_end_user_meter_type", fmt.Sprintf("report_%s", reportId)); cachedType != nil {
|
|
return *cachedType, nil
|
|
}
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
var mType int
|
|
err := global.DB.NewSelect().Model((*model.Report)(nil)).
|
|
Relation("Park", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Column("meter_04kv_type")
|
|
}).
|
|
ExcludeColumn("*").
|
|
Where("r.id = ?", reportId).
|
|
Scan(ctx, &mType)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
cache.CacheEntity(mType, []string{fmt.Sprintf("report:%s", reportId), "park"}, "park_end_user_meter_type", fmt.Sprintf("report_%s", reportId))
|
|
return mType, nil
|
|
}
|
|
|
|
func (_ReportService) PublishReport(report model.Report) (err error) {
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
report.Published = true
|
|
report.PublishedAt = lo.ToPtr(time.Now())
|
|
report.StepState.Publish = true
|
|
_, err = global.DB.NewUpdate().Model(&report).
|
|
WherePK().
|
|
Column("step_state", "published", "published_at").
|
|
Exec(ctx)
|
|
cache.AbolishRelation(fmt.Sprintf("report:%s", report.Id))
|
|
return
|
|
}
|
|
|
|
func (_ReportService) SearchReport(requestUser, requestPark, requestKeyword string, requestPeriod *time.Time, requestPage int, onlyPublished bool) ([]model.JoinedReportForWithdraw, int64, error) {
|
|
var (
|
|
conditions = make([]string, 0)
|
|
reports = make([]model.Report, 0)
|
|
cond = global.DB.NewSelect().
|
|
Model(&reports).
|
|
Relation("Park", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Relation("Enterprise")
|
|
})
|
|
)
|
|
conditions = append(conditions, strconv.Itoa(requestPage))
|
|
if onlyPublished {
|
|
cond = cond.Where("r.published = ?", true)
|
|
}
|
|
conditions = append(conditions, strconv.FormatBool(onlyPublished))
|
|
if len(requestUser) > 0 {
|
|
cond = cond.Where("p.user_id = ?", requestUser)
|
|
conditions = append(conditions, requestUser)
|
|
}
|
|
if len(requestPark) > 0 {
|
|
cond = cond.Where("p.id = ?", requestPark)
|
|
conditions = append(conditions, requestPark)
|
|
}
|
|
if requestPeriod != nil {
|
|
cond = cond.Where("r.period = ?", *requestPeriod)
|
|
conditions = append(conditions, strconv.FormatInt(requestPeriod.Unix(), 10))
|
|
}
|
|
if len(requestKeyword) > 0 {
|
|
keywordCond := "%" + requestKeyword + "%"
|
|
cond = cond.WhereGroup(" and ", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Where("p.name like ?", keywordCond).
|
|
WhereOr("d.name like ?", keywordCond).
|
|
WhereOr("d.abbr like ?", keywordCond).
|
|
WhereOr("p.abbr like ?", keywordCond).
|
|
WhereOr("d.address like ?", keywordCond).
|
|
WhereOr("p.address like ?", keywordCond)
|
|
})
|
|
conditions = append(conditions, requestKeyword)
|
|
}
|
|
if cachedTotal, err := cache.RetreiveCount("join_report_for_withdraw", conditions...); cachedTotal != -1 && err == nil {
|
|
if cachedRecords, _ := cache.RetreiveSearch[[]model.JoinedReportForWithdraw]("join_report_for_withdraw", conditions...); cachedRecords != nil {
|
|
return *cachedRecords, cachedTotal, nil
|
|
}
|
|
}
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
startItem := (requestPage - 1) * config.ServiceSettings.ItemsPageSize
|
|
|
|
total, err := cond.Limit(config.ServiceSettings.ItemsPageSize).
|
|
Offset(startItem).
|
|
ScanAndCount(ctx)
|
|
|
|
records := make([]model.JoinedReportForWithdraw, 0)
|
|
relations := []string{"report", "park"}
|
|
for _, r := range reports {
|
|
records = append(records, model.JoinedReportForWithdraw{
|
|
Report: r,
|
|
Park: model.FromPark(*r.Park),
|
|
User: model.FromUserDetail(*r.Park.Enterprise),
|
|
})
|
|
relations = append(relations, fmt.Sprintf("report:%s", r.Id))
|
|
}
|
|
|
|
cache.CacheCount(relations, "join_report_for_withdraw", int64(total), conditions...)
|
|
cache.CacheSearch(records, relations, "join_report_for_withdraw", conditions...)
|
|
return records, int64(total), err
|
|
}
|
|
|
|
func (_ReportService) AssembleReportPublicity(reportId string) (*model.Publicity, error) {
|
|
if cachedPublicity, _ := cache.RetreiveEntity[model.Publicity]("publicity", reportId); cachedPublicity != nil {
|
|
return cachedPublicity, nil
|
|
}
|
|
// 资料准备
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
var report = new(model.Report)
|
|
err := global.DB.NewSelect().Model(report).
|
|
Relation("Summary").Relation("WillDilutedFees").Relation("EndUsers").
|
|
Relation("Park").
|
|
Where("r.id = ?", reportId).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, exceptions.NewNotFoundErrorFromError("未找到指定的公示报表", err)
|
|
}
|
|
var enterprise = new(model.UserDetail)
|
|
err = global.DB.NewSelect().Model(enterprise).
|
|
Where("id = ?", report.Park.UserId).
|
|
Scan(ctx)
|
|
if err != nil {
|
|
return nil, exceptions.NewNotFoundErrorFromError("未找到指定公示报表对应的用户信息", err)
|
|
}
|
|
|
|
// 组合数据
|
|
paidPart := model.PaidPart{
|
|
Overall: report.Summary.Overall,
|
|
OverallPrice: report.Summary.OverallPrice.Decimal,
|
|
ConsumptionFee: report.Summary.ConsumptionFee.Decimal,
|
|
OverallFee: report.Summary.OverallFee,
|
|
Critical: decimal.NewNullDecimal(report.Summary.Critical),
|
|
CriticalPrice: report.Summary.CriticalPrice,
|
|
CriticalFee: decimal.NewNullDecimal(report.Summary.CriticalFee),
|
|
Peak: decimal.NewNullDecimal(report.Summary.Peak),
|
|
PeakPrice: report.Summary.PeakPrice,
|
|
PeakFee: decimal.NewNullDecimal(report.Summary.PeakFee),
|
|
Flat: decimal.NewNullDecimal(report.Summary.Flat),
|
|
FlatPrice: report.Summary.FlatPrice,
|
|
FlatFee: decimal.NewNullDecimal(report.Summary.FlatFee),
|
|
Valley: decimal.NewNullDecimal(report.Summary.Valley),
|
|
ValleyPrice: report.Summary.ValleyPrice,
|
|
ValleyFee: decimal.NewNullDecimal(report.Summary.ValleyFee),
|
|
BasicFee: report.Summary.BasicFee,
|
|
AdjustFee: report.Summary.AdjustFee,
|
|
}
|
|
endUserSummary := model.EndUserOverallPart{
|
|
Overall: report.Summary.CustomerConsumption.Decimal,
|
|
OverallPrice: report.Summary.OverallPrice.Decimal,
|
|
OverallFee: report.Summary.CustomerConsumptionFee.Decimal,
|
|
Critical: report.Summary.CustomerConsumptionCritical,
|
|
CriticalPrice: report.Summary.CriticalPrice,
|
|
CriticalFee: report.Summary.CustomerConsumptionCriticalFee,
|
|
Peak: report.Summary.CustomerConsumptionPeak,
|
|
PeakPrice: report.Summary.PeakPrice,
|
|
PeakFee: report.Summary.CustomerConsumptionPeakFee,
|
|
Flat: report.Summary.CustomerConsumptionFlat,
|
|
FlatPrice: report.Summary.FlatPrice,
|
|
FlatFee: report.Summary.CustomerConsumptionFlatFee,
|
|
Valley: report.Summary.CustomerConsumptionValley,
|
|
ValleyPrice: report.Summary.ValleyPrice,
|
|
ValleyFee: report.Summary.CustomerConsumptionValleyFee,
|
|
}
|
|
lossPart := model.LossPart{
|
|
Quantity: report.Summary.Loss.Decimal,
|
|
Price: report.Summary.OverallPrice.Decimal,
|
|
ConsumptionFee: report.Summary.LossFee.Decimal,
|
|
Proportion: report.Summary.LossProportion.Decimal,
|
|
}
|
|
publicSummary := model.PublicConsumptionOverallPart{
|
|
Overall: report.Summary.PublicConsumption.Decimal,
|
|
OverallPrice: report.Summary.OverallPrice.Decimal,
|
|
ConsumptionFee: report.Summary.PublicConsumptionFee.Decimal,
|
|
OverallFee: report.Summary.PublicConsumptionFee.Decimal,
|
|
Critical: report.Summary.PublicConsumptionCritical,
|
|
CriticalPrice: report.Summary.CriticalPrice,
|
|
CriticalFee: report.Summary.PublicConsumptionCriticalFee,
|
|
Peak: report.Summary.PublicConsumptionPeak,
|
|
PeakPrice: report.Summary.PeakPrice,
|
|
PeakFee: report.Summary.PublicConsumptionPeakFee,
|
|
Flat: report.Summary.PublicConsumptionFlat,
|
|
FlatPrice: report.Summary.FlatPrice,
|
|
FlatFee: report.Summary.PublicConsumptionFlatFee,
|
|
Valley: report.Summary.PublicConsumptionValley,
|
|
ValleyPrice: report.Summary.ValleyPrice,
|
|
ValleyFee: report.Summary.PublicConsumptionValleyFee,
|
|
Proportion: report.Summary.PublicConsumptionProportion.Decimal,
|
|
}
|
|
otherCollection := model.OtherShouldCollectionPart{
|
|
MaintenanceFee: report.Summary.MaintenanceOverall,
|
|
BasicFees: report.Summary.BasicFee.Add(report.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 !report.Summary.OverallPrice.Decimal.Equal(decimal.Zero) {
|
|
priceRatio = maintenancePrice.Div(report.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(
|
|
report.EndUsers,
|
|
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,
|
|
}
|
|
},
|
|
)
|
|
|
|
publicity := &model.Publicity{
|
|
Report: *report,
|
|
Park: *report.Park,
|
|
User: *enterprise,
|
|
Paid: paidPart,
|
|
EndUser: endUserSummary,
|
|
Loss: lossPart,
|
|
PublicConsumptionOverall: publicSummary,
|
|
OtherCollections: otherCollection,
|
|
Maintenance: maintenanceFees,
|
|
EndUserDetails: endUsers,
|
|
}
|
|
cache.CacheEntity(publicity, []string{fmt.Sprintf("publicity:%s", reportId), fmt.Sprintf("report:%s", reportId), "report", "park"}, "publicity", reportId)
|
|
|
|
return publicity, nil
|
|
}
|