181 lines
5.5 KiB
Go
181 lines
5.5 KiB
Go
package financeapplication
|
|
|
|
import (
|
|
"errors"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"hyapp-admin-server/internal/middleware"
|
|
"hyapp-admin-server/internal/model"
|
|
"hyapp-admin-server/internal/modules/shared"
|
|
"hyapp-admin-server/internal/repository"
|
|
"hyapp-admin-server/internal/response"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type Handler struct {
|
|
service *Service
|
|
audit shared.OperationLogger
|
|
}
|
|
|
|
func New(store *repository.Store, audit shared.OperationLogger, options ...Option) *Handler {
|
|
return &Handler{service: NewService(store, options...), audit: audit}
|
|
}
|
|
|
|
func (h *Handler) ListApplications(c *gin.Context) {
|
|
options := shared.ListOptions(c)
|
|
items, total, err := h.service.ListApplications(repository.FinanceApplicationListOptions{
|
|
Page: options.Page,
|
|
PageSize: options.PageSize,
|
|
AppCode: firstQuery(c, "app_code", "appCode"),
|
|
Operation: firstQuery(c, "operation"),
|
|
Status: options.Status,
|
|
Keyword: options.Keyword,
|
|
})
|
|
if err != nil {
|
|
response.ServerError(c, "获取财务申请列表失败")
|
|
return
|
|
}
|
|
response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: total})
|
|
}
|
|
|
|
func (h *Handler) ListMyApplications(c *gin.Context) {
|
|
options := shared.ListOptions(c)
|
|
items, total, err := h.service.ListMyApplications(shared.ActorFromContext(c), repository.FinanceApplicationListOptions{
|
|
Page: options.Page,
|
|
PageSize: options.PageSize,
|
|
AppCode: firstQuery(c, "app_code", "appCode"),
|
|
Operation: firstQuery(c, "operation"),
|
|
Status: options.Status,
|
|
Keyword: options.Keyword,
|
|
})
|
|
if err != nil {
|
|
writeServiceError(c, err, "获取我的财务申请列表失败")
|
|
return
|
|
}
|
|
response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: total})
|
|
}
|
|
|
|
func (h *Handler) CreateApplication(c *gin.Context) {
|
|
var req createApplicationRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "财务申请参数不正确")
|
|
return
|
|
}
|
|
item, err := h.service.CreateApplication(c.Request.Context(), shared.ActorFromContext(c), req)
|
|
if err != nil {
|
|
writeServiceError(c, err, "发起财务申请失败")
|
|
return
|
|
}
|
|
shared.OperationLogWithResourceID(c, h.audit, "create-finance-application", "admin_finance_applications", idString(item.ID), "success", item.Operation)
|
|
response.Created(c, item)
|
|
}
|
|
|
|
func (h *Handler) ApproveApplication(c *gin.Context) {
|
|
h.auditApplication(c, model.FinanceApplicationStatusApproved)
|
|
}
|
|
|
|
func (h *Handler) RejectApplication(c *gin.Context) {
|
|
h.auditApplication(c, model.FinanceApplicationStatusRejected)
|
|
}
|
|
|
|
func (h *Handler) AuditApplication(c *gin.Context) {
|
|
var req struct {
|
|
Decision string `json:"decision"`
|
|
AuditRemark string `json:"auditRemark"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "审核参数不正确")
|
|
return
|
|
}
|
|
switch strings.TrimSpace(req.Decision) {
|
|
case model.FinanceApplicationStatusApproved:
|
|
h.auditApplicationWithRemark(c, model.FinanceApplicationStatusApproved, req.AuditRemark)
|
|
case model.FinanceApplicationStatusRejected:
|
|
h.auditApplicationWithRemark(c, model.FinanceApplicationStatusRejected, req.AuditRemark)
|
|
default:
|
|
response.BadRequest(c, "审核结果不正确")
|
|
}
|
|
}
|
|
|
|
func (h *Handler) auditApplication(c *gin.Context, decision string) {
|
|
var req auditApplicationRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "审核参数不正确")
|
|
return
|
|
}
|
|
h.auditApplicationWithRemark(c, decision, req.AuditRemark)
|
|
}
|
|
|
|
func (h *Handler) auditApplicationWithRemark(c *gin.Context, decision string, remark string) {
|
|
id, ok := shared.ParseID(c, "application_id")
|
|
if !ok {
|
|
return
|
|
}
|
|
var (
|
|
item *applicationDTO
|
|
err error
|
|
)
|
|
if decision == model.FinanceApplicationStatusApproved {
|
|
item, err = h.service.ApproveApplication(c.Request.Context(), shared.ActorFromContext(c), id, remark, middleware.CurrentRequestID(c))
|
|
} else {
|
|
item, err = h.service.RejectApplication(c.Request.Context(), shared.ActorFromContext(c), id, remark, middleware.CurrentRequestID(c))
|
|
}
|
|
if err != nil {
|
|
writeServiceError(c, err, "审核财务申请失败")
|
|
return
|
|
}
|
|
shared.OperationLogWithResourceID(c, h.audit, "audit-finance-application", "admin_finance_applications", idString(item.ID), "success", decision)
|
|
response.OK(c, item)
|
|
}
|
|
|
|
func writeServiceError(c *gin.Context, err error, fallback string) {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
response.NotFound(c, "财务申请不存在")
|
|
return
|
|
}
|
|
if errors.Is(err, repository.ErrFinanceApplicationAlreadyAudited) {
|
|
response.BadRequest(c, "申请已审核")
|
|
return
|
|
}
|
|
switch err.Error() {
|
|
case "没有操作权限":
|
|
response.Forbidden(c, err.Error())
|
|
case "admin store is not configured", "finance wallet executor is not configured":
|
|
response.ServerError(c, fallback)
|
|
default:
|
|
if status.Code(err) == codes.NotFound {
|
|
response.NotFound(c, err.Error())
|
|
return
|
|
}
|
|
if st, ok := status.FromError(err); ok && strings.TrimSpace(st.Message()) != "" {
|
|
switch st.Code() {
|
|
case codes.PermissionDenied:
|
|
response.Forbidden(c, st.Message())
|
|
return
|
|
case codes.InvalidArgument, codes.FailedPrecondition, codes.AlreadyExists, codes.Aborted, codes.ResourceExhausted:
|
|
response.BadRequest(c, st.Message())
|
|
return
|
|
}
|
|
}
|
|
response.BadRequest(c, err.Error())
|
|
}
|
|
}
|
|
|
|
func firstQuery(c *gin.Context, keys ...string) string {
|
|
for _, key := range keys {
|
|
if value := strings.TrimSpace(c.Query(key)); value != "" {
|
|
return value
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func idString(id uint) string {
|
|
return strconv.FormatUint(uint64(id), 10)
|
|
}
|