enhance(calculate): 完善计算部分

This commit is contained in:
2023-08-07 15:15:11 +08:00
84 changed files with 3173 additions and 5398 deletions

View File

@@ -1,237 +0,0 @@
package controller
import (
"database/sql"
"electricity_bill_calc/excel"
"electricity_bill_calc/global"
"electricity_bill_calc/model"
"electricity_bill_calc/response"
"electricity_bill_calc/security"
"electricity_bill_calc/service"
"fmt"
"net/http"
"strconv"
"github.com/gofiber/fiber/v2"
"github.com/samber/lo"
"github.com/shopspring/decimal"
)
func InitializeEndUserController(router *fiber.App) {
router.Get("/report/:rid/submeter", security.EnterpriseAuthorize, fetchEndUserInReport)
router.Get("/report/:rid/meter/template", downloadEndUserRegisterTemplate)
router.Post("/report/:rid/meter/batch", security.EnterpriseAuthorize, uploadEndUserRegisterTemplate)
router.Put("/report/:rid/submeter/:pid/:mid", security.EnterpriseAuthorize, modifyEndUserRegisterRecord)
router.Get("/end/user/adjusts", security.MustAuthenticated, statEndUserInPeriod)
}
func fetchEndUserInReport(c *fiber.Ctx) error {
result := response.NewResult(c)
requestReportId := c.Params("rid")
if ensure, err := ensureReportBelongs(c, &result, requestReportId); !ensure {
return err
}
keyword := c.Query("keyword")
requestPage, err := strconv.Atoi(c.Query("page", "1"))
if err != nil {
return result.NotAccept("查询参数[page]格式不正确。")
}
endUsers, totalItem, err := service.EndUserService.SearchEndUserRecord(requestReportId, keyword, requestPage)
if err != nil {
return result.NotFound(err.Error())
}
return result.Json(
http.StatusOK,
"已获取到符合条件的终端用户集合",
response.NewPagedResponse(requestPage, totalItem).ToMap(),
fiber.Map{"meters": endUsers},
)
}
func downloadEndUserRegisterTemplate(c *fiber.Ctx) error {
result := response.NewResult(c)
requestReportId := c.Params("rid")
users, err := service.EndUserService.AllEndUserRecord(requestReportId)
if err != nil {
return result.NotFound(err.Error())
}
reportIndex, err := service.ReportService.RetreiveReportIndex(requestReportId)
if err != nil {
return result.NotFound(err.Error())
}
park, err := service.ParkService.FetchParkDetail(reportIndex.ParkId)
if err != nil {
return result.NotFound(err.Error())
}
meterType, err := service.ReportService.RetreiveParkEndUserMeterType(requestReportId)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
if meterType == -1 {
return result.NotFound("未能确定用户表计类型。")
}
c.Status(http.StatusOK)
c.Set("Content-Type", "application/octet-stream")
c.Set("Content-Transfer-Encoding", "binary")
c.Set("Content-Disposition", fmt.Sprintf("attachment; filename=抄表记录-%s-%s.xlsx", park.Name, reportIndex.Period.Format("2006-01")))
gen := lo.Ternary[excel.ExcelTemplateGenerator](
meterType == 0,
excel.NewMeterNonPVExcelTemplateGenerator(),
excel.NewMeterPVExcelTemplateGenerator(),
)
defer gen.Close()
gen.WriteMeterData(users)
gen.WriteTo(c.Response().BodyWriter())
return nil
}
func uploadEndUserRegisterTemplate(c *fiber.Ctx) error {
result := response.NewResult(c)
requestReportId := c.Params("rid")
if ensure, err := ensureReportBelongs(c, &result, requestReportId); !ensure {
return err
}
meterType, err := service.ReportService.RetreiveParkEndUserMeterType(requestReportId)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
if meterType == -1 {
return result.NotFound("未能确定用户表计类型。")
}
uploadedFile, err := c.FormFile("data")
if err != nil {
return result.NotAccept("没有接收到上传的档案文件。")
}
archiveFile, err := uploadedFile.Open()
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
if meterType == 0 {
errs := service.EndUserService.BatchImportNonPVRegister(requestReportId, archiveFile)
if errs.Len() > 0 {
return result.Json(http.StatusInternalServerError, "上传抄表文件存在解析错误", fiber.Map{"errors": errs.Errs})
}
} else {
errs := service.EndUserService.BatchImportPVRegister(requestReportId, archiveFile)
if errs.Len() > 0 {
return result.Json(http.StatusInternalServerError, "上传抄表文件存在解析错误", fiber.Map{"errors": errs.Errs})
}
}
return result.Json(http.StatusOK, "已经成功完成抄表记录的导入。", fiber.Map{"errors": make([]error, 0)})
}
type ModifyEndUserRegisterFormData struct {
CurrentPeriodOverall decimal.NullDecimal `json:"currentPeriodOverall" form:"currentPeriodOverall"`
CurrentPeriodCritical decimal.NullDecimal `json:"currentPeriodCritical" form:"currentPeriodCritical"`
CurrentPeriodPeak decimal.NullDecimal `json:"currentPeriodPeak" form:"currentPeriodPeak"`
CurrentPeriodValley decimal.NullDecimal `json:"currentPeriodValley" form:"currentPeriodValley"`
AdjustOverall decimal.NullDecimal `json:"adjustOverall" form:"adjustOverall"`
AdjustCritical decimal.NullDecimal `json:"adjustCritical" form:"adjustCritical"`
AdjustPeak decimal.NullDecimal `json:"adjustPeak" form:"adjustPeak"`
AdjustValley decimal.NullDecimal `json:"adjustValley" form:"adjustValley"`
}
func modifyEndUserRegisterRecord(c *fiber.Ctx) error {
result := response.NewResult(c)
requestReportId := c.Params("rid")
if ensure, err := ensureReportBelongs(c, &result, requestReportId); !ensure {
return err
}
meterType, err := service.ReportService.RetreiveParkEndUserMeterType(requestReportId)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
if meterType == -1 {
return result.NotFound("未能确定用户表计类型。")
}
requestParkId := c.Params("pid")
requestMeterId := c.Params("mid")
formData := new(ModifyEndUserRegisterFormData)
if err := c.BodyParser(formData); err != nil {
return result.UnableToParse("无法解析提交的数据。")
}
meter, err := service.EndUserService.FetchSpecificEndUserRecord(requestReportId, requestParkId, requestMeterId)
if err != nil {
return result.NotFound(err.Error())
}
if formData.CurrentPeriodOverall.Valid {
meter.CurrentPeriodOverall = formData.CurrentPeriodOverall.Decimal
}
if formData.CurrentPeriodCritical.Valid {
meter.CurrentPeriodCritical = formData.CurrentPeriodCritical.Decimal
}
if formData.CurrentPeriodPeak.Valid {
meter.CurrentPeriodPeak = formData.CurrentPeriodPeak.Decimal
}
if formData.CurrentPeriodValley.Valid {
meter.CurrentPeriodValley = formData.CurrentPeriodValley.Decimal
}
if formData.AdjustOverall.Valid {
meter.AdjustOverall = formData.AdjustOverall.Decimal
}
if formData.AdjustCritical.Valid {
meter.AdjustCritical = formData.AdjustCritical.Decimal
}
if formData.AdjustPeak.Valid {
meter.AdjustPeak = formData.AdjustPeak.Decimal
}
if formData.AdjustValley.Valid {
meter.AdjustValley = formData.AdjustValley.Decimal
}
valid, err := meter.Validate()
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
if !valid {
return result.NotAccept("抄表数据合法性验证失败。")
}
ctx, cancel := global.TimeoutContext()
defer cancel()
tx, err := global.DB.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
err = service.EndUserService.UpdateEndUserRegisterRecord(&tx, &ctx, *meter)
if err != nil {
tx.Rollback()
return result.Error(http.StatusInternalServerError, err.Error())
}
err = tx.Commit()
if err != nil {
tx.Rollback()
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Success("指定终端用户抄表记录已经更新。")
}
func statEndUserInPeriod(c *fiber.Ctx) error {
result := response.NewResult(c)
session, err := _retreiveSession(c)
if err != nil {
return result.Unauthorized(err.Error())
}
requestUser := lo.
If(session.Type == model.USER_TYPE_ENT, session.Uid).
Else(c.Query("user"))
requestPark := c.Query("park")
if len(requestPark) > 0 && session.Type == model.USER_TYPE_ENT {
if ensure, err := ensureParkBelongs(c, &result, requestPark); !ensure {
return err
}
}
startDate := c.Query("start")
endDate := c.Query("end")
stat, err := service.EndUserService.StatEndUserRecordInPeriod(requestUser, requestPark, startDate, endDate)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Success(
"已经完成终端用户的费用统计",
fiber.Map{"details": stat},
)
}

24
controller/foundation.go Normal file
View File

@@ -0,0 +1,24 @@
package controller
import (
"electricity_bill_calc/config"
"electricity_bill_calc/logger"
"electricity_bill_calc/response"
"electricity_bill_calc/security"
"github.com/gofiber/fiber/v2"
)
var foundLog = logger.Named("Handler", "Foundation")
func InitializeFoundationHandlers(router *fiber.App) {
router.Get("/norm/authorized/loss/rate", security.MustAuthenticated, getNormAuthorizedLossRate)
}
func getNormAuthorizedLossRate(c *fiber.Ctx) error {
foundLog.Info("获取系统中定义的基准核定线损率")
result := response.NewResult(c)
BaseLoss := config.BaseLoss
return result.Success("已经获取到系统设置的基准核定线损率。",
fiber.Map{"normAuthorizedLossRate": BaseLoss},
)
}

View File

@@ -1,176 +1,132 @@
package controller
import (
"electricity_bill_calc/exceptions"
"electricity_bill_calc/logger"
"electricity_bill_calc/response"
"electricity_bill_calc/security"
"electricity_bill_calc/service"
"net/http"
"errors"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
"net/http"
)
func InitializeGodModeController(router *fiber.App) {
gmR := router.Group("/gm")
{
gmR.Delete("/report/:rid/summary", security.SingularityAuthorize, gmResetReportSummary)
gmR.Delete("/report/:rid/maintenance", security.SingularityAuthorize, gmResetReportMaintenance)
gmR.Delete("/report/:rid/meters", security.SingularityAuthorize, gmResetReportEndUserRecord)
gmR.Post("/report/:rid/meters", security.SingularityAuthorize, gmResynchronizeReportEndUserRecord)
gmR.Delete("/report/:rid", security.SingularityAuthorize, gmResetReport)
gmR.Delete("/report/:rid/force", security.SingularityAuthorize, gmDeleteReport)
gmR.Delete("/park/:pid/maintenance/:mid", security.SingularityAuthorize, gmDeleteSpecificMaintenance)
gmR.Delete("/park/:pid/maintenance", security.SingularityAuthorize, gmDeleteAllMaintenance)
gmR.Delete("/park/:pid/meters", security.SingularityAuthorize, gmDeleteAllMeters)
gmR.Delete("/park/:pid/force", security.SingularityAuthorize, gmDeletePark)
gmR.Delete("/enterprise/:uid/force", security.SingularityAuthorize, gmDeleteUser)
}
var GmLog = logger.Named("Handler", "GM")
func InitializeGmController(router *fiber.App) {
router.Delete("/gm/tenement", security.SingularityAuthorize, deleteTenement)
router.Delete("/gm/park", security.SingularityAuthorize, deletePark)
router.Delete("/gm/report", security.SingularityAuthorize, deleteReports)
router.Delete("/gm/tenement/meter", security.SingularityAuthorize, deleteTenementMeterRelations)
router.Delete("/gm/enterprise", security.SingularityAuthorize, deleteEnterprise)
router.Delete("/gm/meter/pooling", security.SingularityAuthorize, deleteMeterPoolingRelations)
router.Delete("gm/meter", security.SingularityAuthorize, deleteMeters)
}
func gmResetReportSummary(c *fiber.Ctx) error {
result := response.NewResult(c)
requestReportId := c.Params("rid")
done, err := service.GodModeService.ClearReportSummary(requestReportId)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
//用于将参数转化为切片
func getQueryValues(c *fiber.Ctx, paramName string) []string {
values := c.Request().URI().QueryArgs().PeekMulti(paramName)
result := make([]string, len(values))
for i, v := range values {
result[i] = string(v)
}
if !done {
return result.Error(http.StatusInternalServerError, "未能成功重置指定报表的园区总览部分。")
}
return result.Success("指定报表的园区总览已经重置。")
return result
}
func gmResetReportMaintenance(c *fiber.Ctx) error {
func deleteTenement(c *fiber.Ctx) error {
park := c.Query("park", "")
tenements := getQueryValues(c, "tenements")
result := response.NewResult(c)
requestReportId := c.Params("rid")
done, err := service.GodModeService.ClearReportMaintenances(requestReportId)
GmLog.Info("[天神模式]删除指定园区中的商户", zap.String("park", park), zap.Strings("tenements", tenements))
err := service.GMService.DeleteTenements(park, tenements)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
GmLog.Error("[天神模式]删除指定园区中的商户失败", zap.Error(err))
return result.Error(500, err.Error())
}
if !done {
return result.Error(http.StatusInternalServerError, "未能成功重置指定报表的配电维护费部分。")
}
return result.Success("指定报表的配电维护费已经重置。")
return result.Success("指定商户已经删除。")
}
func gmResynchronizeReportEndUserRecord(c *fiber.Ctx) error {
func deletePark(c *fiber.Ctx) error {
parks := getQueryValues(c, "parks")
result := response.NewResult(c)
requestReportId := c.Params("rid")
done, err := service.GodModeService.ResynchronizeEndUser(requestReportId)
GmLog.Info("[天神模式]删除指定园区", zap.Strings("parks", parks))
if len(parks) < 0 {
GmLog.Info("[天神模式]用户未指派园区参数或者未指定需要删除的园区。")
return result.Error(http.StatusBadRequest, error.Error(errors.New("必须至少指定一个需要删除的园区!")))
}
err := service.GMService.DeleteParks(parks)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
GmLog.Error("[天神模式]删除指定园区失败", zap.Error(err))
return result.Error(500, err.Error())
}
if !done {
return result.Error(http.StatusInternalServerError, "未能成功重置指定报表的抄表记录基本档案。")
}
return result.Success("指定报表的抄表记录基本档案已经重新同步。")
return result.Success("指定园区已经删除。")
}
func gmResetReportEndUserRecord(c *fiber.Ctx) error {
func deleteReports(c *fiber.Ctx) error {
pid := c.Query("park")
reports := getQueryValues(c, "reports")
result := response.NewResult(c)
requestReportId := c.Params("rid")
done, err := service.GodModeService.ResetEndUserRegisterRecords(requestReportId)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
if !done {
return result.Error(http.StatusInternalServerError, "未能成功重置指定报表的抄表记录部分。")
}
return result.Success("指定报表的抄表记录已经重置。")
}
GmLog.Info("[天神模式]删除符合条件的报表。", zap.Strings("reports", reports))
func gmResetReport(c *fiber.Ctx) error {
result := response.NewResult(c)
requestReportId := c.Params("rid")
done, err := service.GodModeService.ResetReport(requestReportId)
err := service.GMService.DeleteReports(pid, reports)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
if !done {
return result.Error(http.StatusInternalServerError, "未能成功重置指定报表。")
}
return result.Success("指定报表已经重置。")
}
func gmDeleteReport(c *fiber.Ctx) error {
result := response.NewResult(c)
requestReportId := c.Params("rid")
done, err := service.GodModeService.DeleteReport(requestReportId)
if err != nil {
if ipErr, ok := err.(exceptions.ImproperOperateError); ok {
return result.NotAccept(ipErr.Message)
} else {
return result.Error(http.StatusInternalServerError, err.Error())
}
}
if !done {
return result.Error(http.StatusInternalServerError, "未能成功删除指定报表。")
GmLog.Error("[天神模式]删除指定园区中的报表失败。", zap.Error(err))
return result.Error(500, err.Error())
}
return result.Success("指定报表已经删除。")
}
func gmDeleteSpecificMaintenance(c *fiber.Ctx) error {
func deleteEnterprise(c *fiber.Ctx) error {
uid := c.Query("uid")
result := response.NewResult(c)
requestParkId := c.Params("pid")
requestMaintenanceId := c.Params("mid")
done, err := service.GodModeService.RemoveSpecificMaintenance(requestParkId, requestMaintenanceId)
GmLog.Info("[天神模式]删除指定企业用户", zap.String("uid", uid))
err := service.GMService.DeleteEnterprises(uid)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
GmLog.Error("[天神模式]删除指定企业用户失败", zap.Error(err))
return result.Error(500, "删除指定企业用户失败。")
}
if !done {
return result.Error(http.StatusInternalServerError, "未能成功删除指定的维护费用记录。")
}
return result.Success("指定维护费用记录已经删除。")
return result.Success("指定企业用户已经删除。")
}
func gmDeleteAllMaintenance(c *fiber.Ctx) error {
func deleteTenementMeterRelations(c *fiber.Ctx) error {
result := response.NewResult(c)
requestParkId := c.Params("pid")
done, err := service.GodModeService.RemoveAllMaintenance(requestParkId)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
parkId := c.Query("park")
tId := getQueryValues(c, "tenements")
metersId := getQueryValues(c, "meters")
GmLog.Info("删除指定园区中的商户与表计的关联关系", zap.String("park id", parkId))
if err := service.GMService.DeleteTenementMeterRelations(parkId, tId, metersId); err != nil {
meterLog.Error("无法删除指定园区中的商户与表计的关联关系", zap.Error(err))
return result.NotAccept(err.Error())
}
if !done {
return result.Error(http.StatusInternalServerError, "未能成功删除全部维护费用记录。")
}
return result.Success("全部维护费用记录已经删除。")
return result.Success("删除成功")
}
func gmDeleteAllMeters(c *fiber.Ctx) error {
func deleteMeterPoolingRelations(c *fiber.Ctx) error {
result := response.NewResult(c)
requestParkId := c.Params("pid")
done, err := service.GodModeService.RemoveAllMeters(requestParkId)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
parkId := c.Query("park")
mId := getQueryValues(c, "meters")
GmLog.Info("[天神模式]删除指定园区中的表计公摊关系", zap.String("park id", parkId))
if err := service.GMService.DeleteMeterPooling(parkId, mId); err != nil {
meterLog.Error("[天神模式]删除指定园区中的表计公摊关系失败", zap.Error(err))
return result.Error(500, "删除指定园区中的表计公摊关系失败。")
}
if !done {
return result.Error(http.StatusInternalServerError, "未能成功删除全部终端表计档案记录。")
}
return result.Success("全部终端表计档案记录已经删除。")
return result.Success("指定表计公摊关系已经删除。")
}
func gmDeletePark(c *fiber.Ctx) error {
func deleteMeters(c *fiber.Ctx) error {
result := response.NewResult(c)
requestParkId := c.Params("pid")
done, err := service.GodModeService.RemovePark(requestParkId)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
parkId := c.Query("park")
mId := getQueryValues(c, "meters")
GmLog.Info("[天神模式]删除指定园区中的表计", zap.String("park id", parkId))
if err := service.GMService.DeleteMeters(parkId, mId); err != nil {
meterLog.Error("[天神模式]删除指定园区中的表计失败", zap.Error(err))
return result.Error(500, "删除指定园区中的表计失败。")
}
if !done {
return result.Error(http.StatusInternalServerError, "未能成功删除指定的园区。")
}
return result.Success("指定的园区已经删除。")
}
func gmDeleteUser(c *fiber.Ctx) error {
result := response.NewResult(c)
requestUserId := c.Params("uid")
done, err := service.GodModeService.DeleteUser(requestUserId)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
if !done {
return result.Error(http.StatusInternalServerError, "未能成功删除指定的用户。")
}
return result.Success("指定的用户及其关联信息已经删除。")
return result.Success("指定表计已经删除。")
}

View File

@@ -1,202 +0,0 @@
package controller
import (
"electricity_bill_calc/model"
"electricity_bill_calc/response"
"electricity_bill_calc/security"
"electricity_bill_calc/service"
"net/http"
"strconv"
"github.com/gofiber/fiber/v2"
"github.com/jinzhu/copier"
"github.com/samber/lo"
"github.com/shopspring/decimal"
)
func InitializeMaintenanceFeeController(router *fiber.App) {
router.Get("/maintenance/fee", security.MustAuthenticated, listMaintenanceFees)
router.Post("/maintenance/fee", security.EnterpriseAuthorize, createMaintenanceFeeRecord)
router.Put("/maintenance/fee/:mid", security.EnterpriseAuthorize, modifyMaintenanceFeeRecord)
router.Put("/maintenance/fee/:mid/enabled", security.EnterpriseAuthorize, changeMaintenanceFeeState)
router.Delete("/maintenance/fee/:mid", security.EnterpriseAuthorize, deleteMaintenanceFee)
router.Get("/additional/charges", security.MustAuthenticated, statAdditionalCharges)
}
func ensureMaintenanceFeeBelongs(c *fiber.Ctx, result *response.Result, requestMaintenanceFeeId string) (bool, error) {
userSession, err := _retreiveSession(c)
if err != nil {
return false, result.Unauthorized(err.Error())
}
sure, err := service.MaintenanceFeeService.EnsureFeeBelongs(userSession.Uid, requestMaintenanceFeeId)
if err != nil {
return false, result.Error(http.StatusInternalServerError, err.Error())
}
if !sure {
return false, result.Unauthorized("所操作维护费记录不属于当前用户。")
}
return true, nil
}
func listMaintenanceFees(c *fiber.Ctx) error {
result := response.NewResult(c)
userSession, err := _retreiveSession(c)
if err != nil {
return result.Unauthorized(err.Error())
}
requestPark := c.Query("park")
requestPeriod := c.Query("period")
requestPage, err := strconv.Atoi(c.Query("page", "1"))
if err != nil {
return result.Error(http.StatusInternalServerError, "不能解析给定的参数[page]。")
}
if len(requestPark) > 0 {
if userSession.Type == model.USER_TYPE_ENT {
if ensure, err := ensureParkBelongs(c, &result, requestPark); !ensure {
return err
}
}
fees, total, err := service.MaintenanceFeeService.ListMaintenanceFees([]string{requestPark}, requestPeriod, requestPage)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Json(
http.StatusOK,
"已获取指定园区下的维护费记录",
response.NewPagedResponse(requestPage, total).ToMap(),
fiber.Map{"fees": fees},
)
} else {
parkIds, err := service.ParkService.AllParkIds(userSession.Uid)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
fees, total, err := service.MaintenanceFeeService.ListMaintenanceFees(parkIds, requestPeriod, requestPage)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Json(
http.StatusOK,
"已获取指定用户下的所有维护费记录。",
response.NewPagedResponse(requestPage, total).ToMap(),
fiber.Map{"fees": fees},
)
}
}
type _FeeCreationFormData struct {
ParkId string `json:"parkId" form:"parkId"`
Name string `json:"name" form:"name"`
Period string `json:"period" form:"period"`
Fee decimal.Decimal `json:"fee" form:"fee"`
Memo *string `json:"memo" form:"memo"`
}
func createMaintenanceFeeRecord(c *fiber.Ctx) error {
result := response.NewResult(c)
formData := new(_FeeCreationFormData)
if err := c.BodyParser(formData); err != nil {
return result.UnableToParse("无法解析提交的数据。")
}
if ensure, err := ensureParkBelongs(c, &result, formData.ParkId); !ensure {
return err
}
newMaintenanceFee := &model.MaintenanceFee{}
copier.Copy(newMaintenanceFee, formData)
err := service.MaintenanceFeeService.CreateMaintenanceFeeRecord(*newMaintenanceFee)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Created("新维护费记录已经创建。")
}
type _FeeModificationFormData struct {
Fee decimal.Decimal `json:"fee" form:"fee"`
Memo *string `json:"memo" form:"memo"`
}
func modifyMaintenanceFeeRecord(c *fiber.Ctx) error {
result := response.NewResult(c)
requestFee := c.Params("mid")
formData := new(_FeeModificationFormData)
if err := c.BodyParser(formData); err != nil {
return result.UnableToParse("无法解析提交的数据。")
}
if ensure, err := ensureMaintenanceFeeBelongs(c, &result, requestFee); !ensure {
return err
}
newFeeState := new(model.MaintenanceFee)
copier.Copy(newFeeState, formData)
newFeeState.Id = requestFee
err := service.MaintenanceFeeService.ModifyMaintenanceFee(*newFeeState)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Updated("指定维护费条目已更新。")
}
type _FeeStateFormData struct {
Enabled bool `json:"enabled" form:"enabled"`
}
func changeMaintenanceFeeState(c *fiber.Ctx) error {
result := response.NewResult(c)
requestFee := c.Params("mid")
formData := new(_FeeStateFormData)
if err := c.BodyParser(formData); err != nil {
return result.UnableToParse("无法解析提交的数据。")
}
if ensure, err := ensureMaintenanceFeeBelongs(c, &result, requestFee); !ensure {
return err
}
err := service.MaintenanceFeeService.ChangeMaintenanceFeeState(requestFee, formData.Enabled)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Updated("指定维护费条目状态已更新。")
}
func deleteMaintenanceFee(c *fiber.Ctx) error {
result := response.NewResult(c)
requestFee := c.Params("mid")
if ensure, err := ensureMaintenanceFeeBelongs(c, &result, requestFee); !ensure {
return err
}
err := service.MaintenanceFeeService.DeleteMaintenanceFee(requestFee)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Deleted("指定维护费条目已删除。")
}
func statAdditionalCharges(c *fiber.Ctx) error {
result := response.NewResult(c)
session, err := _retreiveSession(c)
if err != nil {
return result.Unauthorized(err.Error())
}
requestUser := lo.
If(session.Type == model.USER_TYPE_ENT, session.Uid).
Else(c.Query("user"))
requestPark := c.Query("park")
if len(requestPark) > 0 && session.Type == model.USER_TYPE_ENT {
if ensure, err := ensureParkBelongs(c, &result, requestPark); !ensure {
return err
}
}
period := c.Query("period", "")
keyword := c.Query("keyword", "")
requestPage, err := strconv.Atoi(c.Query("page", "1"))
if err != nil {
return result.Error(http.StatusInternalServerError, "不能解析给定的参数[page]。")
}
fees, total, err := service.MaintenanceFeeService.QueryAdditionalCharges(requestUser, requestPark, period, keyword, requestPage)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Success(
"已经成功获取到物业附加费的统计记录。",
response.NewPagedResponse(requestPage, total).ToMap(),
fiber.Map{"charges": fees},
)
}

View File

@@ -1,188 +0,0 @@
package controller
import (
"electricity_bill_calc/excel"
"electricity_bill_calc/model"
"electricity_bill_calc/response"
"electricity_bill_calc/security"
"electricity_bill_calc/service"
"fmt"
"net/http"
"strconv"
"github.com/gofiber/fiber/v2"
"github.com/jinzhu/copier"
"github.com/samber/lo"
"github.com/shopspring/decimal"
)
func InitializeMeter04kVController(router *fiber.App) {
router.Get("/park/:pid/meter/template", download04kvMeterArchiveTemplate)
router.Get("/park/:pid/meters", security.EnterpriseAuthorize, ListPaged04kVMeter)
router.Get("/park/:pid/meter/:code", security.EnterpriseAuthorize, fetch04kVMeterDetail)
router.Post("/park/:pid/meter", security.EnterpriseAuthorize, createSingle04kVMeter)
router.Post("/park/:pid/meter/batch", security.EnterpriseAuthorize, batchImport04kVMeterArchive)
router.Put("/park/:pid/meter/:code", security.EnterpriseAuthorize, modifySingle04kVMeter)
}
func download04kvMeterArchiveTemplate(c *fiber.Ctx) error {
result := response.NewResult(c)
requestParkId := c.Params("pid")
parkDetail, err := service.ParkService.FetchParkDetail(requestParkId)
if err != nil {
return result.NotFound("未找到指定的园区信息。")
}
return c.Download("./assets/meter_04kv_template.xlsx", fmt.Sprintf("%s-户表档案.xlsx", parkDetail.Name))
}
func ListPaged04kVMeter(c *fiber.Ctx) error {
result := response.NewResult(c)
requestParkId := c.Params("pid")
if ensure, err := ensureParkBelongs(c, &result, requestParkId); !ensure {
return err
}
requestPage, err := strconv.Atoi(c.Query("page", "1"))
if err != nil {
return result.NotAccept("查询参数[page]格式不正确。")
}
requestKeyword := c.Query("keyword", "")
meters, totalItem, err := service.Meter04kVService.ListMeterDetail(requestParkId, requestKeyword, requestPage)
if err != nil {
return result.NotFound(err.Error())
}
return result.Json(
http.StatusOK,
"已获取到符合条件的0.4kV表计集合。",
response.NewPagedResponse(requestPage, totalItem).ToMap(),
fiber.Map{"meters": meters},
)
}
func fetch04kVMeterDetail(c *fiber.Ctx) error {
result := response.NewResult(c)
requestParkId := c.Params("pid")
if ensure, err := ensureParkBelongs(c, &result, requestParkId); !ensure {
return err
}
requestMeterCode := c.Params("code")
meter, err := service.Meter04kVService.Get04kVMeterDetail(requestParkId, requestMeterCode)
if err != nil {
return result.NotFound(err.Error())
}
if meter == nil {
return result.Json(http.StatusNotFound, "指定的表计信息未能找到。", fiber.Map{"meter": nil})
}
return result.Json(http.StatusOK, "指定的表计信息已找到。", fiber.Map{"meter": meter})
}
type _MeterModificationFormData struct {
Address *string `json:"address" form:"address"`
CustomerName *string `json:"customerName" form:"customerName"`
ContactName *string `json:"contactName" form:"contactName"`
ContactPhone *string `json:"contactPhone" form:"contactPhone"`
Ratio decimal.Decimal `json:"ratio" form:"ratio"`
Seq int `json:"seq" form:"seq"`
IsPublicMeter bool `json:"isPublicMeter" form:"isPublicMeter"`
Enabled bool `json:"enabled" form:"enabled"`
}
type _MeterCreationFormData struct {
Code string `json:"code" form:"code"`
Address *string `json:"address" form:"address"`
CustomerName *string `json:"customerName" form:"customerName"`
ContactName *string `json:"contactName" form:"contactName"`
ContactPhone *string `json:"contactPhone" form:"contactPhone"`
Ratio decimal.Decimal `json:"ratio" form:"ratio"`
Seq int `json:"seq" form:"seq"`
IsPublicMeter bool `json:"isPublicMeter" form:"isPublicMeter"`
Enabled bool `json:"enabled" form:"enabled"`
}
func createSingle04kVMeter(c *fiber.Ctx) error {
result := response.NewResult(c)
requestParkId := c.Params("pid")
if ensure, err := ensureParkBelongs(c, &result, requestParkId); !ensure {
return err
}
formData := new(_MeterCreationFormData)
if err := c.BodyParser(formData); err != nil {
return result.UnableToParse("无法解析提交的数据。")
}
newMeter := new(model.Meter04KV)
copier.Copy(newMeter, formData)
newMeter.ParkId = requestParkId
err := service.Meter04kVService.CreateSingleMeter(*newMeter)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Created("新0.4kV表计已经添加完成。")
}
func modifySingle04kVMeter(c *fiber.Ctx) error {
result := response.NewResult(c)
requestParkId := c.Params("pid")
if ensure, err := ensureParkBelongs(c, &result, requestParkId); !ensure {
return err
}
requestMeterCode := c.Params("code")
meterDetail, err := service.Meter04kVService.Get04kVMeterDetail(requestParkId, requestMeterCode)
if err != nil {
return result.NotFound(err.Error())
}
if meterDetail == nil {
return result.NotFound("指定表计的信息为找到,不能修改。")
}
formData := new(_MeterModificationFormData)
if err := c.BodyParser(formData); err != nil {
return result.UnableToParse("无法解析提交的数据。")
}
copier.Copy(meterDetail, formData)
err = service.Meter04kVService.UpdateSingleMeter(meterDetail)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Updated("指定0.4kV表计信息已经更新。")
}
func batchImport04kVMeterArchive(c *fiber.Ctx) error {
result := response.NewResult(c)
requestParkId := c.Params("pid")
if ensure, err := ensureParkBelongs(c, &result, requestParkId); !ensure {
return err
}
uploadedFile, err := c.FormFile("data")
if err != nil {
return result.NotAccept("没有接收到上传的档案文件。")
}
archiveFile, err := uploadedFile.Open()
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
analyzer, err := excel.NewMeterArchiveExcelAnalyzer(archiveFile)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
records, errs := analyzer.Analysis(*new(model.Meter04KV))
if len(errs) > 0 {
return result.Json(http.StatusNotAcceptable, "上传的表计档案文件存在错误。", fiber.Map{"errors": errs})
}
mergedMeters := lo.Map(records, func(meter model.Meter04KV, index int) model.Meter04KV {
meter.ParkId = requestParkId
meter.Enabled = true
return meter
})
errs = service.Meter04kVService.DuplicateMeterCodeValidate(mergedMeters)
if len(errs) > 0 {
return result.Json(http.StatusNotAcceptable, "上传的表计档案文件存在错误。", fiber.Map{"errors": errs})
}
err = service.Meter04kVService.BatchCreateMeter(mergedMeters)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Json(
http.StatusOK,
"上传的表计档案已经全部导入。",
fiber.Map{"errors": make([]excel.ExcelAnalysisError, 0)},
)
}

View File

@@ -24,6 +24,8 @@ func InitializeReportHandlers(router *fiber.App) {
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)

View File

@@ -1,31 +1,36 @@
package controller
import (
"electricity_bill_calc/logger"
"electricity_bill_calc/model"
"electricity_bill_calc/response"
"electricity_bill_calc/security"
"electricity_bill_calc/service"
"net/http"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
"net/http"
)
var StatisticsWithdrawLog = logger.Named("Handler", "StatisticsWithdraw")
func InitializeStatisticsController(router *fiber.App) {
router.Get("/audits", security.OPSAuthorize, currentAuditAmount)
router.Get("/stat/reports", security.MustAuthenticated, statReports)
router.Get("/stat/reports", security.OPSAuthorize, statReports)
}
//获取当前系统中待审核的内容数量
func currentAuditAmount(c *fiber.Ctx) error {
StatisticsWithdrawLog.Info("开始获取当前系统中待审核的内容数量")
result := response.NewResult(c)
amount, err := service.WithdrawService.AuditWaits()
if err != nil {
StatisticsWithdrawLog.Error("获取当前系统中待审核的内容数量出错", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Json(http.StatusOK, "已经获取到指定的统计信息。", fiber.Map{
"amounts": map[string]int64{
"withdraw": amount,
},
})
return result.Success("已经获取到指定的统计信息",
fiber.Map{"withdraw": amount})
}
func statReports(c *fiber.Ctx) error {
@@ -42,28 +47,35 @@ func statReports(c *fiber.Ctx) error {
if session.Type != 0 {
enterprises, err = service.StatisticsService.EnabledEnterprises()
if err != nil {
StatisticsWithdrawLog.Error(err.Error())
return result.Error(http.StatusInternalServerError, err.Error())
}
parks, err = service.StatisticsService.EnabledParks()
if err != nil {
StatisticsWithdrawLog.Error(err.Error())
return result.Error(http.StatusInternalServerError, err.Error())
}
reports, err = service.StatisticsService.ParksNewestState()
//TODO: 2023.07.26 报表数据库结构改变,此处逻辑复杂放在最后处理
reports, err = service.StatisticsService.ParkNewestState()
if err != nil {
StatisticsWithdrawLog.Error(err.Error())
return result.Error(http.StatusInternalServerError, err.Error())
}
} else {
parks, err = service.StatisticsService.EnabledParks(session.Uid)
if err != nil {
StatisticsWithdrawLog.Error(err.Error())
return result.Error(http.StatusInternalServerError, err.Error())
}
reports, err = service.StatisticsService.ParksNewestState(session.Uid)
//TODO: 2023.07.26 报表数据库结构改变,此处逻辑复杂放在最后处理
reports, err = service.StatisticsService.ParkNewestState(session.Uid)
if err != nil {
StatisticsWithdrawLog.Error(err.Error())
return result.Error(http.StatusInternalServerError, err.Error())
}
}
return result.Json(http.StatusOK, "已经完成园区报告的统计。", fiber.Map{
return result.Success("已经完成园区报告的统计。", fiber.Map{
"statistics": fiber.Map{
"enterprises": enterprises,
"parks": parks,

View File

@@ -28,6 +28,11 @@ func InitializeTenementHandler(router *fiber.App) {
router.Post("/tenement/:pid/:tid/move/out", security.EnterpriseAuthorize, moveOutTenement)
router.Post("/tenement/:pid", security.EnterpriseAuthorize, addTenement)
router.Post("/tenement/:pid/:tid/binding", security.EnterpriseAuthorize, bindMeterToTenement)
//TODO: 2023-07-19再apiFox上该请求是个PUT请求后端接收是个POST请求不知道是否有误或是缺少对应请求apiFox测试请求返回值为405
router.Post("/tenement/:pid/:tid/move/out", security.EnterpriseAuthorize, moveOutTenement)
router.Post("/tenement/:pid", security.EnterpriseAuthorize, addTenement)
router.Post("/tenement/:pid/:tid/binding", security.EnterpriseAuthorize, bindMeterToTenement)
//TODO: 2023-07-19再apiFox上该请求是个PUT请求后端接收是个POST请求不知道是否有误或是缺少对应请求apiFox测试请求返回值为405
router.Post("/tenement/:pid/:tid/binding/:code/unbind", security.EnterpriseAuthorize, unbindMeterFromTenement)
}

View File

@@ -18,8 +18,6 @@ import (
"go.uber.org/zap"
)
var userLog = logger.Named("Handler", "User")
func InitializeUserHandlers(router *fiber.App) {
router.Delete("/login", security.MustAuthenticated, doLogout)
router.Post("/login", doLogin)
@@ -35,6 +33,8 @@ func InitializeUserHandlers(router *fiber.App) {
router.Delete("/password/:uid", security.OPSAuthorize, invalidUserPassword)
}
var userLog = logger.Named("Handler", "User")
type _LoginForm struct {
Username string `json:"uname"`
Password string `json:"upass"`
@@ -71,7 +71,6 @@ func doLogin(c *fiber.Ctx) error {
}
return result.LoginSuccess(session)
}
func doLogout(c *fiber.Ctx) error {
result := response.NewResult(c)
session, err := _retreiveSession(c)

View File

@@ -2,18 +2,134 @@ package controller
import (
"electricity_bill_calc/logger"
"electricity_bill_calc/repository"
"electricity_bill_calc/response"
"electricity_bill_calc/security"
"electricity_bill_calc/vo"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
"net/http"
)
var withdrawLog = logger.Named("Handler", "Report")
var withdrawLog = logger.Named("Handler", "Withdraw")
func InitializewithdrawHandlers(router *fiber.App) {
router.Put("/withdraw/:rid", security.EnterpriseAuthorize, changeReportWithdraw)
func InitializeWithdrawHandlers(router *fiber.App) {
router.Get("/withdraw", security.OPSAuthorize, withdraw)
router.Put("/withdraw/:rid", security.OPSAuthorize, reviewRequestWithdraw)
router.Delete("/withdraw/:rid", security.EnterpriseAuthorize, recallReport)
}
func changeReportWithdraw(ctx *fiber.Ctx) error {
//result := response.NewResult(ctx)
//reportId := ctx.Params("rid")
return nil
// 用于分页检索用户的核算报表
func withdraw(c *fiber.Ctx) error {
//记录日志
withdrawLog.Info("带分页的待审核的核算撤回申请列表")
//获取请求参数
result := response.NewResult(c)
keyword := c.Query("keyword", "")
page := c.QueryInt("page", 1)
withdrawLog.Info("参数为: ", zap.String("keyword", keyword), zap.Int("page", page))
//中间数据库操作暂且省略。。。。
//首先进行核算报表的分页查询
withdraws, total, err := repository.WithdrawRepository.FindWithdraw(uint(page), &keyword)
if err != nil {
withdrawLog.Error("检索用户核算报表失败。", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
//TODO: 2023-07-18 此处返回值是个示例,具体返回值需要查询数据库(完成)
return result.Success(
"withdraw请求成功",
response.NewPagedResponse(page, total).ToMap(),
fiber.Map{"records": withdraws},
)
}
// 用于审核撤回报表
func reviewRequestWithdraw(c *fiber.Ctx) error {
Rid := c.Params("rid", "")
Data := new(vo.ReviewWithdraw)
result := response.NewResult(c)
if err := c.BodyParser(&Data); err != nil {
withdrawLog.Error("无法解析审核指定报表的请求数据", zap.Error(err))
return result.BadRequest("无法解析审核指定报表的请求数据。")
}
if Data.Audit == true { //审核通过
ok, err := repository.WithdrawRepository.ReviewTrueReportWithdraw(Rid)
if err != nil {
withdrawLog.Error("审核同意撤回报表失败")
return result.Error(http.StatusInternalServerError, err.Error())
}
if !ok {
withdrawLog.Error("审核同意撤回报表失败")
return result.NotAccept("审核同意撤回报表失败")
} else {
return result.Success("审核同意撤回报表成功!")
}
} else { //审核不通过
ok, err := repository.WithdrawRepository.ReviewFalseReportWithdraw(Rid)
if err != nil {
withdrawLog.Error("审核拒绝撤回报表失败")
return result.Error(http.StatusInternalServerError, err.Error())
}
if !ok {
withdrawLog.Error("审核拒绝撤回报表失败")
return result.NotAccept("审核拒绝撤回报表失败")
} else {
return result.Success("审核拒绝撤回报表成功!")
}
}
}
// 用于撤回电费核算
func recallReport(c *fiber.Ctx) error {
// 获取用户会话信息和参数
rid := c.Params("rid", "")
result := response.NewResult(c)
session, err := _retreiveSession(c)
if err != nil {
withdrawLog.Error("无法获取当前用户的会话。")
return result.Unauthorized(err.Error())
}
// 检查指定报表的所属情况
isBelongsTo, err := repository.ReportRepository.IsBelongsTo(rid, session.Uid)
if err != nil {
withdrawLog.Error("检查报表所属情况出现错误。", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
if err == nil && isBelongsTo == true {
// 判断指定报表是否是当前园区的最后一张报表
isLastReport, err := repository.ReportRepository.IsLastReport(rid)
if err != nil {
withdrawLog.Error("判断指定报表是否为当前园区的最后一张报表时出错", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
if err == nil && isLastReport == true {
// 申请撤回指定的核算报表
//TODO: 2023.07.25 申请撤回指定核算报表,正确状态未处理(完成)
ok, err := repository.ReportRepository.ApplyWithdrawReport(rid)
if err != nil {
withdrawLog.Error("申请撤回指定核算报表出错", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
if ok {
withdrawLog.Info("申请撤回指定核算报表成功")
return result.Success("申请撤回指定核算报表成功")
}
} else {
withdrawLog.Info("当前报表不是当前园区的最后一张报表")
return result.Error(http.StatusForbidden, "当前报表不是当前园区的最后一张报表")
}
} else {
withdrawLog.Info("指定的核算报表不属于当前用户。")
return result.Error(http.StatusForbidden, "指定的核算报表不属于当前用户")
}
return result.Error(http.StatusInternalServerError, "其他错误")
}