Files
junhong_cmp_fiber/internal/routes/employee_collection.go
break ff1362df3f
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m19s
fix(员工代收款): 修正路由前缀注册方式,消除 /api/admin 根级 /:id 抢占
Register 的 basePath 仅用于生成 OpenAPI 文档,不参与路由注册;员工代收款
三个注册函数把资源前缀传给了 basePath、path 只写相对段,导致
GET /api/admin/:id 与 POST /api/admin/:id/close 落在 /api/admin 根上。
账单单段路径被当作路径 ID 解析返回“无效的路径ID”,并抢占其后注册的
同层单段 GET(/api/admin/refunds、/system-configs 等)。

改为 router.Group(前缀) 注册,与仓库既有写法一致;路由布局与文档路径不变。
2026-09-11 14:40:23 +08:00

150 lines
8.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package routes
import (
"github.com/gofiber/fiber/v2"
"github.com/break/junhong_cmp_fiber/internal/handler/admin"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
"github.com/break/junhong_cmp_fiber/pkg/middleware"
"github.com/break/junhong_cmp_fiber/pkg/openapi"
)
// requireEmployeeCollectionConfigAccess 限制线下收款方式字典维护仅超级管理员可用,
// 非超级管理员与其他不可见资源返回同一禁止访问错误,避免可枚举差异。
func requireEmployeeCollectionConfigAccess(handler fiber.Handler) fiber.Handler {
return func(c *fiber.Ctx) error {
if middleware.GetUserTypeFromContext(c.UserContext()) != constants.UserTypeSuperAdmin {
return errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
}
return handler(c)
}
}
func registerEmployeeCollectionRoutes(router fiber.Router, handler *admin.EmployeeCollectionHandler, doc *openapi.Generator, basePath string) {
// 路由前缀必须交给 GroupRegister 的 basePath 只用于生成 OpenAPI 文档,不参与路由注册,
// 否则相对路径会落到 /api/admin 根上并抢占同层后续路由。
group := router.Group("/employee-collection-payment-methods")
paymentMethodPath := basePath + "/employee-collection-payment-methods"
wrap := requireEmployeeCollectionConfigAccess
Register(group, doc, paymentMethodPath, "GET", "", handler.ListPaymentMethods, RouteSpec{
Summary: "查询线下收款方式",
Description: "超级管理员可查询全部字典项;其他后台账号仅返回启用项,用于新核销申请选择收款方式。",
Tags: []string{"员工代收款"},
Input: new(dto.EmployeeCollectionPaymentMethodListRequest),
Output: new(dto.EmployeeCollectionPaymentMethodListResponse),
Auth: true,
})
Register(group, doc, paymentMethodPath, "POST", "", wrap(handler.CreatePaymentMethod), RouteSpec{
Summary: "创建线下收款方式",
Description: "仅超级管理员。稳定编码在未删除记录中唯一。",
Tags: []string{"员工代收款"},
Input: new(dto.CreateEmployeeCollectionPaymentMethodRequest),
Output: new(dto.EmployeeCollectionPaymentMethodResponse),
Auth: true,
})
Register(group, doc, paymentMethodPath, "PUT", "/:id", wrap(handler.UpdatePaymentMethod), RouteSpec{
Summary: "更新线下收款方式",
Description: "仅超级管理员。可修改名称、排序、启停与备注;已被核销申请引用时不允许修改稳定编码。",
Tags: []string{"员工代收款"},
Input: new(dto.IDReq),
Body: new(dto.UpdateEmployeeCollectionPaymentMethodRequest),
Output: new(dto.EmployeeCollectionPaymentMethodResponse),
Auth: true,
})
Register(group, doc, paymentMethodPath, "DELETE", "/:id", wrap(handler.DeletePaymentMethod), RouteSpec{
Summary: "删除线下收款方式",
Description: "仅超级管理员。已被核销申请引用的字典项不可物理删除,只能停用。",
Tags: []string{"员工代收款"},
Input: new(dto.IDReq),
Output: nil,
Auth: true,
})
}
// registerEmployeeCollectionBillRoutes 注册员工代收款账单查询、统计与关闭路由。
// 账单可见性由应用层强制:欠款人仅见本人账单,超级管理员见全部。
func registerEmployeeCollectionBillRoutes(router fiber.Router, handler *admin.EmployeeCollectionHandler, doc *openapi.Generator, basePath string) {
group := router.Group("/employee-collection-bills")
billPath := basePath + "/employee-collection-bills"
adminOnly := requireEmployeeCollectionConfigAccess
Register(group, doc, billPath, "GET", "", handler.ListBills, RouteSpec{
Summary: "查询员工代收款账单",
Description: "欠款人仅返回本人欠款账单,超级管理员返回全部;支持来源、状态、时间、欠款人、客户筛选与分页。",
Tags: []string{"员工代收款"},
Input: new(dto.EmployeeCollectionBillListRequest),
Output: new(dto.EmployeeCollectionBillListResponse),
Auth: true,
})
// 统计必须先于 /:id 注册,保证路径按字面量优先匹配。
Register(group, doc, billPath, "GET", "/statistics", handler.StatisticsBills, RouteSpec{
Summary: "查询员工代收款账单统计",
Description: "与账单列表使用相同筛选条件与可见性范围,返回应收、已核销、未核销金额合计与待处理账单数;不接受分页参数。",
Tags: []string{"员工代收款"},
Input: new(dto.EmployeeCollectionBillStatisticsRequest),
Output: new(dto.EmployeeCollectionBillStatisticsResponse),
Auth: true,
})
Register(group, doc, billPath, "GET", "/:id", handler.GetBill, RouteSpec{
Summary: "查询员工代收款账单详情",
Description: "返回账单、来源退款冲销、分摊、核销申请与企业微信审批历史;附件只返回对象键引用。无权限与不存在返回同一错误。",
Tags: []string{"员工代收款"},
Input: new(dto.IDReq),
Output: new(dto.EmployeeCollectionBillDetailResponse),
Auth: true,
})
Register(group, doc, billPath, "POST", "/:id/close", adminOnly(handler.CloseBill), RouteSpec{
Summary: "关闭员工代收款账单",
Description: "仅超级管理员。仅允许关闭待核销或部分核销且不存在审批中分摊的账单;关闭只作废未核销余额并保留已核销金额。",
Tags: []string{"员工代收款"},
Input: new(dto.IDReq),
Body: new(dto.CloseEmployeeCollectionBillRequest),
Output: new(dto.EmployeeCollectionBillResponse),
Auth: true,
})
}
// registerEmployeeCollectionApplicationRoutes 注册核销申请的创建、重提与受控查询路由。
// 可见性与代办权限由应用层强制:非超级管理员只能为本人账单操作,超级管理员代办必须填写原因。
func registerEmployeeCollectionApplicationRoutes(router fiber.Router, handler *admin.EmployeeCollectionHandler, doc *openapi.Generator, basePath string) {
group := router.Group("/employee-collection-applications")
applicationPath := basePath + "/employee-collection-applications"
Register(group, doc, applicationPath, "POST", "", handler.CreateApplication, RouteSpec{
Summary: "创建核销申请",
Description: "员工为本人可见账单创建;超级管理员可为账单欠款人代办且必须填写 acting_reason。服务端按账单可核销余额与付款金额校验分摊任一失败不保存申请与预占。",
Tags: []string{"员工代收款"},
Input: new(dto.SubmitEmployeeCollectionApplicationRequest),
Output: new(dto.EmployeeCollectionApplicationSubmitResponse),
Auth: true,
})
Register(group, doc, applicationPath, "GET", "", handler.ListApplications, RouteSpec{
Summary: "查询核销申请",
Description: "非超级管理员仅返回本人申请,超级管理员返回全部;支持状态、收款方式、申请人与创建时间筛选和分页。",
Tags: []string{"员工代收款"},
Input: new(dto.EmployeeCollectionApplicationListRequest),
Output: new(dto.EmployeeCollectionApplicationListResponse),
Auth: true,
})
Register(group, doc, applicationPath, "GET", "/:id", handler.GetApplication, RouteSpec{
Summary: "查询核销申请详情",
Description: "返回申请事实、账单分摊与全部审批尝试历史;附件只返回对象键引用。无权限与不存在返回同一错误。",
Tags: []string{"员工代收款"},
Input: new(dto.IDReq),
Output: new(dto.EmployeeCollectionApplicationDetailResponse),
Auth: true,
})
Register(group, doc, applicationPath, "PUT", "/:id", handler.ResubmitApplication, RouteSpec{
Summary: "修改并重提核销申请",
Description: "仅申请人或被代办的超级管理员,且仅已驳回申请可修改;重提新增一条审批尝试记录与新的企业微信审批实例,历史材料不被覆盖。",
Tags: []string{"员工代收款"},
Input: new(dto.IDReq),
Body: new(dto.SubmitEmployeeCollectionApplicationRequest),
Output: new(dto.EmployeeCollectionApplicationSubmitResponse),
Auth: true,
})
}