Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
- 新增六对成对迁移 000232–000237:H5 弹窗类型、退款结算标识与申请人备注、优先轮询事实字段与两个新终态、通道阈值命中留痕、手机号最近解绑人、提现资格校验留痕 - 退款:原因必填与申请人备注、来源支付与渠道流水冻结、线下处理流水号补录审计、按订单查询可选退款方式、企微审批材料补齐且新增字段缺失映射即明确失败 - 优先轮询:人工关闭、有效期到期独立周期任务、失败与过期人工重触发、事实字段与异常重试查询、资产解析端点只读投影 - 通道阈值:命中事实同事务留痕与命中记录查询;员工账单:列表筛选与详情投影;商户池:列表投影与统计周期语义;H5:弹窗类型与类别排序 - 手机号:有效关联数量与最近解绑人、短信验证码失败次数限制;导出:佣金明细十五列与报表序号列 - 时间筛选:三处新增筛选纳入统一严格解析契约,员工账单产生时间参数改名 - 同步 12 份主 Spec 需求、两端点与异步任务证据链,门禁 context-health 与 OpenSpec 校验通过
108 lines
6.4 KiB
Go
108 lines
6.4 KiB
Go
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"
|
||
)
|
||
|
||
// phoneAssetUnbindImportDoc 说明手机号资产解绑 CSV 的模板要求。
|
||
// 模板由前端提供,后端只描述固定列序、取值与编码要求,不提供模板下载端点与模板资源。
|
||
const phoneAssetUnbindImportDoc = `仅超级管理员和平台账号可操作,代理与企业账号返回 403。
|
||
|
||
### 完整导入流程
|
||
|
||
1. **获取上传 URL**:调用 ` + "`POST /api/admin/storage/upload-url`" + `,purpose 传 ` + "`phone_unbind_import`" + `
|
||
2. **上传 CSV**:使用返回的预签名 URL 上传文件到对象存储
|
||
3. **调用本接口**:使用返回的 ` + "`file_key`" + ` 创建导入任务(必须以 ` + "`phone-unbind-imports/`" + ` 开头且扩展名为 ` + "`.csv`" + `)
|
||
|
||
### 模板列序(首行表头必须完全一致)
|
||
|
||
` + "`资产标识`" + `、` + "`备注`" + `
|
||
|
||
- 资产标识:以 ICCID、虚拟号、IMEI、SN 或接入号唯一定位资产;不存在或已删除时该行失败
|
||
- 备注:可选,填写时写入该行审计
|
||
|
||
### 编码要求
|
||
|
||
文件编码为 UTF-8,可带 BOM;非 UTF-8 时按 GBK 尝试解码,仍失败时按任务级失败并给出明确原因。
|
||
|
||
### 执行语义
|
||
|
||
- 逐行独立事务:成功行提交,失败行保留原状,不设行数硬上限
|
||
- 每行解除该资产全部当前有效关联,解绑原因取任务级必填字段
|
||
- 行号自数据首行起计(表头不计入);任务级失败不产生行明细
|
||
- 逐行结果保存解绑当时的完整手机号快照,供任务详情与结果展示`
|
||
|
||
// registerPhoneAssetAssociationRoutes 注册手机号—资产关联查看与解除路由。
|
||
// 沿用超管/平台路由组级 gate 先例:代理、企业与个人客户账号一律 403。
|
||
func registerPhoneAssetAssociationRoutes(router fiber.Router, handler *admin.PhoneAssetAssociationHandler, doc *openapi.Generator, basePath string) {
|
||
group := router.Group("/phone-asset-associations", func(c *fiber.Ctx) error {
|
||
userType := middleware.GetUserTypeFromContext(c.UserContext())
|
||
if userType != constants.UserTypeSuperAdmin && userType != constants.UserTypePlatform {
|
||
return errors.New(errors.CodeForbidden, constants.PlatformManagementForbiddenMessage)
|
||
}
|
||
return c.Next()
|
||
})
|
||
groupPath := basePath + "/phone-asset-associations"
|
||
|
||
Register(group, doc, groupPath, "GET", "", handler.List, RouteSpec{
|
||
Summary: "查询手机号资产关联列表",
|
||
Description: constants.PhoneAssetAssociationAccessDescription + "按资产数据范围过滤后分页返回资产(类型/ID/标识)、完整手机号、建立时间、建立来源与状态;支持资产标识、手机号、关联状态与创建时间区间筛选。越权与不存在不形成可枚举差异。列表按当页涉及的手机号集合一次批量聚合返回该手机号当前有效关联数量(只统计有效关系、卡与设备各计一项,与「最多关联十项」上限判定同一口径);已失效关系随既有失效方式与原因一并返回最近解绑人的账号名称快照、账号标识与解绑时间,关系仍有效时这三项为空,不以创建人或最后更新人填充。以上投影字段只读,不改变既有解绑、换绑与上限判定规则。",
|
||
Tags: []string{"手机号资产关联"},
|
||
Input: new(dto.ListPhoneAssetAssociationRequest),
|
||
Output: new(dto.PhoneAssetAssociationPageResult),
|
||
Auth: true,
|
||
})
|
||
|
||
Register(group, doc, groupPath, "POST", "/batch-unbind", handler.BatchUnbind, RouteSpec{
|
||
Summary: "按资产批量解除手机号关联",
|
||
Description: constants.PhoneAssetAssociationAccessDescription + "资产集合按 (资产类型, 资产ID) 去重后逐项独立执行:每项解除该资产全部当前有效关联,返回成功数、失败数与逐项结果,部分成功不回滚成功项。越权、资产不存在与已无有效关系返回同一失败文案。" + constants.PhoneAssetAssociationDeniedMessage + "。",
|
||
Tags: []string{"手机号资产关联"},
|
||
Input: new(dto.BatchUnbindPhoneAssetAssociationRequest),
|
||
Output: new(dto.BatchUnbindPhoneAssetAssociationResponse),
|
||
Auth: true,
|
||
})
|
||
|
||
Register(group, doc, groupPath, "POST", "/unbind-imports", handler.CreateImportTask, RouteSpec{
|
||
Summary: "创建手机号资产解绑导入任务",
|
||
Description: phoneAssetUnbindImportDoc,
|
||
Tags: []string{"手机号资产关联"},
|
||
Input: new(dto.CreatePhoneAssetUnbindImportRequest),
|
||
Output: new(dto.PhoneAssetUnbindImportTaskResponse),
|
||
Auth: true,
|
||
})
|
||
|
||
Register(group, doc, groupPath, "GET", "/unbind-imports", handler.ListImportTasks, RouteSpec{
|
||
Summary: "查询手机号资产解绑导入任务列表",
|
||
Description: constants.PhoneAssetAssociationAccessDescription,
|
||
Tags: []string{"手机号资产关联"},
|
||
Input: new(dto.ListPhoneAssetUnbindImportRequest),
|
||
Output: new(dto.PhoneAssetUnbindImportTaskPageResult),
|
||
Auth: true,
|
||
})
|
||
|
||
Register(group, doc, groupPath, "GET", "/unbind-imports/:id", handler.ImportTaskDetail, RouteSpec{
|
||
Summary: "查询手机号资产解绑导入任务详情",
|
||
Description: constants.PhoneAssetAssociationAccessDescription + "返回成功数、失败数、逐行失败原因与解绑当时的完整手机号快照,并单独返回任务级错误原因。",
|
||
Tags: []string{"手机号资产关联"},
|
||
Input: new(dto.GetPhoneAssetUnbindImportRequest),
|
||
Output: new(dto.PhoneAssetUnbindImportTaskDetailResponse),
|
||
Auth: true,
|
||
})
|
||
|
||
Register(group, doc, groupPath, "DELETE", "/:id", handler.Unbind, RouteSpec{
|
||
Summary: "解除单条手机号资产关联",
|
||
Description: constants.PhoneAssetAssociationAccessDescription + "路径主键即指定一条资产—手机号关系,必须指定;必须二次确认并填写原因(1~500 字符),缺一即拒绝且不解除任何关系。越权、资产不存在与已无有效关系返回同一失败文案。" + constants.PhoneAssetAssociationDeniedMessage + "。",
|
||
Tags: []string{"手机号资产关联"},
|
||
Input: new(dto.UnbindPhoneAssetAssociationRequest),
|
||
Output: new(dto.UnbindPhoneAssetAssociationResponse),
|
||
Auth: true,
|
||
})
|
||
}
|