feat(收口): 补齐 8 月迭代缺口并同步 Spec 与证据链
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled

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

View File

@@ -158,31 +158,50 @@ func (PollingManualTriggerLog) TableName() string {
// PollingPriorityItem 是「某卡某轮询任务类型被加急」的持久化事实。
//
// 活动项粒度为 (card_id, task_type)由部分唯一索引保证至多一条Status 取
// pending-待执行 / processing-执行中 时为活动项,取 completed-已完成 / failed-失败出队 时为终态,
// pending-待执行 / processing-执行中 时为活动项,取
// completed-已完成 / failed-失败出队 / closed-人工关闭 / expired-有效期到期 时为终态,
// 终态行不占用唯一键。TriggerType 是首次触发场景TriggerTypes 是去重后的全部触发场景集合;
// ClaimedAt 是认领租约基准AttemptCount 只在真正发起执行后累加Result 与 FailureReason
// 只承载可安全展示的结果与原因ShopIDSnapshot 是消费时点解析的卡所属店铺快照(平台卡为 NULL
// 读侧数据范围按它下推,卡改归属不追溯已入队的加急事实。
//
// 资产身份AssetType/AssetID与设备号、代理归属同样在入队时冻结卡绑定有效设备时资产为
// 该设备独立卡为卡自身AgentShopIDSnapshot 是卡所属店铺的直接上级代理店铺(一级代理与平台卡为空)。
// AttemptLimit 取代码常量既有行随数据库默认值获得上限。StartedAt/FinishedAt 只在真正发起执行
// 后写入NextRunAt 是下一次计划执行时间(未排期为 NULL读侧 MUST NOT 据此判定已过期),
// DequeuedAt 在任一终态写入PriorityEffectiveFrom 是有效期起算时间(新增行取入队时间)。
// IntegrationLogID 只保存集成交互日志标识,不复制凭证或响应原文。
// 本模型不声明任何关联标签与数据库外键,关联一律只存 ID 并由应用层显式查询。
type PollingPriorityItem struct {
gorm.Model
CardID uint `gorm:"column:card_id;type:bigint;not null" json:"card_id"`
TaskType string `gorm:"column:task_type;type:varchar(50);not null" json:"task_type"`
Status string `gorm:"column:status;type:varchar(16);not null;default:'pending'" json:"status"`
TriggerType string `gorm:"column:trigger_type;type:varchar(30);not null" json:"trigger_type"`
TriggerTypes string `gorm:"column:trigger_types;type:varchar(255);not null;default:''" json:"trigger_types"`
TriggerCount int `gorm:"column:trigger_count;type:int;not null;default:1" json:"trigger_count"`
LastTriggeredAt time.Time `gorm:"column:last_triggered_at;type:timestamptz;not null;default:now()" json:"last_triggered_at"`
SourceOrderID *uint `gorm:"column:source_order_id;type:bigint" json:"source_order_id,omitempty"`
SourcePackageUsageID *uint `gorm:"column:source_package_usage_id;type:bigint" json:"source_package_usage_id,omitempty"`
AttemptCount int `gorm:"column:attempt_count;type:int;not null;default:0" json:"attempt_count"`
ClaimedAt *time.Time `gorm:"column:claimed_at;type:timestamptz" json:"claimed_at,omitempty"`
ManualReason string `gorm:"column:manual_reason;type:varchar(500);not null;default:''" json:"manual_reason"`
ManualOperatorID uint `gorm:"column:manual_operator_id;type:bigint;not null;default:0" json:"manual_operator_id"`
ManualOperatorName string `gorm:"column:manual_operator_name;type:varchar(100);not null;default:''" json:"manual_operator_name"`
ShopIDSnapshot *uint `gorm:"column:shop_id_snapshot;type:bigint" json:"shop_id_snapshot,omitempty"`
Result string `gorm:"column:result;type:varchar(16);not null;default:''" json:"result"`
FailureReason string `gorm:"column:failure_reason;type:varchar(500);not null;default:''" json:"failure_reason"`
CardID uint `gorm:"column:card_id;type:bigint;not null" json:"card_id"`
TaskType string `gorm:"column:task_type;type:varchar(50);not null" json:"task_type"`
Status string `gorm:"column:status;type:varchar(16);not null;default:'pending'" json:"status"`
TriggerType string `gorm:"column:trigger_type;type:varchar(30);not null" json:"trigger_type"`
TriggerTypes string `gorm:"column:trigger_types;type:varchar(255);not null;default:''" json:"trigger_types"`
TriggerCount int `gorm:"column:trigger_count;type:int;not null;default:1" json:"trigger_count"`
LastTriggeredAt time.Time `gorm:"column:last_triggered_at;type:timestamptz;not null;default:now()" json:"last_triggered_at"`
SourceOrderID *uint `gorm:"column:source_order_id;type:bigint" json:"source_order_id,omitempty"`
SourcePackageUsageID *uint `gorm:"column:source_package_usage_id;type:bigint" json:"source_package_usage_id,omitempty"`
AttemptCount int `gorm:"column:attempt_count;type:int;not null;default:0" json:"attempt_count"`
AttemptLimit int `gorm:"column:attempt_limit;type:int;not null;default:3" json:"attempt_limit"`
ClaimedAt *time.Time `gorm:"column:claimed_at;type:timestamptz" json:"claimed_at,omitempty"`
StartedAt *time.Time `gorm:"column:started_at;type:timestamptz" json:"started_at,omitempty"`
FinishedAt *time.Time `gorm:"column:finished_at;type:timestamptz" json:"finished_at,omitempty"`
NextRunAt *time.Time `gorm:"column:next_run_at;type:timestamptz" json:"next_run_at,omitempty"`
DequeuedAt *time.Time `gorm:"column:dequeued_at;type:timestamptz" json:"dequeued_at,omitempty"`
IntegrationLogID string `gorm:"column:integration_log_id;type:varchar(64);not null;default:''" json:"integration_log_id"`
PriorityEffectiveFrom *time.Time `gorm:"column:priority_effective_from;type:timestamptz" json:"priority_effective_from,omitempty"`
ManualReason string `gorm:"column:manual_reason;type:varchar(500);not null;default:''" json:"manual_reason"`
ManualOperatorID uint `gorm:"column:manual_operator_id;type:bigint;not null;default:0" json:"manual_operator_id"`
ManualOperatorName string `gorm:"column:manual_operator_name;type:varchar(100);not null;default:''" json:"manual_operator_name"`
ShopIDSnapshot *uint `gorm:"column:shop_id_snapshot;type:bigint" json:"shop_id_snapshot,omitempty"`
AgentShopIDSnapshot *uint `gorm:"column:agent_shop_id_snapshot;type:bigint" json:"agent_shop_id_snapshot,omitempty"`
AssetType string `gorm:"column:asset_type;type:varchar(20);not null;default:''" json:"asset_type"`
AssetID *uint `gorm:"column:asset_id;type:bigint" json:"asset_id,omitempty"`
DeviceNoSnapshot string `gorm:"column:device_no_snapshot;type:varchar(100);not null;default:''" json:"device_no_snapshot"`
Result string `gorm:"column:result;type:varchar(16);not null;default:''" json:"result"`
FailureReason string `gorm:"column:failure_reason;type:varchar(500);not null;default:''" json:"failure_reason"`
}
// TableName 指定表名