Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
- 新增六对成对迁移 000232–000237:H5 弹窗类型、退款结算标识与申请人备注、优先轮询事实字段与两个新终态、通道阈值命中留痕、手机号最近解绑人、提现资格校验留痕 - 退款:原因必填与申请人备注、来源支付与渠道流水冻结、线下处理流水号补录审计、按订单查询可选退款方式、企微审批材料补齐且新增字段缺失映射即明确失败 - 优先轮询:人工关闭、有效期到期独立周期任务、失败与过期人工重触发、事实字段与异常重试查询、资产解析端点只读投影 - 通道阈值:命中事实同事务留痕与命中记录查询;员工账单:列表筛选与详情投影;商户池:列表投影与统计周期语义;H5:弹窗类型与类别排序 - 手机号:有效关联数量与最近解绑人、短信验证码失败次数限制;导出:佣金明细十五列与报表序号列 - 时间筛选:三处新增筛选纳入统一严格解析契约,员工账单产生时间参数改名 - 同步 12 份主 Spec 需求、两端点与异步任务证据链,门禁 context-health 与 OpenSpec 校验通过
156 lines
12 KiB
Go
156 lines
12 KiB
Go
package dto
|
||
|
||
import "time"
|
||
|
||
// ListPhoneAssetAssociationRequest 后台查询手机号—资产关联列表请求。
|
||
// 仅超级管理员与平台用户可调用,范围外资产不进入结果集,越权与不存在不形成可枚举差异。
|
||
type ListPhoneAssetAssociationRequest struct {
|
||
Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码,默认 1"`
|
||
PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量,默认 20,最大 100"`
|
||
AssetIdentifier string `json:"asset_identifier" query:"asset_identifier" validate:"omitempty,max=100" maxLength:"100" description:"资产标识(ICCID、虚拟号、IMEI、SN 或接入号,精确匹配)"`
|
||
Phone string `json:"phone" query:"phone" validate:"omitempty,max=20" maxLength:"20" description:"手机号(完整值精确匹配)"`
|
||
Status *int `json:"status" query:"status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"关联状态 (0:已失效, 1:有效)"`
|
||
CreatedAtStart *time.Time `json:"created_at_start" query:"created_at_start" description:"关联创建时间起(含)"`
|
||
CreatedAtEnd *time.Time `json:"created_at_end" query:"created_at_end" description:"关联创建时间止(含)"`
|
||
}
|
||
|
||
// PhoneAssetAssociationResponse 手机号—资产关联列表项。
|
||
// 手机号为读取范围内的完整值(读侧不脱敏);审计与日志仍只写脱敏值。
|
||
type PhoneAssetAssociationResponse struct {
|
||
ID uint `json:"id" description:"关联关系ID"`
|
||
Phone string `json:"phone" description:"关联手机号(完整值)"`
|
||
AssetType string `json:"asset_type" description:"资产类型 (iot_card:物联网卡, device:设备)"`
|
||
AssetID uint `json:"asset_id" description:"资产ID"`
|
||
AssetIdentifier string `json:"asset_identifier" description:"资产当前标识(卡为 ICCID,设备为虚拟号)"`
|
||
Status int `json:"status" description:"关联状态 (0:已失效, 1:有效)"`
|
||
StatusName string `json:"status_name" description:"关联状态中文名称"`
|
||
Source string `json:"source" description:"建立来源,固定为 h5_sms_verification"`
|
||
EstablishedAt string `json:"established_at" description:"建立时间(短信验证通过时间)"`
|
||
ValidAssociationCount int64 `json:"valid_association_count" description:"该手机号当前有效关联数量(只统计有效关系,卡与设备各计一项,与「最多关联十项」上限判定同一计数口径)"`
|
||
InvalidatedAt string `json:"invalidated_at" description:"失效时间;有效关系为空"`
|
||
InvalidationMethod string `json:"invalidation_method" description:"失效方式 (backend_single:后台单项, backend_batch:后台批量, csv_import:CSV导入);有效关系为空"`
|
||
InvalidationMethodName string `json:"invalidation_method_name" description:"失效方式中文名称;有效关系为空"`
|
||
InvalidationReason string `json:"invalidation_reason" description:"失效原因;有效关系为空"`
|
||
InvalidatorID uint `json:"invalidator_id" description:"最近解绑人账号ID(后台账号标识);有效关系为空,值为 0"`
|
||
InvalidatorName string `json:"invalidator_name" description:"最近解绑人后台账号名称快照;有效关系为空。不以创建人或最后更新人填充"`
|
||
}
|
||
|
||
// PhoneAssetAssociationPageResult 手机号—资产关联列表分页响应。
|
||
type PhoneAssetAssociationPageResult struct {
|
||
Items []*PhoneAssetAssociationResponse `json:"items" description:"关联列表"`
|
||
Total int64 `json:"total" description:"总记录数"`
|
||
Page int `json:"page" description:"当前页码"`
|
||
Size int `json:"size" description:"每页数量"`
|
||
}
|
||
|
||
// UnbindPhoneAssetAssociationRequest 单项解除手机号—资产关联请求。
|
||
// 路径主键即指定一条关系;解除必须二次确认并填写原因,缺一即拒绝。
|
||
type UnbindPhoneAssetAssociationRequest struct {
|
||
ID uint `json:"-" path:"id" description:"关联关系ID" required:"true" minimum:"1"`
|
||
Reason string `json:"reason" validate:"required,min=1,max=500" required:"true" minLength:"1" maxLength:"500" description:"解除原因(1~500 字符)"`
|
||
Confirmed bool `json:"confirmed" validate:"required,eq=true" required:"true" description:"二次确认,必须为 true"`
|
||
}
|
||
|
||
// UnbindPhoneAssetAssociationResponse 单项解除结果。
|
||
type UnbindPhoneAssetAssociationResponse struct {
|
||
ID uint `json:"id" description:"关联关系ID"`
|
||
AssetType string `json:"asset_type" description:"资产类型 (iot_card:物联网卡, device:设备)"`
|
||
AssetID uint `json:"asset_id" description:"资产ID"`
|
||
UnboundCount int `json:"unbound_count" description:"本次解除的有效关系数,成功时为 1"`
|
||
InvalidatedAt string `json:"invalidated_at" description:"失效时间"`
|
||
}
|
||
|
||
// BatchUnbindAssetItem 批量解除中的单项资产。
|
||
type BatchUnbindAssetItem struct {
|
||
AssetType string `json:"asset_type" validate:"required,oneof=iot_card device" required:"true" description:"资产类型 (iot_card:物联网卡, device:设备)"`
|
||
AssetID uint `json:"asset_id" validate:"required,min=1" required:"true" minimum:"1" description:"资产ID"`
|
||
}
|
||
|
||
// BatchUnbindPhoneAssetAssociationRequest 按资产批量解除手机号关联请求。
|
||
// 每项资产解除其全部当前有效关系,逐资产独立执行,部分成功不回滚成功项。
|
||
type BatchUnbindPhoneAssetAssociationRequest struct {
|
||
Assets []BatchUnbindAssetItem `json:"assets" validate:"required,min=1,max=200,dive" required:"true" description:"待解除的资产集合,按 (资产类型, 资产ID) 去重后执行"`
|
||
Reason string `json:"reason" validate:"required,min=1,max=500" required:"true" minLength:"1" maxLength:"500" description:"解除原因(1~500 字符)"`
|
||
Confirmed bool `json:"confirmed" validate:"required,eq=true" required:"true" description:"二次确认,必须为 true"`
|
||
}
|
||
|
||
// BatchUnbindAssetResult 批量解除的逐项结果。
|
||
type BatchUnbindAssetResult struct {
|
||
AssetType string `json:"asset_type" description:"资产类型 (iot_card:物联网卡, device:设备)"`
|
||
AssetID uint `json:"asset_id" description:"资产ID"`
|
||
Success bool `json:"success" description:"该项是否解除成功"`
|
||
UnboundCount int `json:"unbound_count" description:"该项解除的有效关系数"`
|
||
Reason string `json:"reason,omitempty" description:"该项失败原因,成功时为空"`
|
||
}
|
||
|
||
// CreatePhoneAssetUnbindImportRequest 创建手机号—资产关联 CSV 解绑导入任务请求。
|
||
type CreatePhoneAssetUnbindImportRequest struct {
|
||
FileKey string `json:"file_key" validate:"required,min=1,max=500" required:"true" minLength:"1" maxLength:"500" description:"CSV 对象存储 Key,必须以 phone-unbind-imports/ 开头且扩展名为 .csv(通过 POST /api/admin/storage/upload-url 获取)"`
|
||
Reason string `json:"reason" validate:"required,min=1,max=500" required:"true" minLength:"1" maxLength:"500" description:"任务级解绑原因(1~500 字符),写入每次解除的失效原因"`
|
||
Confirmed bool `json:"confirmed" validate:"required,eq=true" required:"true" description:"二次确认,必须为 true"`
|
||
}
|
||
|
||
// ListPhoneAssetUnbindImportRequest 查询解绑导入任务列表请求。
|
||
type ListPhoneAssetUnbindImportRequest struct {
|
||
Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码,默认 1"`
|
||
PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量,默认 20,最大 100"`
|
||
Status *int `json:"status" query:"status" validate:"omitempty,min=1,max=4" minimum:"1" maximum:"4" description:"任务状态 (1:待处理, 2:处理中, 3:已完成, 4:失败)"`
|
||
}
|
||
|
||
// GetPhoneAssetUnbindImportRequest 解绑导入任务详情路径参数。
|
||
type GetPhoneAssetUnbindImportRequest struct {
|
||
ID uint `path:"id" required:"true" description:"导入任务ID"`
|
||
}
|
||
|
||
// PhoneAssetUnbindImportTaskResponse 解绑导入任务响应。
|
||
type PhoneAssetUnbindImportTaskResponse struct {
|
||
ID uint `json:"id" description:"导入任务ID"`
|
||
TaskNo string `json:"task_no" description:"导入任务编号"`
|
||
FileName string `json:"file_name" description:"上传的源 CSV 文件名"`
|
||
UnbindReason string `json:"unbind_reason" description:"任务级解绑原因"`
|
||
Status int `json:"status" description:"任务状态 (1:待处理, 2:处理中, 3:已完成, 4:失败)"`
|
||
StatusName string `json:"status_name" description:"任务状态中文名称"`
|
||
TotalCount int `json:"total_count" description:"数据行总数;任务级失败时为 0"`
|
||
SuccessCount int `json:"success_count" description:"成功行数"`
|
||
FailCount int `json:"fail_count" description:"失败行数"`
|
||
ErrorMessage string `json:"error_message" description:"任务级失败原因;与行级失败原因分开记录"`
|
||
CreatorName string `json:"creator_name" description:"任务创建人名称快照"`
|
||
CreatedAt string `json:"created_at" description:"创建时间"`
|
||
StartedAt string `json:"started_at" description:"开始处理时间"`
|
||
CompletedAt string `json:"completed_at" description:"完成时间"`
|
||
}
|
||
|
||
// PhoneAssetUnbindImportTaskPageResult 解绑导入任务分页响应。
|
||
type PhoneAssetUnbindImportTaskPageResult struct {
|
||
Items []*PhoneAssetUnbindImportTaskResponse `json:"items" description:"导入任务列表"`
|
||
Total int64 `json:"total" description:"总记录数"`
|
||
Page int `json:"page" description:"当前页码"`
|
||
Size int `json:"size" description:"每页数量"`
|
||
}
|
||
|
||
// PhoneAssetUnbindImportItemResponse 解绑导入逐行结果。
|
||
// AssociatedPhones 是解绑当时的完整手机号快照:关系已失效,只有快照能事后展示被解绑的手机号。
|
||
type PhoneAssetUnbindImportItemResponse struct {
|
||
Line int `json:"line" description:"行号,自数据首行起计(表头不计入)"`
|
||
AssetType string `json:"asset_type" description:"资产类型 (iot_card:物联网卡, device:设备);未定位到资产时为空"`
|
||
AssetIdentifier string `json:"asset_identifier" description:"导入文件中的资产标识原文"`
|
||
AssetID uint `json:"asset_id" description:"资产ID;未定位到资产时为 0"`
|
||
UnboundCount int `json:"unbound_count" description:"该行解除的有效关系数"`
|
||
AssociatedPhones []string `json:"associated_phones" description:"解绑当时的完整关联手机号快照;失败行为空数组"`
|
||
Status int `json:"status" description:"行状态 (3:成功, 4:失败)"`
|
||
StatusName string `json:"status_name" description:"行状态中文名称"`
|
||
Reason string `json:"reason" description:"失败原因;成功行为空"`
|
||
}
|
||
|
||
// PhoneAssetUnbindImportTaskDetailResponse 解绑导入任务详情响应。
|
||
type PhoneAssetUnbindImportTaskDetailResponse struct {
|
||
PhoneAssetUnbindImportTaskResponse
|
||
Items []PhoneAssetUnbindImportItemResponse `json:"items" description:"逐行结果明细;任务级失败时为空数组"`
|
||
}
|
||
|
||
type BatchUnbindPhoneAssetAssociationResponse struct {
|
||
SuccessCount int `json:"success_count" description:"解除成功的资产项数"`
|
||
FailCount int `json:"fail_count" description:"解除失败的资产项数"`
|
||
Items []BatchUnbindAssetResult `json:"items" description:"逐项结果,顺序与请求去重后的资产集合一致"`
|
||
}
|