electricity_bill_calc_service/controller/report.go

455 lines
19 KiB
Go

package controller
import (
"electricity_bill_calc/logger"
"electricity_bill_calc/model"
"electricity_bill_calc/repository"
"electricity_bill_calc/response"
"electricity_bill_calc/security"
"electricity_bill_calc/service"
"electricity_bill_calc/tools"
"electricity_bill_calc/types"
"electricity_bill_calc/vo"
"log"
"strconv"
"github.com/gofiber/fiber/v2"
"github.com/jinzhu/copier"
"github.com/samber/lo"
"go.uber.org/zap"
)
var reportLog = logger.Named("Handler", "Report")
func InitializeReportHandlers(router *fiber.App) {
router.Get("/reports", security.MustAuthenticated, reportComprehensiveSearch)
router.Post("/report", security.EnterpriseAuthorize, initNewReportCalculateTask)
router.Get("/report/draft", security.EnterpriseAuthorize, listDraftReportIndicies)
router.Post("/report/calcualte", security.EnterpriseAuthorize, testCalculateReportSummary)
//TODO: 2023-07-20将calcualte错误请求改为正确的calculate请求
router.Post("/report/calculate", security.EnterpriseAuthorize, testCalculateReportSummary)
router.Get("/report/calculate/status", security.EnterpriseAuthorize, listCalculateTaskStatus)
router.Get("/report/:rid", security.EnterpriseAuthorize, getReportDetail)
router.Put("/report/:rid", security.EnterpriseAuthorize, updateReportCalculateTask)
router.Post("/report/:rid/publish", security.EnterpriseAuthorize, publishReport)
router.Put("/report/:rid/calculate", security.EnterpriseAuthorize, initiateCalculateTask)
router.Get("/report/:rid/publics", security.MustAuthenticated, listPublicMetersInReport)
router.Get("/report/:rid/summary", security.MustAuthenticated, getReportSummary)
router.Get("/report/:rid/summary/filled", security.EnterpriseAuthorize, getParkFilledSummary)
router.Get("/report/:rid/pooled", security.MustAuthenticated, listPooledMetersInReport)
router.Get("/report/:rid/pooled/:code/submeter", security.MustAuthenticated, listSubmetersInPooledMeter)
router.Get("/report/:rid/tenement", security.MustAuthenticated, listTenementsInReport)
router.Get("/report/:rid/tenement/:tid", security.MustAuthenticated, getTenementDetailInReport)
}
// 检查指定报表是否属于当前用户
func checkReportBelongs(reportId string, log *zap.Logger, c *fiber.Ctx, result *response.Result) (bool, error) {
session, err := _retreiveSession(c)
if err != nil {
log.Error("无法获取当前用户的会话信息", zap.Error(err))
return false, result.Unauthorized("无法获取当前用户的会话信息。")
}
ok, err := repository.ReportRepository.IsBelongsTo(reportId, session.Uid)
if err != nil {
log.Error("无法检查核算报表的所有权", zap.Error(err))
return false, result.Error(fiber.StatusInternalServerError, "无法检查核算报表的所有权。")
}
if !ok {
log.Error("核算报表不属于当前用户")
return false, result.Forbidden("核算报表不属于当前用户。")
}
return true, nil
}
// 获取当前登录用户下所有园区的尚未发布的核算报表索引
func listDraftReportIndicies(c *fiber.Ctx) error {
result := response.NewResult(c)
session, err := _retreiveSession(c)
if err != nil {
reportLog.Error("无法获取当前用户的会话信息", zap.Error(err))
return result.Unauthorized("无法获取当前用户的会话信息。")
}
reportLog.Info("检索指定用户下的未发布核算报表索引", zap.String("User", session.Uid))
indicies, err := service.ReportService.ListDraftReportIndicies(session.Uid)
if err != nil {
reportLog.Error("无法获取当前用户的核算报表索引", zap.Error(err))
return result.NotFound("当前用户下未找到核算报表索引。")
}
return result.Success(
"已经获取到指定用户的报表索引。",
fiber.Map{"reports": indicies},
)
}
// 初始化一个新的核算任务
func initNewReportCalculateTask(c *fiber.Ctx) error {
result := response.NewResult(c)
session, err := _retreiveSession(c)
if err != nil {
reportLog.Error("无法获取当前用户的会话信息", zap.Error(err))
return result.Unauthorized("无法获取当前用户的会话信息。")
}
reportLog.Info("初始化指定用户的一个新核算任务", zap.String("User", session.Uid))
var form vo.ReportCreationForm
if err := c.BodyParser(&form); err != nil {
reportLog.Error("无法解析创建核算报表的请求数据。", zap.Error(err))
return result.BadRequest("无法解析创建核算报表的请求数据。")
}
if pass, err := checkParkBelongs(form.Park, reportLog, c, &result); !pass {
return err
}
ok, err := service.ReportService.CreateNewReport(&form)
log.Println("??????????????????????kkkkkkkkkkkkkkkkkkkkkkkkk", ok)
if err != nil {
reportLog.Error("无法创建核算报表", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法创建核算报表。")
}
if !ok {
reportLog.Error("未能完成核算报表的保存。")
return result.NotAccept("未能完成核算报表的保存。")
}
return result.Success("已经成功创建核算报表。")
}
// 更新指定的核算任务
func updateReportCalculateTask(c *fiber.Ctx) error {
result := response.NewResult(c)
reportId := c.Params("rid")
if pass, err := checkReportBelongs(reportId, reportLog, c, &result); !pass {
return err
}
var form vo.ReportModifyForm
if err := c.BodyParser(&form); err != nil {
reportLog.Error("无法解析更新核算报表的请求数据。", zap.Error(err))
return result.BadRequest("无法解析更新核算报表的请求数据。")
}
ok, err := service.ReportService.UpdateRepoet(reportId, &form)
if err != nil {
reportLog.Error("无法更新核算报表", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法更新核算报表。")
}
if !ok {
reportLog.Error("未能完成核算报表的更新。")
return result.NotAccept("未能完成核算报表的更新。")
}
return result.Success("已经成功更新核算报表。")
}
// 启动指定的核算任务
func initiateCalculateTask(c *fiber.Ctx) error {
result := response.NewResult(c)
reportId := c.Params("rid")
if pass, err := checkReportBelongs(reportId, reportLog, c, &result); !pass {
return err
}
err := service.ReportService.DispatchReportCalculate(reportId)
if err != nil {
reportLog.Error("无法启动核算报表计算任务", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法启动核算报表计算任务。")
}
//开启核算任务
err = service.ReportService.ReportCalcuateDispatch(reportId)
if err != nil {
return result.Error(500, "核算任务启动失败"+err.Error())
}
return result.Success("已经成功启动核算报表计算任务。")
}
// 获取自己园区的已经填写的园区电量信息
func getParkFilledSummary(c *fiber.Ctx) error {
result := response.NewResult(c)
reportId := c.Params("rid")
if pass, err := checkReportBelongs(reportId, reportLog, c, &result); !pass {
return err
}
reportLog.Info("获取园区电量信息", zap.String("Report", reportId))
summary, err := repository.ReportRepository.RetrieveReportSummary(reportId)
if err != nil {
reportLog.Error("无法获取核算报表的园区电量信息", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法获取核算报表的园区电量信息。")
}
if summary == nil {
reportLog.Error("未找到核算报表的园区电量信息")
return result.NotFound("未找到核算报表的园区电量信息。")
}
var summaryResponse vo.SimplifiedReportSummary
copier.Copy(&summaryResponse, summary)
return result.Success(
"已经获取到核算报表的园区电量信息。",
fiber.Map{"summary": summaryResponse},
)
}
// 对提供的园区电量信息进行试计算,返回试计算结果
func testCalculateReportSummary(c *fiber.Ctx) error {
result := response.NewResult(c)
reportLog.Info("试计算园区电量信息")
var form vo.TestCalculateForm
if err := c.BodyParser(&form); err != nil {
reportLog.Error("无法解析试计算核算报表的请求数据。", zap.Error(err))
return result.BadRequest("无法解析试计算核算报表的请求数据。")
}
return result.Success(
"电量电费试计算已经完成。",
fiber.Map{"summary": form.Calculate()},
)
}
// 获取指定园区中尚未发布的核算报表计算状态
func listCalculateTaskStatus(c *fiber.Ctx) error {
result := response.NewResult(c)
session, err := _retreiveSession(c)
if err != nil {
reportLog.Error("无法获取当前用户的会话信息", zap.Error(err))
return result.Unauthorized("无法获取当前用户的会话信息。")
}
status, err := repository.ReportRepository.GetReportTaskStatus(session.Uid)
if err != nil {
reportLog.Error("无法获取核算报表计算状态", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法获取核算报表计算状态。")
}
statusResponse := make([]*vo.ReportCalculateTaskStatusResponse, 0)
copier.Copy(&statusResponse, &status)
return result.Success(
"已经获取到核算报表计算状态。",
fiber.Map{"status": statusResponse},
)
}
// 获取指定报表的详细信息
func getReportDetail(c *fiber.Ctx) error {
result := response.NewResult(c)
reportId := c.Params("rid")
reportLog.Info("获取核算报表的详细信息", zap.String("Report", reportId))
user, park, report, err := service.ReportService.RetrieveReportIndexDetail(reportId)
if err != nil {
reportLog.Error("无法获取核算报表的详细信息", zap.Error(err))
return result.NotFound("无法获取核算报表的详细信息。")
}
return result.Success(
"已经获取到核算报表的详细信息。",
fiber.Map{
"detail": vo.NewReportDetailQueryResponse(user, park, report),
},
)
}
// 获取指定核算报表的总览信息
func getReportSummary(c *fiber.Ctx) error {
result := response.NewResult(c)
reportId := c.Params("rid")
report, err := repository.ReportRepository.RetrieveReportSummary(reportId)
if err != nil {
reportLog.Error("无法获取核算报表的总览信息", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法获取核算报表的总览信息。")
}
if report == nil {
reportLog.Error("未找到核算报表的总览信息")
return result.NotFound("未找到核算报表的总览信息。")
}
summaryResponse := vo.ParkSummaryResponse{
ReportId: report.ReportId,
OverallDisplay: vo.ConsumptionDisplay{
AmountStr: strconv.FormatFloat(report.Overall.Amount.InexactFloat64(), 'f', -1, 64),
FeeStr: strconv.FormatFloat(report.Overall.Fee.InexactFloat64(), 'f', -1, 64),
PriceStr: strconv.FormatFloat(report.Overall.Price.InexactFloat64(), 'f', -1, 64),
ProportionStr: strconv.FormatFloat(report.Overall.Proportion.InexactFloat64(), 'f', -1, 64),
},
Area: report.OverallArea,
BasicFee: report.BasicFee,
PooledBasicFeeByAmount: report.BasicPooledPriceConsumption.Decimal,
PooledBasicFeeByArea: report.BasicPooledPriceArea.Decimal,
AdjustFee: report.AdjustFee,
PooledAdjustFeeByAmount: report.AdjustPooledPriceConsumption.Decimal,
PooledAdjustFeeByArea: report.AdjustPooledPriceArea.Decimal,
Consumption: report.ConsumptionFee.Decimal,
//Loss: report.Loss.Decimal,
Loss: report.AuthorizeLoss.Amount,
//LossRate: report.LossFee.Decimal,
LossRate: report.AuthorizeLoss.Proportion,
}
//copier.Copy(&summaryResponse, report)
return result.Success(
"已经获取到核算报表的总览信息。",
fiber.Map{"summary": summaryResponse},
)
}
// 获取指定报表中分页的公共表计的核算摘要信息
func listPublicMetersInReport(c *fiber.Ctx) error {
result := response.NewResult(c)
reportId := c.Params("rid")
reportLog.Info("获取核算报表中的公共表计信息", zap.String("Report", reportId))
page := c.QueryInt("page", 1)
keyword := tools.EmptyToNil(c.Query("keyword"))
meters, total, err := repository.ReportRepository.ListPublicMetersInReport(reportId, uint(page), keyword)
if err != nil {
reportLog.Error("无法获取核算报表中的公共表计信息", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法获取核算报表中的公共表计信息。")
}
meterResponse := lo.Map(meters, func(meter *model.ReportDetailedPublicConsumption, _ int) *vo.ReportPublicQueryResponse {
m := &vo.ReportPublicQueryResponse{}
m.FromReportDetailPublicConsumption(meter)
return m
})
return result.Success(
"已经获取到指定核算报表中的分页公共表计的核算信息。",
response.NewPagedResponse(page, total).ToMap(),
fiber.Map{"public": meterResponse},
)
}
// 获取指定报表中的分页的公摊表计的核算摘要信息
func listPooledMetersInReport(c *fiber.Ctx) error {
result := response.NewResult(c)
reportId := c.Params("rid")
reportLog.Info("获取核算报表中的公摊表计信息", zap.String("Report", reportId))
page := c.QueryInt("page", 1)
keyword := tools.EmptyToNil(c.Query("keyword"))
meters, total, err := repository.ReportRepository.ListPooledMetersInReport(reportId, uint(page), keyword)
if err != nil {
reportLog.Error("无法获取核算报表中的公摊表计信息", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法获取核算报表中的公摊表计信息。")
}
meterResponse := lo.Map(meters, func(meter *model.ReportDetailedPooledConsumption, _ int) *vo.ReportPooledQueryResponse {
m := &vo.ReportPooledQueryResponse{}
m.FromReportDetailPooledConsumption(meter)
return m
})
return result.Success(
"已经获取到指定核算报表中的分页公摊表计的核算信息。",
response.NewPagedResponse(page, total).ToMap(),
fiber.Map{"pooled": meterResponse},
)
}
// 列出指定报表中指定公共表计下各个分摊表计的消耗数据
func listSubmetersInPooledMeter(c *fiber.Ctx) error {
result := response.NewResult(c)
reportId := c.Params("rid")
meterId := c.Params("code")
if len(meterId) == 0 {
reportLog.Error("未提供公共表计的编号")
return result.BadRequest("未提供公共表计的编号。")
}
meters, err := repository.ReportRepository.ListPooledMeterDetailInReport(reportId, meterId)
if err != nil {
reportLog.Error("无法获取核算报表中的公共表计信息", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法获取核算报表中的公共表计信息。")
}
meterResponse := lo.Map(meters, func(meter *model.ReportDetailNestedMeterConsumption, _ int) *vo.ReportPooledQueryResponse {
m := &vo.ReportPooledQueryResponse{}
m.FromReportDetailNestedMeterConsumption(meter)
return m
})
return result.Success(
"已经获取到指定核算报表中的公共表计的核算信息。",
fiber.Map{"meters": meterResponse},
)
}
// 获取指定报表中分页的商户核算电量电费概要数据
func listTenementsInReport(c *fiber.Ctx) error {
result := response.NewResult(c)
reportId := c.Params("rid")
page := c.QueryInt("page", 1)
keyword := tools.EmptyToNil(c.Query("keyword"))
tenements, total, err := repository.ReportRepository.ListTenementInReport(reportId, uint(page), keyword)
if err != nil {
reportLog.Error("无法获取核算报表中的商户信息", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法获取核算报表中的商户信息。")
}
tenementsResponse := lo.Map(tenements, func(tenement *model.ReportTenement, _ int) *vo.ReportTenementSummaryResponse {
t := &vo.ReportTenementSummaryResponse{}
t.FromReportTenement(tenement)
return t
})
return result.Success(
"已经获取到指定核算报表中的分页商户的核算信息。",
response.NewPagedResponse(page, total).ToMap(),
fiber.Map{"tenements": tenementsResponse},
)
}
// 获取指定报表中指定商户的详细核算信息
func getTenementDetailInReport(c *fiber.Ctx) error {
result := response.NewResult(c)
reportId := c.Params("rid")
tenementId := c.Params("tid")
detail, err := repository.ReportRepository.GetTenementDetailInReport(reportId, tenementId)
if err != nil {
reportLog.Error("无法获取核算报表中的商户信息", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法获取核算报表中的商户信息。")
}
var detailResponse vo.ReportTenementDetailResponse
detailResponse.FromReportTenement(detail)
return result.Success(
"已经获取到指定核算报表中的商户的详细核算信息。",
fiber.Map{"detail": detailResponse},
)
}
// 发布指定的核算报表
func publishReport(c *fiber.Ctx) error {
result := response.NewResult(c)
reportId := c.Params("rid")
if pass, err := checkReportBelongs(reportId, reportLog, c, &result); !pass {
return err
}
ok, err := repository.ReportRepository.PublishReport(reportId)
if err != nil {
reportLog.Error("无法发布核算报表", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "发布核算报表出错。")
}
if !ok {
reportLog.Error("未能完成核算报表的发布。")
return result.NotAccept("未能完成核算报表的发布。")
}
return result.Success("已经成功发布核算报表。")
}
// 对核算报表进行综合检索
func reportComprehensiveSearch(c *fiber.Ctx) error {
result := response.NewResult(c)
user := tools.EmptyToNil(c.Query("user"))
session, err := _retreiveSession(c)
if err != nil {
reportLog.Error("无法获取当前用户的会话信息", zap.Error(err))
return result.Unauthorized("无法获取当前用户的会话信息。")
}
park := tools.EmptyToNil(c.Query("park"))
if session.Type == model.USER_TYPE_ENT && park != nil && len(*park) > 0 {
if pass, err := checkParkBelongs(*park, reportLog, c, &result); !pass {
return err
}
}
var requestUser *string
if session.Type == model.USER_TYPE_ENT {
requestUser = lo.ToPtr(tools.DefaultTo(user, session.Uid))
} else {
requestUser = user
}
page := c.QueryInt("page", 1)
keyword := tools.EmptyToNil(c.Query("keyword"))
startDate, err := types.ParseDatep(c.Query("period_start"))
if err != nil {
reportLog.Error("无法解析核算报表查询的开始日期", zap.Error(err))
return result.BadRequest("无法解析核算报表查询的开始日期。")
}
endDate, err := types.ParseDatep(c.Query("period_end"))
if err != nil {
reportLog.Error("无法解析核算报表查询的结束日期", zap.Error(err))
return result.BadRequest("无法解析核算报表查询的结束日期。")
}
reports, total, err := service.ReportService.QueryReports(requestUser, park, uint(page), keyword, startDate, endDate)
if err != nil {
reportLog.Error("无法查询核算报表", zap.Error(err))
return result.Error(fiber.StatusInternalServerError, "无法查询核算报表。")
}
return result.Success(
"已经获取到指定核算报表的分页信息。",
response.NewPagedResponse(page, total).ToMap(),
fiber.Map{"reports": reports},
)
}