diff --git a/controller/statistics.go b/controller/statistics.go new file mode 100644 index 0000000..9a783b7 --- /dev/null +++ b/controller/statistics.go @@ -0,0 +1,80 @@ +package controller + +import ( + "electricity_bill_calc/model" + "electricity_bill_calc/response" + "electricity_bill_calc/security" + "electricity_bill_calc/service" + "net/http" + + "github.com/gin-gonic/gin" +) + +func InitializeStatisticsController(router *gin.Engine) { + router.GET("/audits", security.OPSAuthorize, currentAuditAmount) + router.GET("/stat/reports", security.MustAuthenticated, statReports) +} + +func currentAuditAmount(c *gin.Context) { + result := response.NewResult(c) + amount, err := service.WithdrawService.AuditWaits() + if err != nil { + result.Error(http.StatusInternalServerError, err.Error()) + return + } + result.Json(http.StatusOK, "已经获取到指定的统计信息。", gin.H{ + "amounts": map[string]int64{ + "withdraw": amount, + }, + }) +} + +func statReports(c *gin.Context) { + result := response.NewResult(c) + session, err := _retreiveSession(c) + if err != nil { + result.Unauthorized(err.Error()) + return + } + var ( + enterprises int64 = 0 + parks int64 = 0 + reports []model.ParkPeriodStatistics + ) + if session.Type != 0 { + enterprises, err = service.StatisticsService.EnabledEnterprises() + if err != nil { + result.Error(http.StatusInternalServerError, err.Error()) + return + } + parks, err = service.StatisticsService.EnabledParks() + if err != nil { + result.Error(http.StatusInternalServerError, err.Error()) + return + } + reports, err = service.StatisticsService.ParksNewestState() + if err != nil { + result.Error(http.StatusInternalServerError, err.Error()) + return + } + } else { + parks, err = service.StatisticsService.EnabledParks(session.Uid) + if err != nil { + result.Error(http.StatusInternalServerError, err.Error()) + return + } + reports, err = service.StatisticsService.ParksNewestState(session.Uid) + if err != nil { + result.Error(http.StatusInternalServerError, err.Error()) + return + } + } + + result.Json(http.StatusOK, "已经完成园区报告的统计。", gin.H{ + "statistics": gin.H{ + "enterprises": enterprises, + "parks": parks, + "reports": reports, + }, + }) +} diff --git a/controller/user.go b/controller/user.go index e7b579e..f17af0a 100644 --- a/controller/user.go +++ b/controller/user.go @@ -28,6 +28,7 @@ func InitializeUserController(router *gin.Engine) { router.POST("/enterprise", security.OPSAuthorize, createEnterpriseAccount) router.PUT("/account/:uid", security.OPSAuthorize, modifyAccountDetail) router.GET("/enterprise/quick/search", security.OPSAuthorize, quickSearchEnterprise) + router.GET("/expiration", security.EnterpriseAuthorize, fetchExpiration) } type _LoginFormData struct { @@ -348,3 +349,18 @@ func quickSearchEnterprise(c *gin.Context) { } result.Json(http.StatusOK, "已查询到存在符合条件的企业", gin.H{"users": searchResult}) } + +func fetchExpiration(c *gin.Context) { + result := response.NewResult(c) + session, err := _retreiveSession(c) + if err != nil { + result.Unauthorized(err.Error()) + return + } + user, err := service.UserService.FetchUserDetail(session.Uid) + if err != nil { + result.NotFound(err.Error()) + return + } + result.Json(http.StatusOK, "已经取得用户的服务期限信息", gin.H{"expiration": user.ServiceExpiration.Format("2006-01-02")}) +} diff --git a/model/park.go b/model/park.go index 2f53e9d..9002df3 100644 --- a/model/park.go +++ b/model/park.go @@ -1,6 +1,8 @@ package model import ( + "time" + "github.com/shopspring/decimal" ) @@ -46,3 +48,9 @@ type ParkSimplified struct { func (ParkSimplified) TableName() string { return "park" } + +type ParkPeriodStatistics struct { + Id string `xorm:"varchar(120) not null" json:"id"` + Name string `xorm:"varchar(120) not null" json:"name"` + Period *time.Time `xorm:"date" json:"period" time_format:"simple_date" time_location:"shanghai"` +} diff --git a/router/router.go b/router/router.go index 0ed81ff..87c8212 100644 --- a/router/router.go +++ b/router/router.go @@ -24,6 +24,7 @@ func Router() *gin.Engine { controller.InitializeReportController(router) controller.InitializeEndUserController(router) controller.InitializeWithdrawController(router) + controller.InitializeStatisticsController(router) return router } diff --git a/service/statistics.go b/service/statistics.go new file mode 100644 index 0000000..a3730e8 --- /dev/null +++ b/service/statistics.go @@ -0,0 +1,62 @@ +package service + +import ( + "electricity_bill_calc/global" + "electricity_bill_calc/model" + + "github.com/samber/lo" + "xorm.io/builder" +) + +type _StatisticsService struct{} + +var StatisticsService _StatisticsService + +func (_StatisticsService) EnabledEnterprises() (int64, error) { + return global.DBConn. + Table(new(model.User)). + Where(builder.Eq{"type": 0, "enabled": true}). + Count() +} + +func (_StatisticsService) EnabledParks(userIds ...string) (int64, error) { + cond := builder.NewCond().And(builder.Eq{"enabled": true}) + if len(userIds) > 0 { + cond = cond.And(builder.Eq{"user_id": userIds}) + } + return global.DBConn. + Table(new(model.Park)). + Where(cond). + Count() +} + +func (_StatisticsService) ParksNewestState(userIds ...string) ([]model.ParkPeriodStatistics, error) { + cond := builder.NewCond().And(builder.Eq{"p.enabled": true, "r.published": true}) + if len(userIds) > 0 { + cond = cond.And(builder.Eq{"p.user_id": userIds}) + } + parks := make([]model.ParkPeriodStatistics, 0) + groupedParks := make(map[string]model.ParkPeriodStatistics, 0) + err := global.DBConn. + Table("park").Alias("p"). + Join("LEFT", []string{"report", "r"}, "r.park_id=p.id"). + Where(cond). + Cols("p.id", "p.name", "r.period"). + Find(&parks) + if err != nil { + return make([]model.ParkPeriodStatistics, 0), err + } + for _, p := range parks { + if c, ok := groupedParks[p.Id]; ok { + if c.Period != nil && p.Period != nil && p.Period.After(*c.Period) { + groupedParks[p.Id] = p + } + if c.Period == nil && p.Period != nil { + groupedParks[p.Id] = p + } + } else { + groupedParks[p.Id] = p + } + } + return lo.Values(groupedParks), nil +} diff --git a/service/withdraw.go b/service/withdraw.go index a8e6e2f..3c519cf 100644 --- a/service/withdraw.go +++ b/service/withdraw.go @@ -92,6 +92,7 @@ func (_WithdrawService) FetchPagedWithdrawApplies(page int, keyword string) ([]m Find(&reports) return reports, total, err } + func (_WithdrawService) AuditWithdraw(reportId string, granted bool) error { var report = new(model.Report) has, err := global.DBConn.ID(reportId).NoAutoCondition().Get(report) @@ -109,3 +110,12 @@ func (_WithdrawService) AuditWithdraw(reportId string, granted bool) error { _, err = global.DBConn.ID(report.Id).Cols("withdraw", "last_withdraw_audit_at", "published").Update(report) return err } + +func (_WithdrawService) AuditWaits() (int64, error) { + cond := builder.NewCond() + cond = cond.And(builder.Eq{"withdraw": model.REPORT_WITHDRAW_APPLIED}) + return global.DBConn. + Table(new(model.JoinedReportForWithdraw)). + Where(cond). + Count() +}