Files
junhong_cmp_fiber/internal/model/dto/phone_asset_association_dto.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

156 lines
12 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 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:"解除原因1500 字符)"`
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:"解除原因1500 字符)"`
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:"任务级解绑原因1500 字符),写入每次解除的失效原因"`
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:"逐项结果,顺序与请求去重后的资产集合一致"`
}