forked from free-lancers/electricity_bill_calc_service
		
	enhance(fee):基本完成物业附加费部分的运算。
This commit is contained in:
		| @@ -6,9 +6,11 @@ import ( | |||||||
| 	"electricity_bill_calc/security" | 	"electricity_bill_calc/security" | ||||||
| 	"electricity_bill_calc/service" | 	"electricity_bill_calc/service" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"strconv" | ||||||
|  |  | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
| 	"github.com/jinzhu/copier" | 	"github.com/jinzhu/copier" | ||||||
|  | 	"github.com/samber/lo" | ||||||
| 	"github.com/shopspring/decimal" | 	"github.com/shopspring/decimal" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -18,6 +20,7 @@ func InitializeMaintenanceFeeController(router *gin.Engine) { | |||||||
| 	router.PUT("/maintenance/fee/:mid", security.EnterpriseAuthorize, modifyMaintenanceFeeRecord) | 	router.PUT("/maintenance/fee/:mid", security.EnterpriseAuthorize, modifyMaintenanceFeeRecord) | ||||||
| 	router.PUT("/maintenance/fee/:mid/enabled", security.EnterpriseAuthorize, changeMaintenanceFeeState) | 	router.PUT("/maintenance/fee/:mid/enabled", security.EnterpriseAuthorize, changeMaintenanceFeeState) | ||||||
| 	router.DELETE("/maintenance/fee/:mid", security.EnterpriseAuthorize, deleteMaintenanceFee) | 	router.DELETE("/maintenance/fee/:mid", security.EnterpriseAuthorize, deleteMaintenanceFee) | ||||||
|  | 	router.GET("/additional/charges", security.MustAuthenticated, statAdditionalCharges) | ||||||
| } | } | ||||||
|  |  | ||||||
| func ensureMaintenanceFeeBelongs(c *gin.Context, result *response.Result, requestMaintenanceFeeId string) bool { | func ensureMaintenanceFeeBelongs(c *gin.Context, result *response.Result, requestMaintenanceFeeId string) bool { | ||||||
| @@ -46,34 +49,51 @@ func listMaintenanceFees(c *gin.Context) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	requestPark := c.DefaultQuery("park", "") | 	requestPark := c.DefaultQuery("park", "") | ||||||
|  | 	requestPeriod := c.DefaultQuery("period", "") | ||||||
|  | 	requestPage, err := strconv.Atoi(c.DefaultQuery("page", "1")) | ||||||
|  | 	if err != nil { | ||||||
|  | 		result.Error(http.StatusInternalServerError, "不能解析给定的参数[page]。") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
| 	if len(requestPark) > 0 { | 	if len(requestPark) > 0 { | ||||||
| 		if !ensureParkBelongs(c, result, requestPark) { | 		if !ensureParkBelongs(c, result, requestPark) { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		fees, err := service.MaintenanceFeeService.ListMaintenanceFees([]string{requestPark}) | 		fees, total, err := service.MaintenanceFeeService.ListMaintenanceFees([]string{requestPark}, requestPeriod, requestPage) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			result.Error(http.StatusInternalServerError, err.Error()) | 			result.Error(http.StatusInternalServerError, err.Error()) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		result.Json(http.StatusOK, "已获取指定园区下的维护费记录", gin.H{"fees": fees}) | 		result.Json( | ||||||
|  | 			http.StatusOK, | ||||||
|  | 			"已获取指定园区下的维护费记录", | ||||||
|  | 			response.NewPagedResponse(requestPage, total).ToMap(), | ||||||
|  | 			gin.H{"fees": fees}, | ||||||
|  | 		) | ||||||
| 	} else { | 	} else { | ||||||
| 		parkIds, err := service.ParkService.AllParkIds(userSession.Uid) | 		parkIds, err := service.ParkService.AllParkIds(userSession.Uid) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			result.Error(http.StatusInternalServerError, err.Error()) | 			result.Error(http.StatusInternalServerError, err.Error()) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		fees, err := service.MaintenanceFeeService.ListMaintenanceFees(parkIds) | 		fees, total, err := service.MaintenanceFeeService.ListMaintenanceFees(parkIds, requestPeriod, requestPage) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			result.Error(http.StatusInternalServerError, err.Error()) | 			result.Error(http.StatusInternalServerError, err.Error()) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		result.Json(http.StatusOK, "已获取指定用户下的所有维护费记录。", gin.H{"fees": fees}) | 		result.Json( | ||||||
|  | 			http.StatusOK, | ||||||
|  | 			"已获取指定用户下的所有维护费记录。", | ||||||
|  | 			response.NewPagedResponse(requestPage, total).ToMap(), | ||||||
|  | 			gin.H{"fees": fees}, | ||||||
|  | 		) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| type _FeeCreationFormData struct { | type _FeeCreationFormData struct { | ||||||
| 	ParkId string          `json:"parkId" form:"parkId"` | 	ParkId string          `json:"parkId" form:"parkId"` | ||||||
| 	Name   string          `json:"name" form:"name"` | 	Name   string          `json:"name" form:"name"` | ||||||
|  | 	Period string          `json:"period" form:"period"` | ||||||
| 	Fee    decimal.Decimal `json:"fee" form:"fee"` | 	Fee    decimal.Decimal `json:"fee" form:"fee"` | ||||||
| 	Memo   *string         `json:"memo" form:"memo"` | 	Memo   *string         `json:"memo" form:"memo"` | ||||||
| } | } | ||||||
| @@ -152,3 +172,38 @@ func deleteMaintenanceFee(c *gin.Context) { | |||||||
| 	} | 	} | ||||||
| 	result.Deleted("指定维护费条目已删除。") | 	result.Deleted("指定维护费条目已删除。") | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func statAdditionalCharges(c *gin.Context) { | ||||||
|  | 	result := response.NewResult(c) | ||||||
|  | 	session, err := _retreiveSession(c) | ||||||
|  | 	if err != nil { | ||||||
|  | 		result.Unauthorized(err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	requestUser := lo. | ||||||
|  | 		If(session.Type == model.USER_TYPE_ENT, session.Uid). | ||||||
|  | 		Else(c.DefaultQuery("user", "")) | ||||||
|  | 	requestPark := c.DefaultQuery("park", "") | ||||||
|  | 	if len(requestPark) > 0 && session.Type == model.USER_TYPE_ENT { | ||||||
|  | 		if !ensureParkBelongs(c, result, requestPark) { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	period := c.DefaultQuery("period", "") | ||||||
|  | 	keyword := c.DefaultQuery("keyword", "") | ||||||
|  | 	requestPage, err := strconv.Atoi(c.DefaultQuery("page", "1")) | ||||||
|  | 	if err != nil { | ||||||
|  | 		result.Error(http.StatusInternalServerError, "不能解析给定的参数[page]。") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	fees, total, err := service.MaintenanceFeeService.QueryAdditiionalCharges(requestUser, requestPark, period, keyword, requestPage) | ||||||
|  | 	if err != nil { | ||||||
|  | 		result.Error(http.StatusInternalServerError, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	result.Success( | ||||||
|  | 		"已经成功获取到物业附加费的统计记录。", | ||||||
|  | 		response.NewPagedResponse(requestPage, total).ToMap(), | ||||||
|  | 		gin.H{"charges": fees}, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -11,7 +11,6 @@ import ( | |||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/fufuok/utils" |  | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
| 	"github.com/jinzhu/copier" | 	"github.com/jinzhu/copier" | ||||||
| 	"github.com/samber/lo" | 	"github.com/samber/lo" | ||||||
| @@ -26,12 +25,6 @@ func InitializeReportController(router *gin.Engine) { | |||||||
| 	router.PUT("/report/:rid/summary", security.EnterpriseAuthorize, fillReportSummary) | 	router.PUT("/report/:rid/summary", security.EnterpriseAuthorize, fillReportSummary) | ||||||
| 	router.GET("/report/:rid/summary/calculate", security.EnterpriseAuthorize, testCalculateReportSummary) | 	router.GET("/report/:rid/summary/calculate", security.EnterpriseAuthorize, testCalculateReportSummary) | ||||||
| 	router.POST("/report/:rid/summary/calculate", security.EnterpriseAuthorize, progressReportSummary) | 	router.POST("/report/:rid/summary/calculate", security.EnterpriseAuthorize, progressReportSummary) | ||||||
| 	router.GET("/report/:rid/maintenance", security.EnterpriseAuthorize, fetchWillDilutedFees) |  | ||||||
| 	router.POST("/report/:rid/maintenance", security.EnterpriseAuthorize, createTemporaryWillDilutedFee) |  | ||||||
| 	router.POST("/report/:rid/maintenance/import", security.EnterpriseAuthorize, importPredefinedMaintenanceFees) |  | ||||||
| 	router.PUT("/report/:rid/maintenance/:mid", security.EnterpriseAuthorize, modifyWillDilutedFee) |  | ||||||
| 	router.DELETE("/report/:rid/maintenance/:mid", security.EnterpriseAuthorize, deleteTemporaryWillDilutedFee) |  | ||||||
| 	router.PUT("/report/:rid/step/diluted/fees", security.EnterpriseAuthorize, progressReportWillDilutedFee) |  | ||||||
| 	router.PUT("/report/:rid/step/meter/register", security.EnterpriseAuthorize, progressEndUserRegister) | 	router.PUT("/report/:rid/step/meter/register", security.EnterpriseAuthorize, progressEndUserRegister) | ||||||
| 	router.POST("/report/:rid/publish", security.EnterpriseAuthorize, publishReport) | 	router.POST("/report/:rid/publish", security.EnterpriseAuthorize, publishReport) | ||||||
| 	router.GET("/reports", security.MustAuthenticated, searchReports) | 	router.GET("/reports", security.MustAuthenticated, searchReports) | ||||||
| @@ -208,161 +201,6 @@ func progressReportSummary(c *gin.Context) { | |||||||
| 	result.Success("已经完成园区概况的计算,并可以进行到下一步骤。") | 	result.Success("已经完成园区概况的计算,并可以进行到下一步骤。") | ||||||
| } | } | ||||||
|  |  | ||||||
| func fetchWillDilutedFees(c *gin.Context) { |  | ||||||
| 	result := response.NewResult(c) |  | ||||||
| 	requestReportId := c.Param("rid") |  | ||||||
| 	if !ensureReportBelongs(c, result, requestReportId) { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	fees, err := service.ReportService.FetchWillDulutedMaintenanceFees(requestReportId) |  | ||||||
| 	if err != nil { |  | ||||||
| 		result.NotFound(err.Error()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	result.Json(http.StatusOK, "待摊薄费用已经获取到。", gin.H{"fees": fees}) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type DilutedFeeCreationFormData struct { |  | ||||||
| 	ParkId string          `json:"parkId" form:"parkId"` |  | ||||||
| 	Name   string          `json:"name" form:"name"` |  | ||||||
| 	Fee    decimal.Decimal `json:"fee" form:"fee"` |  | ||||||
| 	Memo   *string         `json:"memo" form:"memo"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func createTemporaryWillDilutedFee(c *gin.Context) { |  | ||||||
| 	result := response.NewResult(c) |  | ||||||
| 	requestReportId := c.Param("rid") |  | ||||||
| 	if !ensureReportBelongs(c, result, requestReportId) { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	formData := new(DilutedFeeCreationFormData) |  | ||||||
| 	c.BindJSON(formData) |  | ||||||
| 	report, err := service.ReportService.RetreiveReportIndex(requestReportId) |  | ||||||
| 	if err != nil { |  | ||||||
| 		result.NotFound(err.Error()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	if formData.ParkId != report.ParkId { |  | ||||||
| 		result.NotAccept("选择的园区与公示报表所属的园区不一致。") |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	newWillDilutedFee := new(model.WillDilutedFee) |  | ||||||
| 	copier.Copy(newWillDilutedFee, formData) |  | ||||||
| 	newWillDilutedFee.ReportId = report.Id |  | ||||||
| 	err = service.ReportService.CreateTemporaryWillDilutedMaintenanceFee(*newWillDilutedFee) |  | ||||||
| 	if err != nil { |  | ||||||
| 		result.Error(http.StatusInternalServerError, err.Error()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	result.Created("公示报表中所要使用的临时待摊薄费用已添加。") |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func importPredefinedMaintenanceFees(c *gin.Context) { |  | ||||||
| 	result := response.NewResult(c) |  | ||||||
| 	requestReportId := c.Param("rid") |  | ||||||
| 	if !ensureReportBelongs(c, result, requestReportId) { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	report, err := service.ReportService.RetreiveReportIndex(requestReportId) |  | ||||||
| 	if err != nil { |  | ||||||
| 		result.NotFound(err.Error()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	maintenanceFees, err := service.MaintenanceFeeService.ListMaintenanceFees([]string{report.ParkId}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		result.Error(http.StatusInternalServerError, err.Error()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	enabledMaintenanceFees := lo.Filter( |  | ||||||
| 		maintenanceFees, |  | ||||||
| 		func(elem model.MaintenanceFee, index int) bool { |  | ||||||
| 			return elem.Enabled |  | ||||||
| 		}, |  | ||||||
| 	) |  | ||||||
| 	if len(enabledMaintenanceFees) == 0 { |  | ||||||
| 		result.NotFound("没有找到可供导入的配电维护费记录。") |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	dilutedFees := lo.Map( |  | ||||||
| 		enabledMaintenanceFees, |  | ||||||
| 		func(elem model.MaintenanceFee, index int) model.WillDilutedFee { |  | ||||||
| 			fee := &model.WillDilutedFee{ |  | ||||||
| 				Id:       utils.UUIDString(), |  | ||||||
| 				ReportId: report.Id, |  | ||||||
| 				SourceId: lo.ToPtr(elem.Id), |  | ||||||
| 				Name:     elem.Name, |  | ||||||
| 				Fee:      elem.Fee, |  | ||||||
| 				Memo:     elem.Memo, |  | ||||||
| 			} |  | ||||||
| 			return *fee |  | ||||||
| 		}, |  | ||||||
| 	) |  | ||||||
| 	err = service.ReportService.BatchSaveMaintenanceFee(report.Id, dilutedFees) |  | ||||||
| 	if err != nil { |  | ||||||
| 		result.Error(http.StatusInternalServerError, err.Error()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	result.Created("预定义的配电维护费已经导入。") |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type DilutedFeeModificationFormData struct { |  | ||||||
| 	Name *string         `json:"name,omitempty" form:"name"` |  | ||||||
| 	Fee  decimal.Decimal `json:"fee" form:"fee"` |  | ||||||
| 	Memo *string         `json:"memo,omitempty" form:"memo"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func modifyWillDilutedFee(c *gin.Context) { |  | ||||||
| 	result := response.NewResult(c) |  | ||||||
| 	requestReportId := c.Param("rid") |  | ||||||
| 	if !ensureReportBelongs(c, result, requestReportId) { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	requestFeeId := c.Param("mid") |  | ||||||
| 	formData := new(DilutedFeeModificationFormData) |  | ||||||
| 	c.BindJSON(formData) |  | ||||||
| 	updateValues := tools.ConvertStructToMap(formData) |  | ||||||
| 	err := service.ReportService.UpdateMaintenanceFee(requestFeeId, updateValues) |  | ||||||
| 	if err != nil { |  | ||||||
| 		result.Error(http.StatusInternalServerError, err.Error()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	result.Updated("指定待摊薄费用信息已经更新。") |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func deleteTemporaryWillDilutedFee(c *gin.Context) { |  | ||||||
| 	result := response.NewResult(c) |  | ||||||
| 	requestReportId := c.Param("rid") |  | ||||||
| 	if !ensureReportBelongs(c, result, requestReportId) { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	requestFeeId := c.Param("mid") |  | ||||||
| 	err := service.ReportService.DeleteWillDilutedFee(requestFeeId) |  | ||||||
| 	if err != nil { |  | ||||||
| 		result.Error(http.StatusInternalServerError, err.Error()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	result.Deleted("指定待摊薄费用信息已经删除。") |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func progressReportWillDilutedFee(c *gin.Context) { |  | ||||||
| 	result := response.NewResult(c) |  | ||||||
| 	requestReportId := c.Param("rid") |  | ||||||
| 	if !ensureReportBelongs(c, result, requestReportId) { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	report, err := service.ReportService.RetreiveReportIndex(requestReportId) |  | ||||||
| 	if err != nil { |  | ||||||
| 		result.NotFound(err.Error()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	err = service.ReportService.ProgressReportWillDilutedFee(*report) |  | ||||||
| 	if err != nil { |  | ||||||
| 		result.Error(http.StatusInternalServerError, err.Error()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	result.Success("待摊薄费用编辑步骤已经完成。") |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func progressEndUserRegister(c *gin.Context) { | func progressEndUserRegister(c *gin.Context) { | ||||||
| 	result := response.NewResult(c) | 	result := response.NewResult(c) | ||||||
| 	requestReportId := c.Param("rid") | 	requestReportId := c.Param("rid") | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ type MaintenanceFee struct { | |||||||
| 	Fee                decimal.Decimal `bun:"type:numeric,notnull" json:"fee"` | 	Fee                decimal.Decimal `bun:"type:numeric,notnull" json:"fee"` | ||||||
| 	Memo               *string         `bun:"type:text" json:"memo"` | 	Memo               *string         `bun:"type:text" json:"memo"` | ||||||
| 	Enabled            bool            `bun:",notnull" json:"enabled"` | 	Enabled            bool            `bun:",notnull" json:"enabled"` | ||||||
|  | 	Park               Park            `bun:"rel:belongs-to,join:park_id=id"` | ||||||
| } | } | ||||||
|  |  | ||||||
| var _ bun.BeforeAppendModelHook = (*MaintenanceFee)(nil) | var _ bun.BeforeAppendModelHook = (*MaintenanceFee)(nil) | ||||||
| @@ -34,3 +35,14 @@ func (f *MaintenanceFee) BeforeAppendModel(ctx context.Context, query bun.Query) | |||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type AdditionalCharge struct { | ||||||
|  | 	ParkId          string               `json:"parkId"` | ||||||
|  | 	Period          string               `json:"period"` | ||||||
|  | 	Fee             decimal.Decimal      `json:"fee"` | ||||||
|  | 	Price           decimal.Decimal      `json:"price"` | ||||||
|  | 	QuarterPrice    decimal.Decimal      `json:"quarterPrice"` | ||||||
|  | 	SemiAnnualPrice decimal.Decimal      `json:"semiAnnualPrice"` | ||||||
|  | 	Enterprise      UserDetailSimplified `json:"user"` | ||||||
|  | 	Park            Park                 `json:"park"` | ||||||
|  | } | ||||||
|   | |||||||
| @@ -2,14 +2,17 @@ package service | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"electricity_bill_calc/cache" | 	"electricity_bill_calc/cache" | ||||||
|  | 	"electricity_bill_calc/config" | ||||||
| 	"electricity_bill_calc/exceptions" | 	"electricity_bill_calc/exceptions" | ||||||
| 	"electricity_bill_calc/global" | 	"electricity_bill_calc/global" | ||||||
| 	"electricity_bill_calc/logger" | 	"electricity_bill_calc/logger" | ||||||
| 	"electricity_bill_calc/model" | 	"electricity_bill_calc/model" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  |  | ||||||
|  | 	mapset "github.com/deckarep/golang-set/v2" | ||||||
| 	"github.com/google/uuid" | 	"github.com/google/uuid" | ||||||
| 	"github.com/samber/lo" | 	"github.com/samber/lo" | ||||||
|  | 	"github.com/shopspring/decimal" | ||||||
| 	"github.com/uptrace/bun" | 	"github.com/uptrace/bun" | ||||||
| 	"go.uber.org/zap" | 	"go.uber.org/zap" | ||||||
| ) | ) | ||||||
| @@ -22,9 +25,14 @@ var MaintenanceFeeService = _MaintenanceFeeService{ | |||||||
| 	l: logger.Named("Service", "maintenance"), | 	l: logger.Named("Service", "maintenance"), | ||||||
| } | } | ||||||
|  |  | ||||||
| func (_MaintenanceFeeService) ListMaintenanceFees(pid []string) ([]model.MaintenanceFee, error) { | func (_MaintenanceFeeService) ListMaintenanceFees(pid []string, period string, requestPage int) ([]model.MaintenanceFee, int64, error) { | ||||||
| 	if fees, _ := cache.RetreiveSearch[[]model.MaintenanceFee]("maintenance_fee", pid...); fees != nil { | 	conditions := []string{fmt.Sprintf("%d", requestPage)} | ||||||
| 		return *fees, nil | 	conditions = append(conditions, pid...) | ||||||
|  | 	conditions = append(conditions, period) | ||||||
|  | 	if cachedTotal, err := cache.RetreiveCount("maintenance_fee", conditions...); cachedTotal != -1 && err == nil { | ||||||
|  | 		if fees, _ := cache.RetreiveSearch[[]model.MaintenanceFee]("maintenance_fee", conditions...); fees != nil { | ||||||
|  | 			return *fees, cachedTotal, nil | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var ( | 	var ( | ||||||
| @@ -34,23 +42,30 @@ func (_MaintenanceFeeService) ListMaintenanceFees(pid []string) ([]model.Mainten | |||||||
| 	if len(pid) > 0 { | 	if len(pid) > 0 { | ||||||
| 		cond = cond.Where("park_id in (?)", bun.In(pid)) | 		cond = cond.Where("park_id in (?)", bun.In(pid)) | ||||||
| 	} else { | 	} else { | ||||||
| 		return make([]model.MaintenanceFee, 0), exceptions.NewIllegalArgumentsError("必须给定所要请求的至少一个园区", "park_id") | 		return make([]model.MaintenanceFee, 0), 0, exceptions.NewIllegalArgumentsError("必须给定所要请求的至少一个园区", "park_id") | ||||||
|  | 	} | ||||||
|  | 	if len(period) > 0 { | ||||||
|  | 		cond = cond.Where("period = ?", period) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ctx, cancel := global.TimeoutContext() | 	ctx, cancel := global.TimeoutContext() | ||||||
| 	defer cancel() | 	defer cancel() | ||||||
|  | 	startItem := (requestPage - 1) * config.ServiceSettings.ItemsPageSize | ||||||
| 	err := cond.Order("created_at desc").Scan(ctx) | 	total, err := cond.Order("period desc", "created_at desc"). | ||||||
|  | 		Limit(config.ServiceSettings.ItemsPageSize). | ||||||
|  | 		Offset(startItem). | ||||||
|  | 		ScanAndCount(ctx) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return make([]model.MaintenanceFee, 0), err | 		return make([]model.MaintenanceFee, 0), 0, fmt.Errorf("附加费查询出现错误,%w", err) | ||||||
| 	} | 	} | ||||||
| 	relations := lo.Map(fees, func(f model.MaintenanceFee, _ int) string { | 	relations := lo.Map(fees, func(f model.MaintenanceFee, _ int) string { | ||||||
| 		return fmt.Sprintf("maintenance_fee:%s", f.Id) | 		return fmt.Sprintf("maintenance_fee:%s", f.Id) | ||||||
| 	}) | 	}) | ||||||
| 	relations = append(relations, "maintenance_fee", "park") | 	relations = append(relations, "maintenance_fee", "park") | ||||||
|  |  | ||||||
| 	cache.CacheSearch(fees, relations, "maintenance_fee", pid...) | 	cache.CacheCount(relations, "maintenance_fee", int64(total), conditions...) | ||||||
| 	return fees, nil | 	cache.CacheSearch(fees, relations, "maintenance_fee", conditions...) | ||||||
|  | 	return fees, int64(total), nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (_MaintenanceFeeService) CreateMaintenanceFeeRecord(fee model.MaintenanceFee) error { | func (_MaintenanceFeeService) CreateMaintenanceFeeRecord(fee model.MaintenanceFee) error { | ||||||
| @@ -77,7 +92,7 @@ func (_MaintenanceFeeService) ModifyMaintenanceFee(fee model.MaintenanceFee) err | |||||||
| 		Exec(ctx) | 		Exec(ctx) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if rows, _ := res.RowsAffected(); rows == 0 { | 		if rows, _ := res.RowsAffected(); rows == 0 { | ||||||
| 			return exceptions.NewNotFoundError("未能找到匹配的维护费记录。") | 			return exceptions.NewNotFoundError("未能找到匹配的附加费记录。") | ||||||
| 		} else { | 		} else { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| @@ -96,7 +111,7 @@ func (_MaintenanceFeeService) ChangeMaintenanceFeeState(fid string, state bool) | |||||||
| 		Exec(ctx) | 		Exec(ctx) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if rows, err := res.RowsAffected(); rows == 0 { | 		if rows, err := res.RowsAffected(); rows == 0 { | ||||||
| 			return exceptions.NewNotFoundError("未能找到匹配的维护费记录。") | 			return exceptions.NewNotFoundError("未能找到匹配的附加费记录。") | ||||||
| 		} else { | 		} else { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| @@ -114,7 +129,7 @@ func (_MaintenanceFeeService) DeleteMaintenanceFee(fid string) error { | |||||||
| 		Exec(ctx) | 		Exec(ctx) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if rows, err := res.RowsAffected(); rows == 0 { | 		if rows, err := res.RowsAffected(); rows == 0 { | ||||||
| 			return exceptions.NewNotFoundError("未能找到匹配的维护费记录。") | 			return exceptions.NewNotFoundError("未能找到匹配的附加费记录。") | ||||||
| 		} else { | 		} else { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| @@ -148,8 +163,130 @@ func (_MaintenanceFeeService) EnsureFeeBelongs(uid, mid string) (bool, error) { | |||||||
| 		return acc || false | 		return acc || false | ||||||
| 	}, false) | 	}, false) | ||||||
| 	if !exists { | 	if !exists { | ||||||
| 		return false, exceptions.NewNotFoundError("指定维护费所属园区未找到。") | 		return false, exceptions.NewNotFoundError("指定附加费所属园区未找到。") | ||||||
| 	} | 	} | ||||||
| 	cache.CacheExists([]string{fmt.Sprintf("maintenance_fee:%s", mid), "maintenance_fee", "park"}, "maintenance_fee", mid, uid) | 	cache.CacheExists([]string{fmt.Sprintf("maintenance_fee:%s", mid), "maintenance_fee", "park"}, "maintenance_fee", mid, uid) | ||||||
| 	return exists, nil | 	return exists, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type _FeeStat struct { | ||||||
|  | 	ParkId string | ||||||
|  | 	Period string | ||||||
|  | 	Total  decimal.Decimal | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (f _MaintenanceFeeService) QueryAdditiionalCharges(uid, pid, period, keyword string, requestPage int) ([]model.AdditionalCharge, int64, error) { | ||||||
|  | 	var ( | ||||||
|  | 		conditions = []string{fmt.Sprintf("%d", requestPage)} | ||||||
|  | 		statFees   = make([]_FeeStat, 0) | ||||||
|  | 		cond       = global.DB.NewSelect(). | ||||||
|  | 				Model((*model.MaintenanceFee)(nil)). | ||||||
|  | 				Relation("Park", func(q *bun.SelectQuery) *bun.SelectQuery { | ||||||
|  | 				return q.ExcludeColumn("*") | ||||||
|  | 			}). | ||||||
|  | 			Relation("Park.Enterprise", func(q *bun.SelectQuery) *bun.SelectQuery { | ||||||
|  | 				return q.ExcludeColumn("*") | ||||||
|  | 			}). | ||||||
|  | 			Where("m.enabled = ?", true) | ||||||
|  | 	) | ||||||
|  | 	if len(uid) > 0 { | ||||||
|  | 		cond = cond.Where("park__enterprise.id = ?", uid) | ||||||
|  | 		conditions = append(conditions, uid) | ||||||
|  | 	} else { | ||||||
|  | 		conditions = append(conditions, "_") | ||||||
|  | 	} | ||||||
|  | 	if len(pid) > 0 { | ||||||
|  | 		cond = cond.Where("park.id = ?", pid) | ||||||
|  | 		conditions = append(conditions, pid) | ||||||
|  | 	} else { | ||||||
|  | 		conditions = append(conditions, "_") | ||||||
|  | 	} | ||||||
|  | 	if len(period) > 0 { | ||||||
|  | 		cond = cond.Where("m.period = ?", period) | ||||||
|  | 		conditions = append(conditions, period) | ||||||
|  | 	} else { | ||||||
|  | 		conditions = append(conditions, "_") | ||||||
|  | 	} | ||||||
|  | 	if len(keyword) > 0 { | ||||||
|  | 		keywordCond := "%" + keyword + "%" | ||||||
|  | 		cond = cond.WhereGroup(" and ", func(q *bun.SelectQuery) *bun.SelectQuery { | ||||||
|  | 			return q.Where("park__enterprise.name like ?", keywordCond). | ||||||
|  | 				WhereOr("park__enterprise.abbr like ?", keywordCond). | ||||||
|  | 				WhereOr("park.name like ?", keywordCond). | ||||||
|  | 				WhereOr("park.abbr like ?", keywordCond). | ||||||
|  | 				WhereOr("park.address like ?", keywordCond) | ||||||
|  | 		}) | ||||||
|  | 		conditions = append(conditions, keyword) | ||||||
|  | 	} else { | ||||||
|  | 		conditions = append(conditions, "_") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if cachedTotal, err := cache.RetreiveCount("additional_charge", conditions...); cachedTotal != -1 && err == nil { | ||||||
|  | 		if cachedData, _ := cache.RetreiveSearch[[]model.AdditionalCharge]("additional_charge", conditions...); cachedData != nil { | ||||||
|  | 			return *cachedData, cachedTotal, nil | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	ctx, cancel := global.TimeoutContext(24) | ||||||
|  | 	defer cancel() | ||||||
|  |  | ||||||
|  | 	startItem := (requestPage - 1) * config.ServiceSettings.ItemsPageSize | ||||||
|  |  | ||||||
|  | 	total, err := cond.ColumnExpr("sum(?) as total", bun.Ident("fee")). | ||||||
|  | 		Column("park_id", "period"). | ||||||
|  | 		Group("park_id", "period"). | ||||||
|  | 		Order("period desc"). | ||||||
|  | 		Limit(config.ServiceSettings.ItemsPageSize). | ||||||
|  | 		Offset(startItem). | ||||||
|  | 		ScanAndCount(ctx, &statFees) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return make([]model.AdditionalCharge, 0), 0, fmt.Errorf("获取附加费统计信息出现错误,%w", err) | ||||||
|  | 	} | ||||||
|  | 	parkIds := lo.Reduce( | ||||||
|  | 		statFees, | ||||||
|  | 		func(acc mapset.Set[string], elem _FeeStat, _ int) mapset.Set[string] { | ||||||
|  | 			acc.Add(elem.ParkId) | ||||||
|  | 			return acc | ||||||
|  | 		}, | ||||||
|  | 		mapset.NewSet[string](), | ||||||
|  | 	) | ||||||
|  | 	parks := make([]model.Park, 0) | ||||||
|  | 	err = global.DB.NewSelect().Model(&parks).Relation("Enterprise"). | ||||||
|  | 		Where("p.id in (?)", bun.In(parkIds.ToSlice())). | ||||||
|  | 		Scan(ctx) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return make([]model.AdditionalCharge, 0), 0, fmt.Errorf("获取园区信息出现错误,%w", err) | ||||||
|  | 	} | ||||||
|  | 	f.l.Debug("Park ids", zap.Any("ids", parkIds)) | ||||||
|  | 	f.l.Debug("Check fees", zap.Any("fees", statFees)) | ||||||
|  | 	assembledStat := lo.Reduce( | ||||||
|  | 		statFees, | ||||||
|  | 		func(acc []model.AdditionalCharge, elem _FeeStat, _ int) []model.AdditionalCharge { | ||||||
|  | 			park, has := lo.Find(parks, func(p model.Park) bool { | ||||||
|  | 				return p.Id == elem.ParkId | ||||||
|  | 			}) | ||||||
|  | 			f.l.Debug("Park detection.", zap.Bool("has", has), zap.Any("park", park)) | ||||||
|  | 			if has { | ||||||
|  | 				if !park.Area.Valid || park.Area.Decimal.Equal(decimal.Zero) { | ||||||
|  | 					return acc | ||||||
|  | 				} | ||||||
|  | 				price := elem.Total.Div(park.Area.Decimal).RoundBank(8) | ||||||
|  | 				return append(acc, model.AdditionalCharge{ | ||||||
|  | 					ParkId:          elem.ParkId, | ||||||
|  | 					Period:          elem.Period, | ||||||
|  | 					Fee:             elem.Total, | ||||||
|  | 					Price:           price, | ||||||
|  | 					QuarterPrice:    price.Div(decimal.NewFromInt(4)), | ||||||
|  | 					SemiAnnualPrice: price.Div(decimal.NewFromInt(2)), | ||||||
|  | 					Enterprise:      model.FromUserDetail(*park.Enterprise), | ||||||
|  | 					Park:            park, | ||||||
|  | 				}) | ||||||
|  | 			} else { | ||||||
|  | 				return acc | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  | 		make([]model.AdditionalCharge, 0), | ||||||
|  | 	) | ||||||
|  | 	cache.CacheCount([]string{"maintenance_fee"}, "additional_charge", int64(total), conditions...) | ||||||
|  | 	cache.CacheSearch(assembledStat, []string{"maintenance_fee"}, "additional_charge", conditions...) | ||||||
|  | 	return assembledStat, int64(total), nil | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user