feat(手机号资产关联): AUG26-009 手机号—资产关联、十项上限与后台解绑
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m2s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m2s
- 新增成对迁移 000223(tb_phone_asset_association,含有效关系部分唯一索引与 down 守卫)与 000224(解绑导入任务表),不回填历史 - H5:need_bind_phone 三支判定(开关关闭完全短路);已有主号幂等建联;十项上限按手机号 advisory 串行化(含换绑到全新号的并发场景);换绑原子迁移与冲突整单回滚;不写遗留列 - 后台:关联列表、单项/批量解绑、CSV 导入解绑(B1–B16),超管/平台 gate + 资产数据范围复核,三态统一文案 - 读侧:卡/设备列表与详情按页一次 IN 聚合;两类导出补「关联手机号」列并保留历史表头反解兼容 - 脱敏:关联审计走独立动作/资源只写脱敏手机号;访问日志手机号类字段脱敏 - 同步主 Spec openspec/specs/phone-asset-association 并归档 AUG26-009,补齐 requirement-evidence 与入口矩阵,context-health 通过
This commit is contained in:
@@ -524,6 +524,18 @@ const (
|
||||
AuditActionExportTaskCreated = "export_task.create"
|
||||
// AuditActionExportTaskCancelled 表示取消业务导出任务或提交取消请求。
|
||||
AuditActionExportTaskCancelled = "export_task.cancel"
|
||||
// AuditActionPhoneAssetAssociationCreated 表示 H5 短信验证通过后建立手机号—资产关联。
|
||||
AuditActionPhoneAssetAssociationCreated = "phone_asset_association.create"
|
||||
// AuditActionPhoneAssetAssociationMigrated 表示换绑手机号时把旧号全部有效关联迁移到新号。
|
||||
AuditActionPhoneAssetAssociationMigrated = "phone_asset_association.migrate"
|
||||
// AuditActionPhoneAssetAssociationUnbound 表示后台单项或按资产批量解除手机号—资产关联。
|
||||
AuditActionPhoneAssetAssociationUnbound = "phone_asset_association.unbind"
|
||||
// AuditActionPhoneAssetAssociationImported 表示 CSV 导入单行解除手机号—资产关联。
|
||||
AuditActionPhoneAssetAssociationImported = "phone_asset_association.import_unbind"
|
||||
// AuditActionPhoneAssetUnbindImportTaskCreated 表示创建 CSV 解绑导入任务。
|
||||
AuditActionPhoneAssetUnbindImportTaskCreated = "phone_asset_unbind_import_task.create"
|
||||
// AuditActionPhoneAssetUnbindImportTaskCompleted 表示 CSV 解绑导入任务完成。
|
||||
AuditActionPhoneAssetUnbindImportTaskCompleted = "phone_asset_unbind_import_task.complete"
|
||||
// AuditActionNotificationDelivered 表示 Outbox 消费后实际生成站内通知。
|
||||
AuditActionNotificationDelivered = "notification.deliver"
|
||||
// AuditActionNotificationRead 表示单条通知首次标记已读。
|
||||
@@ -667,6 +679,10 @@ const (
|
||||
AuditResourceOrderPackageInvalidateTask = "order_package_invalidate_task"
|
||||
// AuditResourceExportTask 表示业务导出任务资源。
|
||||
AuditResourceExportTask = "export_task"
|
||||
// AuditResourcePhoneAssetAssociation 表示手机号—资产关联资源。
|
||||
AuditResourcePhoneAssetAssociation = "phone_asset_association"
|
||||
// AuditResourcePhoneAssetUnbindImportTask 表示手机号—资产 CSV 解绑导入任务资源。
|
||||
AuditResourcePhoneAssetUnbindImportTask = "phone_asset_unbind_import_task"
|
||||
// AuditResourceNotification 表示站内通知资源。
|
||||
AuditResourceNotification = "notification"
|
||||
// AuditResourceNotificationReadBatch 表示通知批量已读资源。
|
||||
@@ -863,6 +879,10 @@ const (
|
||||
AuditResourceRoleEnterpriseDeviceBinding = "enterprise_device_binding"
|
||||
// AuditResourceRoleEnterpriseDeviceAuthorization 表示企业设备授权记录。
|
||||
AuditResourceRoleEnterpriseDeviceAuthorization = "enterprise_device_authorization"
|
||||
// AuditResourceRolePhoneAssetAssociationTarget 表示手机号—资产关联的主要目标。
|
||||
AuditResourceRolePhoneAssetAssociationTarget = "phone_asset_association_target"
|
||||
// AuditResourceRolePhoneAssetAssociationAsset 表示关联指向的资产。
|
||||
AuditResourceRolePhoneAssetAssociationAsset = "phone_asset_association_asset"
|
||||
// AuditResourceRolePersonalCustomerTarget 表示个人客户操作的主体目标。
|
||||
AuditResourceRolePersonalCustomerTarget = "personal_customer_target"
|
||||
// AuditResourceRolePersonalCustomerPhone 表示个人客户手机号关系。
|
||||
|
||||
@@ -77,6 +77,7 @@ const (
|
||||
TaskTypeAssetPackageBatchOrder = "asset:package:batch_order" // 资产套餐批量订购
|
||||
// 店铺负责人 CSV 导入任务类型,独立成队列以隔离逐行执行的长时任务。
|
||||
TaskTypeShopBusinessOwnerImport = "shop_business_owner:import"
|
||||
TaskTypePhoneAssetUnbindImport = "phone_asset_unbind:import" // 手机号—资产关联 CSV 解绑导入
|
||||
|
||||
// 订单超时任务类型
|
||||
TaskTypeOrderExpire = "order:expire" // 订单超时自动取消
|
||||
@@ -232,6 +233,7 @@ const (
|
||||
QueueOrderPackageInvalidate = TaskTypeOrderPackageInvalidate // 批量失效订单套餐任务队列
|
||||
QueueAssetPackageBatchOrder = TaskTypeAssetPackageBatchOrder // 资产套餐批量订购任务队列
|
||||
QueueShopBusinessOwnerImport = TaskTypeShopBusinessOwnerImport // 店铺负责人 CSV 导入任务队列
|
||||
QueuePhoneAssetUnbindImport = TaskTypePhoneAssetUnbindImport // 手机号—资产关联 CSV 解绑导入任务队列
|
||||
QueueOrderExpire = TaskTypeOrderExpire // 订单超时取消任务队列
|
||||
QueueAutoPurchase = TaskTypeAutoPurchaseAfterRecharge // 充值后自动购包任务队列
|
||||
QueueAlertCheck = TaskTypeAlertCheck // 告警检查任务队列
|
||||
@@ -291,6 +293,8 @@ func QueueForTaskType(taskType string) string {
|
||||
return QueueAssetPackageBatchOrder
|
||||
case TaskTypeShopBusinessOwnerImport:
|
||||
return QueueShopBusinessOwnerImport
|
||||
case TaskTypePhoneAssetUnbindImport:
|
||||
return QueuePhoneAssetUnbindImport
|
||||
case TaskTypeOrderExpire:
|
||||
return QueueOrderExpire
|
||||
case TaskTypeAutoPurchaseAfterRecharge:
|
||||
@@ -332,6 +336,7 @@ func DefaultTaskQueueWeights() map[string]int {
|
||||
QueueOrderPackageInvalidate: 5,
|
||||
QueueAssetPackageBatchOrder: 5,
|
||||
QueueShopBusinessOwnerImport: 4,
|
||||
QueuePhoneAssetUnbindImport: 4,
|
||||
QueueOrderExpire: 4,
|
||||
QueueEmailSend: 4,
|
||||
QueueExportDispatch: 4,
|
||||
|
||||
142
pkg/constants/phone_asset_association.go
Normal file
142
pkg/constants/phone_asset_association.go
Normal file
@@ -0,0 +1,142 @@
|
||||
package constants
|
||||
|
||||
import "time"
|
||||
|
||||
// 手机号—资产关联的状态取值。
|
||||
const (
|
||||
// PhoneAssetAssociationStatusInvalid 表示关联已失效,不再占用十项额度。
|
||||
PhoneAssetAssociationStatusInvalid = 0
|
||||
// PhoneAssetAssociationStatusValid 表示关联当前有效。
|
||||
PhoneAssetAssociationStatusValid = 1
|
||||
)
|
||||
|
||||
// 手机号—资产关联的建立来源;关联只能由 H5 短信验证建立,后台无创建或补录入口。
|
||||
const (
|
||||
// PhoneAssetAssociationSourceH5SMSVerification 表示关联由 H5 短信验证码校验通过后建立。
|
||||
PhoneAssetAssociationSourceH5SMSVerification = "h5_sms_verification"
|
||||
)
|
||||
|
||||
// 手机号—资产关联的失效方式,用于审计与事后核对解除入口。
|
||||
const (
|
||||
// PhoneAssetAssociationInvalidateMethodBackendSingle 表示后台单项解除。
|
||||
PhoneAssetAssociationInvalidateMethodBackendSingle = "backend_single"
|
||||
// PhoneAssetAssociationInvalidateMethodBackendBatch 表示后台勾选批量解除。
|
||||
PhoneAssetAssociationInvalidateMethodBackendBatch = "backend_batch"
|
||||
// PhoneAssetAssociationInvalidateMethodCSVImport 表示 CSV 导入解除。
|
||||
PhoneAssetAssociationInvalidateMethodCSVImport = "csv_import"
|
||||
)
|
||||
|
||||
// 手机号—资产关联的业务口径常量。
|
||||
const (
|
||||
// PhoneAssetAssociationMaxValidPerPhone 表示单手机号可同时有效的关联资产项数上限。
|
||||
PhoneAssetAssociationMaxValidPerPhone = 10
|
||||
// PhoneAssetAssociationLimitMessage 表示超过十项上限时的统一失败文案。
|
||||
PhoneAssetAssociationLimitMessage = "该手机号最多关联10项有效资产"
|
||||
)
|
||||
|
||||
// 手机号—资产关联解绑入口的角色说明。
|
||||
const (
|
||||
// PhoneAssetAssociationAccessDescription 表示关联查看与解除入口的角色说明。
|
||||
PhoneAssetAssociationAccessDescription = "仅超级管理员和平台账号可访问,代理与企业账号返回 403。"
|
||||
)
|
||||
|
||||
// 手机号—资产关联解除的入参口径。
|
||||
const (
|
||||
// PhoneAssetAssociationUnbindReasonMaxLength 表示解除原因的最大长度。
|
||||
PhoneAssetAssociationUnbindReasonMaxLength = 500
|
||||
)
|
||||
|
||||
// 手机号—资产关联 CSV 解绑导入的场景常量。
|
||||
const (
|
||||
// StoragePurposePhoneAssetUnbindImport 表示手机号资产解绑 CSV 导入上传用途。
|
||||
StoragePurposePhoneAssetUnbindImport = "phone_unbind_import"
|
||||
// PhoneAssetUnbindImportStoragePrefix 表示解绑导入文件的对象存储目录。
|
||||
PhoneAssetUnbindImportStoragePrefix = "phone-unbind-imports"
|
||||
// PhoneAssetUnbindImportTaskTimeout 表示单个解绑导入任务的最长执行时间。
|
||||
PhoneAssetUnbindImportTaskTimeout = 2 * time.Hour
|
||||
// PhoneAssetUnbindImportProgressBatchSize 表示导入按批更新进度计数的批大小。
|
||||
PhoneAssetUnbindImportProgressBatchSize = 100
|
||||
// PhoneAssetUnbindImportItemStatusSuccess 表示导入单行已成功解除关联。
|
||||
PhoneAssetUnbindImportItemStatusSuccess = 3
|
||||
// PhoneAssetUnbindImportItemStatusFailed 表示导入单行校验或执行失败并保留原状。
|
||||
PhoneAssetUnbindImportItemStatusFailed = 4
|
||||
)
|
||||
|
||||
// PhoneAssetUnbindImportColumns 表示导入文件首行必须完全一致的固定列序;解绑原因由任务级必填字段提供。
|
||||
var PhoneAssetUnbindImportColumns = []string{"资产标识", "备注"}
|
||||
|
||||
// 手机号—资产关联解绑导入的任务级失败原因,与行级失败原因分开记录。
|
||||
const (
|
||||
// PhoneAssetUnbindImportErrorFileFormat 表示文件格式或表头与固定列序不符。
|
||||
PhoneAssetUnbindImportErrorFileFormat = "文件格式或表头与固定列序不符"
|
||||
// PhoneAssetUnbindImportErrorEncoding 表示文件既非合法 UTF-8 也无法按 GBK 解码。
|
||||
PhoneAssetUnbindImportErrorEncoding = "文件编码无法按 UTF-8 或 GBK 解码"
|
||||
// PhoneAssetUnbindImportErrorNoDataRow 表示文件没有数据行。
|
||||
PhoneAssetUnbindImportErrorNoDataRow = "文件没有数据行"
|
||||
)
|
||||
|
||||
// 手机号—资产关联解绑导入的行级失败原因,取值集合固定。
|
||||
const (
|
||||
// PhoneAssetUnbindImportRowErrorIdentifier 表示资产标识为空。
|
||||
PhoneAssetUnbindImportRowErrorIdentifier = "资产标识不能为空"
|
||||
// PhoneAssetUnbindImportRowErrorAssetMissing 表示资产标识无法定位到资产。
|
||||
PhoneAssetUnbindImportRowErrorAssetMissing = "资产标识不存在或已删除"
|
||||
// PhoneAssetUnbindImportRowErrorNoAssociation 表示该资产已无有效关联。
|
||||
PhoneAssetUnbindImportRowErrorNoAssociation = "该资产已无有效关联手机号"
|
||||
// PhoneAssetUnbindImportRowErrorFormat 表示该行列数与固定列序不一致。
|
||||
PhoneAssetUnbindImportRowErrorFormat = "行格式错误"
|
||||
// PhoneAssetUnbindImportRowErrorRemarkTooLong 表示备注超过长度上限。
|
||||
PhoneAssetUnbindImportRowErrorRemarkTooLong = "备注超过500字符"
|
||||
)
|
||||
|
||||
// 手机号—资产关联解绑导入的备注长度上限。
|
||||
const (
|
||||
// PhoneAssetUnbindImportRemarkMaxLength 表示行内备注的最大长度。
|
||||
PhoneAssetUnbindImportRemarkMaxLength = 500
|
||||
)
|
||||
|
||||
// 手机号—资产关联的三态统一失败文案。
|
||||
// 越权、资产不存在与已无有效关系三种情况必须返回同一文案,避免形成可枚举差异(ENG-AUTHZ-001)。
|
||||
// 本常量只供新增用例使用;既有内联字面量按 As-Is 保留,不在本 Change 统一。
|
||||
const (
|
||||
// PhoneAssetAssociationDeniedMessage 表示越权、资产不存在或已无有效关系时的统一失败文案。
|
||||
PhoneAssetAssociationDeniedMessage = "无权限操作该资源或资源不存在"
|
||||
)
|
||||
|
||||
// GetPhoneAssetAssociationImportItemStatusName 返回解绑导入行状态中文名称。
|
||||
func GetPhoneAssetAssociationImportItemStatusName(status int) string {
|
||||
switch status {
|
||||
case PhoneAssetUnbindImportItemStatusSuccess:
|
||||
return "成功"
|
||||
case PhoneAssetUnbindImportItemStatusFailed:
|
||||
return "失败"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// GetPhoneAssetAssociationStatusName 返回关联状态中文名称。
|
||||
func GetPhoneAssetAssociationStatusName(status int) string {
|
||||
switch status {
|
||||
case PhoneAssetAssociationStatusValid:
|
||||
return "有效"
|
||||
case PhoneAssetAssociationStatusInvalid:
|
||||
return "已失效"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// PhoneAssetAssociationInvalidateMethodName 返回失效方式中文名称。
|
||||
func PhoneAssetAssociationInvalidateMethodName(method string) string {
|
||||
switch method {
|
||||
case PhoneAssetAssociationInvalidateMethodBackendSingle:
|
||||
return "后台单项解除"
|
||||
case PhoneAssetAssociationInvalidateMethodBackendBatch:
|
||||
return "后台批量解除"
|
||||
case PhoneAssetAssociationInvalidateMethodCSVImport:
|
||||
return "CSV导入解除"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user