Files
junhong_cmp_fiber/internal/routes/employee_collection.go
break 5ed6b39deb
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
feat(收口): 补齐 8 月迭代缺口并同步 Spec 与证据链
- 新增六对成对迁移 000232–000237:H5 弹窗类型、退款结算标识与申请人备注、优先轮询事实字段与两个新终态、通道阈值命中留痕、手机号最近解绑人、提现资格校验留痕
- 退款:原因必填与申请人备注、来源支付与渠道流水冻结、线下处理流水号补录审计、按订单查询可选退款方式、企微审批材料补齐且新增字段缺失映射即明确失败
- 优先轮询:人工关闭、有效期到期独立周期任务、失败与过期人工重触发、事实字段与异常重试查询、资产解析端点只读投影
- 通道阈值:命中事实同事务留痕与命中记录查询;员工账单:列表筛选与详情投影;商户池:列表投影与统计周期语义;H5:弹窗类型与类别排序
- 手机号:有效关联数量与最近解绑人、短信验证码失败次数限制;导出:佣金明细十五列与报表序号列
- 时间筛选:三处新增筛选纳入统一严格解析契约,员工账单产生时间参数改名
- 同步 12 份主 Spec 需求、两端点与异步任务证据链,门禁 context-health 与 OpenSpec 校验通过
2026-09-18 15:34:29 +08:00

159 lines
9.2 KiB
Go
Raw Permalink 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: "欠款人仅返回本人欠款账单,超级管理员返回全部;支持账单编号(即账单记录标识)、来源、状态、" +
"欠款人姓名或账号(子串模糊)、客户名称(子串模糊)、产生时间与核销通过时间筛选与分页。" +
"产生时间参数为 `start_time`/`end_time`,核销通过时间为 `decided_start_time`/`decided_end_time`" +
"两类均为带显式时区的 RFC3339 秒级闭区间(含两端);旧参数名 `created_from`/`created_to` 与旧日期格式一律以参数非法拒绝。" +
"核销通过时间取该账单已通过分摊关联的申请表审批终态时间。" +
"响应并列返回未核销金额(应收减已核销)与剩余可核销金额(应收减已核销减审批中预占),已关闭账单两者为零。",
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,
})
}