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

@@ -30,6 +30,23 @@ type CarrierTrafficThresholdLock struct {
// AnomalyFlag 为 1 表示查询窗口超期或失败无法自动确认,必须退出自动扫描转人工核对。
AnomalyFlag int `gorm:"column:anomaly_flag;type:smallint;not null;default:0" json:"anomaly_flag"`
FailureReason string `gorm:"column:failure_reason;type:varchar(500);not null;default:''" json:"failure_reason"`
// HitTrafficMB 是命中时该卡当前计费周期的累计流量读数MB
// 取与停机判定同一来源的运营商网关累计读数换算值,不使用本地用量统计或套餐真流量;
// 本次上线前的历史行为空,表示读数不可重建,读侧按「无」展示。
HitTrafficMB *float64 `gorm:"column:hit_traffic_mb;type:numeric(18,2)" json:"hit_traffic_mb,omitempty"`
// HitThresholdValue 是本次判定实际生效的通道阈值数值,冻结命中时值:
// 之后修改通道阈值不会改写历史命中;历史行为空。
HitThresholdValue *float64 `gorm:"column:hit_threshold_value;type:numeric(18,2)" json:"hit_threshold_value,omitempty"`
// HitThresholdUnit 是本次判定阈值的单位MB/GB空串表示历史行未记录。
HitThresholdUnit string `gorm:"column:hit_threshold_unit;type:varchar(8);not null;default:''" json:"hit_threshold_unit"`
// JudgedAt 是本次达量判定的时刻,既有行以创建时间回填,是命中记录查询与排序的业务时间。
JudgedAt time.Time `gorm:"column:judged_at;type:timestamptz;not null" json:"judged_at"`
// TriggerSource 是触发本次判定的流量观测来源constants.CardObservationSource*);空串表示未记录。
TriggerSource string `gorm:"column:trigger_source;type:varchar(20);not null;default:''" json:"trigger_source"`
// UnlockedAt 是周期恢复时的解锁时间,只在跨期解锁成功时写入;绝不覆盖上面的命中事实。
UnlockedAt *time.Time `gorm:"column:unlocked_at;type:timestamptz" json:"unlocked_at,omitempty"`
// ResumeResult 是周期恢复的复机结果resumed/skipped/manual跳过原因沿用 FailureReason。
ResumeResult string `gorm:"column:resume_result;type:varchar(30);not null;default:''" json:"resume_result"`
}
// TableName 指定运营商通道流量阈值周期锁表名。

View File

@@ -132,8 +132,14 @@ type WithdrawalRequestAttemptItem struct {
ApprovalInstanceID uint `json:"approval_instance_id" description:"本次尝试关联的通用审批实例ID0 表示尚未关联"`
ApprovalStatus int `json:"approval_status" description:"通用审批实例状态 (0:提交中, 1:审批中, 2:已通过, 3:已拒绝, 4:已撤销, 5:通过后撤销, 6:已删除, 7:提交失败, 8:提交结果未知)"`
ApprovalStatusName string `json:"approval_status_name" description:"通用审批状态名称(中文)"`
ReleasedAt string `json:"released_at,omitempty" description:"本次冻结释放时间,空表示冻结仍未结算"`
CreatedAt string `json:"created_at" description:"创建时间"`
// 本次提交依据的提现资料资格校验留痕,冻结在尝试快照上,历史尝试不被新版本改写。
QualificationVersionID uint `json:"qualification_version_id" description:"本次依据的有效提现资料资格版本ID0 表示资格不存在或早于本变更的历史尝试"`
QualificationCheckedAt string `json:"qualification_checked_at,omitempty" description:"本次资料资格校验时间,空表示历史尝试无留痕"`
QualificationPassed int `json:"qualification_passed" description:"本次资料资格校验是否通过 (0:未通过, 1:通过)"`
QualificationFailureReason string `json:"qualification_failure_reason" description:"未通过时的稳定原因编码 (qualification_missing:资格不存在, qualification_invalidated:已失效, shop_disabled:已停用, qualification_not_approved:资料未通过审批),通过时为空"`
QualificationFailureName string `json:"qualification_failure_name" description:"未通过原因中文名称,通过时为空"`
ReleasedAt string `json:"released_at,omitempty" description:"本次冻结释放时间,空表示冻结仍未结算"`
CreatedAt string `json:"created_at" description:"创建时间"`
}
// ShopWithdrawalRequestDetailResp 提现申请详情响应。

View File

@@ -71,9 +71,23 @@ type AssetResolveResponse struct {
GatewayExtend string `json:"gateway_extend" description:"Gateway 卡状态扩展字段,原样返回上游 extend用于展示运营商侧实际停机原因"`
GatewayCardIMEI string `json:"gateway_card_imei" description:"插拔卡业务 IMEI由 Gateway 卡状态接口同步,非设备自身 IMEI无业务含义仅供查看"`
// 流量汇总字段(仅在 ?include_usage_summary=true 时返回非 null 值)
TotalVirtualUsedMB *float64 `json:"total_virtual_used_mb" description:"当前世代所有套餐虚已用之和MB未请求时为 null"`
TotalVirtualRemainingMB *float64 `json:"total_virtual_remaining_mb" description:"当前世代所有套餐虚剩余之和MB未请求时为 null"`
ExchangeTrace *AssetExchangeTrace `json:"exchange_trace" description:"换货链路;对象始终存在,前代或后代不存在时对应字段为 null"`
TotalVirtualUsedMB *float64 `json:"total_virtual_used_mb" description:"当前世代所有套餐虚已用之和MB未请求时为 null"`
TotalVirtualRemainingMB *float64 `json:"total_virtual_remaining_mb" description:"当前世代所有套餐虚剩余之和MB未请求时为 null"`
ExchangeTrace *AssetExchangeTrace `json:"exchange_trace" description:"换货链路;对象始终存在,前代或后代不存在时对应字段为 null"`
PriorityPolling *AssetPriorityPollingProjection `json:"priority_polling" description:"优先轮询状态只读投影;对象始终存在,无任何优先轮询事实时字段以否或空值返回,不使用普通轮询结果填充"`
}
// AssetPriorityPollingProjection 是资产解析响应中的优先轮询状态只读投影。
// 口径与该卡(设备取其在用卡)在优先轮询事实表中的未完成活动项一致;
// 读取不创建、不合并、不推进、不出队任何优先项,也不触发上游调用。
type AssetPriorityPollingProjection struct {
InPriorityPolling bool `json:"in_priority_polling" description:"是否处于优先轮询中:存在待执行或执行中的优先轮询项"`
LastTriggerType string `json:"last_trigger_type,omitempty" description:"最近触发场景触发类型purchase_activated-主套餐购买后立即生效 renewal_activated-续购套餐生效 queue_activated-排队主套餐顺延生效 addon_activated-加油包生效 no_valid_package-资产无有效套餐 manual_trigger-人工入队"`
LastTriggerName string `json:"last_trigger_name,omitempty" description:"最近触发场景名称"`
LastResult string `json:"last_result,omitempty" description:"最近轮询结果processing-处理中 success-执行成功 failed-轮询失败 closed-已关闭 expired-已过期"`
LastResultName string `json:"last_result_name,omitempty" description:"最近轮询结果名称"`
LastPollingAt *time.Time `json:"last_polling_at" description:"最近轮询时间:最近一次优先执行时间,未执行过时取最近触发时间;无优先轮询事实时为 null"`
FailureReason string `json:"failure_reason,omitempty" description:"最近一次可安全展示的失败原因;无失败时为 empty"`
}
// AssetExchangeTrace 资产单节点双向换货链路。

View File

@@ -1,5 +1,7 @@
package dto
import "time"
type CreateCarrierRequest struct {
CarrierCode string `json:"carrier_code" validate:"required,min=1,max=50" required:"true" minLength:"1" maxLength:"50" description:"运营商编码"`
CarrierName string `json:"carrier_name" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"运营商名称"`
@@ -88,3 +90,55 @@ type CarrierPageResult struct {
Page int `json:"page" description:"当前页"`
PageSize int `json:"size" description:"每页数量"`
}
// CarrierThresholdHitListRequest 是通道阈值命中记录的查询参数。
//
// 判定时间使用统一时间筛选参数名 start_time/end_time带显式时区的 RFC3339 秒级,闭区间含两端,
// 开始晚于结束拒绝);计费周期起点用周期起点的瞬时精确匹配,与判定时间共用同一严格解析器。
type CarrierThresholdHitListRequest 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"`
CarrierID *uint `json:"carrier_id" query:"carrier_id" validate:"omitempty,min=1" minimum:"1" description:"运营商通道ID"`
CardID *uint `json:"card_id" query:"card_id" validate:"omitempty,min=1" minimum:"1" description:"IoT卡ID"`
// PeriodStart 为计费周期起点,取值必须与命中事实记录的周期起点时刻一致(如东八区 2026-09-01T00:00:00+08:00
PeriodStart string `json:"period_start" query:"period_start" description:"计费周期起点带时区的RFC3339秒级时间精确匹配该计费周期"`
StartTime string `json:"start_time" query:"start_time" description:"判定时间范围开始带时区的RFC3339秒级时间闭区间含该时刻"`
EndTime string `json:"end_time" query:"end_time" description:"判定时间范围结束带时区的RFC3339秒级时间闭区间含该时刻"`
}
// CarrierThresholdHitItem 是一条通道阈值命中事实。
//
// 累计流量与阈值为命中时冻结的证据:历史行(本次上线前)未记录读数与阈值,按「无」返回空值,
// 不阻断查询;判定时间取既有创建时间。响应不包含任何凭证与上游响应原文。
type CarrierThresholdHitItem struct {
ID uint `json:"id" description:"命中记录ID"`
CarrierID uint `json:"carrier_id" description:"运营商通道ID"`
CardID uint `json:"card_id" description:"IoT卡ID"`
// PeriodStart 是计费周期起点。
PeriodStart time.Time `json:"period_start" description:"计费周期起点"`
// HitTrafficMB 为空表示无(历史行读数不可重建)。
HitTrafficMB *float64 `json:"hit_traffic_mb" description:"命中时该卡当前计费周期的累计流量读数(MB),取与停机判定同一来源的网关累计读数,不使用本地用量或套餐真流量;为空表示无"`
// HitThresholdValue 为空表示无(历史行未记录)。
HitThresholdValue *float64 `json:"hit_threshold_value" description:"本次判定实际生效的通道阈值数值,冻结命中时值,通道阈值变更不改写历史命中;为空表示无"`
// HitThresholdUnit 为空字符串表示无(历史行未记录)。
HitThresholdUnit string `json:"hit_threshold_unit" description:"本次判定阈值单位 MB-兆字节 GB-吉字节;空字符串表示无"`
// TriggerSource 取值与 constants.CardObservationSource* 一致,空字符串表示无。
TriggerSource string `json:"trigger_source" description:"触发本次判定的流量观测来源 polling-周期轮询 manual_sync-手动同步 manual_override-人工纠偏 carrier_callback-运营商回调 business_event-业务成功后的观测;空字符串表示无"`
JudgedAt time.Time `json:"judged_at" description:"判定时间,既有锁行取创建时间"`
Status string `json:"status" description:"锁状态 locked-持锁中 unlocked-已跨期解锁"`
// UnlockedAt 为空表示尚未解锁。
UnlockedAt *time.Time `json:"unlocked_at" description:"周期恢复的解锁时间,未解锁为空"`
// ResumeResult 为空字符串表示未处理或历史行。
ResumeResult string `json:"resume_result" description:"周期恢复的复机结果 resumed-已发起复机 skipped-仅解锁未复机 manual-周期归属不可判定转人工;空字符串表示未处理或历史行"`
// FailureReason 只承载可安全展示的跳过原因或转人工原因,不含内部细节与渠道报文。
FailureReason string `json:"failure_reason" description:"跳过复机或转人工核对的可安全原因,无则为空"`
CreatedAt time.Time `json:"created_at" description:"记录创建时间"`
}
// CarrierThresholdHitPageResult 是通道阈值命中记录的分页结果。
type CarrierThresholdHitPageResult struct {
List []*CarrierThresholdHitItem `json:"items" description:"通道阈值命中记录列表,按判定时间倒序"`
Total int64 `json:"total" description:"总数"`
Page int `json:"page" description:"当前页"`
PageSize int `json:"size" description:"每页数量"`
}

View File

@@ -55,27 +55,37 @@ type EmployeeCollectionPaymentMethodListResponse struct {
// 枚举说明source_type 对应 constants.EmployeeCollectionSourceTypeOrder/Recharge
// status 对应 constants.EmployeeCollectionBillStatusPending/Partial/Settled/Closed。
type EmployeeCollectionBillListRequest 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"`
SourceType *string `json:"source_type" query:"source_type" validate:"omitempty,oneof=order recharge" enum:"order,recharge" description:"按来源类型过滤 (order:后台线下套餐订单, recharge:代理线下充值)"`
SourceNo *string `json:"source_no" query:"source_no" validate:"omitempty,max=64" maxLength:"64" description:"按来源单号精确过滤"`
Status *int `json:"status" query:"status" validate:"omitempty,oneof=0 1 2 3" enum:"0,1,2,3" description:"按账单状态过滤 (0:待核销, 1:部分核销, 2:已核销, 3:已关闭)"`
DebtorAccountID *uint `json:"debtor_account_id" query:"debtor_account_id" description:"按欠款人后台账号ID过滤非超级管理员固定为当前账号该参数被忽略"`
CustomerID *uint `json:"customer_id" query:"customer_id" description:"按来源客户或店铺ID过滤匹配来源订单买家或充值归属店铺"`
CreatedFrom *string `json:"created_from" query:"created_from" description:"创建时间起始YYYY-MM-DD含当日 00:00:00"`
CreatedTo *string `json:"created_to" query:"created_to" description:"创建时间截止YYYY-MM-DD含当日 23:59:59"`
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"`
BillID *uint `json:"bill_id" query:"bill_id" validate:"omitempty,min=1" minimum:"1" description:"按账单编号精确过滤账单编号即账单记录标识主键ID"`
SourceType *string `json:"source_type" query:"source_type" validate:"omitempty,oneof=order recharge" enum:"order,recharge" description:"按来源类型过滤 (order:后台线下套餐订单, recharge:代理线下充值)"`
SourceNo *string `json:"source_no" query:"source_no" validate:"omitempty,max=64" maxLength:"64" description:"按来源单号精确过滤"`
Status *int `json:"status" query:"status" validate:"omitempty,oneof=0 1 2 3" enum:"0,1,2,3" description:"按账单状态过滤 (0:待核销, 1:部分核销, 2:已核销, 3:已关闭)"`
DebtorAccountID *uint `json:"debtor_account_id" query:"debtor_account_id" description:"按欠款人后台账号ID过滤非超级管理员固定为当前账号该参数被忽略"`
DebtorKeyword *string `json:"debtor_keyword" query:"debtor_keyword" validate:"omitempty,max=50" maxLength:"50" description:"按欠款人姓名或账号模糊过滤,取去空白后的子串匹配,最多 50 字符无需先取得账号ID"`
CustomerKeyword *string `json:"customer_keyword" query:"customer_keyword" validate:"omitempty,max=50" maxLength:"50" description:"按客户名称模糊过滤,取去空白后的子串匹配,最多 50 字符无需先取得客户ID"`
CustomerID *uint `json:"customer_id" query:"customer_id" description:"按来源客户或店铺ID过滤匹配来源订单买家或充值归属店铺"`
StartTime *string `json:"start_time" query:"start_time" description:"账单产生时间起始,必须是带显式时区的 RFC3339 秒级时间(如 2026-09-01T00:00:00+08:00闭区间含该时刻"`
EndTime *string `json:"end_time" query:"end_time" description:"账单产生时间截止,必须是带显式时区的 RFC3339 秒级时间,闭区间含该时刻"`
DecidedStartTime *string `json:"decided_start_time" query:"decided_start_time" description:"核销通过时间起始,取该账单已通过分摊关联的申请表审批终态时间;格式与 start_time 相同,闭区间含该时刻"`
DecidedEndTime *string `json:"decided_end_time" query:"decided_end_time" description:"核销通过时间截止,取该账单已通过分摊关联的申请表审批终态时间;格式与 end_time 相同,闭区间含该时刻"`
}
// EmployeeCollectionBillStatisticsRequest 查询员工代收款账单统计请求。
// 与账单列表使用同一批筛选字段与可见性范围,但不接受分页参数。
type EmployeeCollectionBillStatisticsRequest struct {
SourceType *string `json:"source_type" query:"source_type" validate:"omitempty,oneof=order recharge" enum:"order,recharge" description:"按来源类型过滤 (order:后台线下套餐订单, recharge:代理线下充值)"`
SourceNo *string `json:"source_no" query:"source_no" validate:"omitempty,max=64" maxLength:"64" description:"按来源单号精确过滤"`
Status *int `json:"status" query:"status" validate:"omitempty,oneof=0 1 2 3" enum:"0,1,2,3" description:"按账单状态过滤 (0:待核销, 1:部分核销, 2:已核销, 3:已关闭)"`
DebtorAccountID *uint `json:"debtor_account_id" query:"debtor_account_id" description:"按欠款人后台账号ID过滤非超级管理员固定为当前账号该参数被忽略"`
CustomerID *uint `json:"customer_id" query:"customer_id" description:"按来源客户或店铺ID过滤匹配来源订单买家或充值归属店铺"`
CreatedFrom *string `json:"created_from" query:"created_from" description:"创建时间起始YYYY-MM-DD含当日 00:00:00"`
CreatedTo *string `json:"created_to" query:"created_to" description:"创建时间截止YYYY-MM-DD含当日 23:59:59"`
BillID *uint `json:"bill_id" query:"bill_id" validate:"omitempty,min=1" minimum:"1" description:"按账单编号精确过滤账单编号即账单记录标识主键ID"`
SourceType *string `json:"source_type" query:"source_type" validate:"omitempty,oneof=order recharge" enum:"order,recharge" description:"按来源类型过滤 (order:后台线下套餐订单, recharge:代理线下充值)"`
SourceNo *string `json:"source_no" query:"source_no" validate:"omitempty,max=64" maxLength:"64" description:"按来源单号精确过滤"`
Status *int `json:"status" query:"status" validate:"omitempty,oneof=0 1 2 3" enum:"0,1,2,3" description:"按账单状态过滤 (0:待核销, 1:部分核销, 2:已核销, 3:已关闭)"`
DebtorAccountID *uint `json:"debtor_account_id" query:"debtor_account_id" description:"按欠款人后台账号ID过滤非超级管理员固定为当前账号该参数被忽略"`
DebtorKeyword *string `json:"debtor_keyword" query:"debtor_keyword" validate:"omitempty,max=50" maxLength:"50" description:"按欠款人姓名或账号模糊过滤,取去空白后的子串匹配,最多 50 字符无需先取得账号ID"`
CustomerKeyword *string `json:"customer_keyword" query:"customer_keyword" validate:"omitempty,max=50" maxLength:"50" description:"按客户名称模糊过滤,取去空白后的子串匹配,最多 50 字符无需先取得客户ID"`
CustomerID *uint `json:"customer_id" query:"customer_id" description:"按来源客户或店铺ID过滤匹配来源订单买家或充值归属店铺"`
StartTime *string `json:"start_time" query:"start_time" description:"账单产生时间起始,必须是带显式时区的 RFC3339 秒级时间(如 2026-09-01T00:00:00+08:00闭区间含该时刻"`
EndTime *string `json:"end_time" query:"end_time" description:"账单产生时间截止,必须是带显式时区的 RFC3339 秒级时间,闭区间含该时刻"`
DecidedStartTime *string `json:"decided_start_time" query:"decided_start_time" description:"核销通过时间起始,取该账单已通过分摊关联的申请表审批终态时间;格式与 start_time 相同,闭区间含该时刻"`
DecidedEndTime *string `json:"decided_end_time" query:"decided_end_time" description:"核销通过时间截止,取该账单已通过分摊关联的申请表审批终态时间;格式与 end_time 相同,闭区间含该时刻"`
}
// EmployeeCollectionBillResponse 员工代收款账单行响应。
@@ -90,6 +100,7 @@ type EmployeeCollectionBillResponse struct {
CustomerSnapshot map[string]any `json:"customer_snapshot" description:"来源客户或店铺只读快照,不含付款凭证内容"`
ReceivableAmount int64 `json:"receivable_amount" description:"应收金额(分)"`
ReceivedAmount int64 `json:"received_amount" description:"已核销金额(分),仅企业微信最终通过的分摊计入"`
UnsettledAmount int64 `json:"unsettled_amount" description:"未核销金额(分),应收金额减已核销金额;已关闭账单为 0"`
ReservedAmount int64 `json:"reserved_amount" description:"审批中预占金额(分)"`
RemainingAmount int64 `json:"remaining_amount" description:"剩余可核销金额(分),已关闭账单为 0"`
Status int `json:"status" description:"账单状态 (0:待核销, 1:部分核销, 2:已核销, 3:已关闭)"`
@@ -194,10 +205,37 @@ type EmployeeCollectionBillApplicationResponse struct {
// EmployeeCollectionBillDetailResponse 员工代收款账单详情响应。
type EmployeeCollectionBillDetailResponse struct {
Bill *EmployeeCollectionBillResponse `json:"bill" description:"账单事实"`
Refunds []*EmployeeCollectionBillRefundResponse `json:"refunds" description:"来源订单退款冲销关联"`
Allocations []*EmployeeCollectionBillAllocationResponse `json:"allocations" description:"该账单的核销分摊"`
Applications []*EmployeeCollectionBillApplicationResponse `json:"applications" description:"涉及该账单的核销申请与审批历史"`
Bill *EmployeeCollectionBillResponse `json:"bill" description:"账单事实"`
Refunds []*EmployeeCollectionBillRefundResponse `json:"refunds" description:"来源订单退款冲销关联"`
Allocations []*EmployeeCollectionBillAllocationResponse `json:"allocations" description:"该账单的核销分摊"`
Applications []*EmployeeCollectionBillApplicationResponse `json:"applications" description:"涉及该账单的核销申请与审批历史"`
Operations []*EmployeeCollectionBillOperationLogResponse `json:"operations" description:"该账单的操作日志投影,按操作时间升序;仅含安全摘要,不含凭证内容与完整收款原文"`
SourceOrder *EmployeeCollectionBillSourceSnapshotResponse `json:"source_order" description:"来源订单或来源充值记录的只读快照;来源不可读或字段缺失时对应字段为空值,不影响详情其余内容"`
}
// EmployeeCollectionBillOperationLogResponse 是账单维度既有审计事实的安全投影。
// 只返回动作、操作账号名称快照、操作时间与变更前后摘要(白名单字段),
// MUST NOT 返回支付凭证内容、完整收款信息或其它敏感原文。
type EmployeeCollectionBillOperationLogResponse struct {
ActionCode string `json:"action_code" description:"稳定动作编码"`
ActionName string `json:"action_name" description:"动作中文名称"`
Summary string `json:"summary" description:"事件中文摘要"`
OperatorName string `json:"operator_name" description:"操作账号名称快照"`
OccurredAt time.Time `json:"occurred_at" description:"操作发生时间"`
Result string `json:"result" description:"操作结果 (success:成功, failed:失败, denied:拒绝, partial:部分成功, unknown:未知)"`
BeforeSummary map[string]any `json:"before_summary" description:"变更前安全摘要,只包含允许展示的账单字段"`
AfterSummary map[string]any `json:"after_summary" description:"变更后安全摘要,只包含允许展示的账单字段"`
}
// EmployeeCollectionBillSourceSnapshotResponse 是来源订单或来源充值记录的只读快照投影。
// 来源记录已不可读或字段缺失时对应字段为空值,详情其余内容正常返回。
type EmployeeCollectionBillSourceSnapshotResponse struct {
SourceType string `json:"source_type" description:"来源业务类型 (order:后台线下套餐订单, recharge:代理线下充值)"`
SourceTypeName string `json:"source_type_name" description:"来源业务类型中文名称"`
SourceNo string `json:"source_no" description:"来源单号"`
Amount int64 `json:"amount" description:"来源实收金额或充值金额(分)"`
CreatedAt *time.Time `json:"created_at,omitempty" description:"来源记录创建时间"`
AssetIdentifier string `json:"asset_identifier" description:"来源资产标识卡为ICCID设备优先虚拟号其次IMEI来源无资产维度或不可读时为空"`
}
// CloseEmployeeCollectionBillRequest 关闭员工代收款账单请求

View File

@@ -8,6 +8,7 @@ import "time"
type CreateH5PopupConfigurationRequest struct {
Title string `json:"title" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"弹窗标题1100 字符;投放时冻结写入通知标题"`
Content string `json:"content" validate:"required,min=1,max=2000" required:"true" minLength:"1" maxLength:"2000" description:"弹窗正文12000 字符;投放时冻结写入通知正文,不接受 HTML、URL 或前端路由"`
PopupType string `json:"popup_type" validate:"required,oneof=promotion announcement" required:"true" enum:"promotion,announcement" description:"弹窗类型,必填 (promotion:套餐政策推广, announcement:通用公告);类别优先级为风险换卡提醒 > 套餐政策推广 > 通用公告,类别优先于显式优先级"`
Pages []string `json:"pages" validate:"required,min=1,max=4,dive,oneof=home asset_detail package_purchase asset_wallet_recharge" required:"true" description:"命中页面集合,至少一项 (home:首页, asset_detail:资产详情, package_purchase:套餐购买, asset_wallet_recharge:资产钱包充值)"`
ShopIDs []uint `json:"shop_ids" validate:"omitempty,max=200,dive,min=1" maxLength:"200" description:"店铺范围;不传或空数组表示全量,同维度多选取任一命中"`
DeviceTypes []string `json:"device_types" validate:"omitempty,max=100,dive,min=1,max=50" maxLength:"100" description:"设备类型范围;不传或空数组表示全量;资产该维度无值(独立卡或未绑定设备)时不命中已配置范围"`
@@ -26,6 +27,7 @@ type CreateH5PopupConfigurationRequest struct {
type UpdateH5PopupConfigurationRequest struct {
Title *string `json:"title" validate:"omitempty,min=1,max=100" minLength:"1" maxLength:"100" description:"弹窗标题1100 字符;不传保持原值"`
Content *string `json:"content" validate:"omitempty,min=1,max=2000" minLength:"1" maxLength:"2000" description:"弹窗正文12000 字符;不传保持原值,不接受 HTML、URL 或前端路由"`
PopupType *string `json:"popup_type" validate:"omitempty,oneof=promotion announcement" enum:"promotion,announcement" description:"弹窗类型 (promotion:套餐政策推广, announcement:通用公告);不传保持原值。类别优先级为风险换卡提醒 > 套餐政策推广 > 通用公告,类别优先于显式优先级"`
Pages *[]string `json:"pages" validate:"omitempty,min=1,max=4,dive,oneof=home asset_detail package_purchase asset_wallet_recharge" description:"命中页面集合;不传保持原值,传空数组等价于非法(页面必选)"`
ShopIDs *[]uint `json:"shop_ids" validate:"omitempty,max=200,dive,min=1" maxLength:"200" description:"店铺范围;不传保持原值,传空数组表示改为全量"`
DeviceTypes *[]string `json:"device_types" validate:"omitempty,max=100,dive,min=1,max=50" maxLength:"100" description:"设备类型范围;不传保持原值,传空数组表示改为全量"`
@@ -55,6 +57,8 @@ type H5PopupConfigurationResponse struct {
ID uint `json:"id" description:"配置ID"`
Title string `json:"title" description:"弹窗标题"`
Content string `json:"content" description:"弹窗正文"`
PopupType string `json:"popup_type" enums:"promotion,announcement" description:"弹窗类型 (promotion:套餐政策推广, announcement:通用公告)"`
PopupTypeText string `json:"popup_type_text" description:"弹窗类型名称(中文)"`
Pages []string `json:"pages" enums:"home,asset_detail,package_purchase,asset_wallet_recharge" description:"命中页面集合 (home:首页, asset_detail:资产详情, package_purchase:套餐购买, asset_wallet_recharge:资产钱包充值)"`
ShopIDs []uint `json:"shop_ids" description:"店铺范围;空数组表示全量"`
DeviceTypes []string `json:"device_types" description:"设备类型范围;空数组表示全量"`

View File

@@ -21,21 +21,21 @@ type CreatePackageRequest struct {
// UpdatePackageRequest 更新套餐请求
type UpdatePackageRequest struct {
PackageName *string `json:"package_name" validate:"omitempty,min=1,max=255" minLength:"1" maxLength:"255" description:"套餐名称"`
SeriesID *uint `json:"series_id" validate:"omitempty" description:"套餐系列ID"`
PackageType *string `json:"package_type" validate:"omitempty,oneof=formal addon" description:"套餐类型 (formal:正式套餐, addon:附加套餐)"`
IsGift *bool `json:"is_gift" description:"是否赠送套餐"`
DurationMonths *int `json:"duration_months" validate:"omitempty,min=1,max=120" minimum:"1" maximum:"120" description:"套餐时长(月数)"`
RealDataMB *int64 `json:"real_data_mb" validate:"omitempty,min=0" minimum:"0" description:"真流量额度(MB)"`
VirtualDataMB *int64 `json:"virtual_data_mb" validate:"omitempty,min=0" minimum:"0" description:"虚流量额度(MB)"`
EnableVirtualData *bool `json:"enable_virtual_data" description:"是否启用虚流量"`
SuggestedRetailPrice *int64 `json:"suggested_retail_price" validate:"omitempty,min=0" minimum:"0" description:"建议售价原始值(分普通可售套餐留空表示未配置赠送套餐必须显式为0)"`
ClearSuggestedRetailPrice bool `json:"clear_suggested_retail_price" description:"是否清空建议售价并恢复为未配置状态"`
CostPrice *int64 `json:"cost_price" validate:"omitempty,min=0" minimum:"0" description:"成本价(分)"`
CalendarType *string `json:"calendar_type" validate:"omitempty,oneof=natural_month by_day" description:"套餐周期类型 (natural_month:自然月, by_day:按天)"`
DurationDays *int `json:"duration_days" validate:"omitempty,min=1,max=3650" minimum:"1" maximum:"3650" description:"套餐天数(calendar_type=by_day时必填)"`
DataResetCycle *string `json:"data_reset_cycle" validate:"omitempty,oneof=daily monthly yearly none" description:"流量重置周期 (daily:每日, monthly:每月, yearly:每年, none:不重置)"`
ExpiryBase *string `json:"expiry_base" validate:"omitempty,oneof=from_activation from_purchase" description:"到期时间基准 (from_activation:实名激活时起算, from_purchase:购买时起算)"`
PackageName *string `json:"package_name" validate:"omitempty,min=1,max=255" minLength:"1" maxLength:"255" description:"套餐名称"`
SeriesID *uint `json:"series_id" validate:"omitempty" description:"套餐系列ID"`
PackageType *string `json:"package_type" validate:"omitempty,oneof=formal addon" description:"套餐类型 (formal:正式套餐, addon:附加套餐)"`
IsGift *bool `json:"is_gift" description:"是否赠送套餐"`
DurationMonths *int `json:"duration_months" validate:"omitempty,min=1,max=120" minimum:"1" maximum:"120" description:"套餐时长(月数)"`
RealDataMB *int64 `json:"real_data_mb" validate:"omitempty,min=0" minimum:"0" description:"真流量额度(MB)"`
VirtualDataMB *int64 `json:"virtual_data_mb" validate:"omitempty,min=0" minimum:"0" description:"虚流量额度(MB)"`
EnableVirtualData *bool `json:"enable_virtual_data" description:"是否启用虚流量"`
SuggestedRetailPrice *int64 `json:"suggested_retail_price" validate:"omitempty,min=0" minimum:"0" description:"建议售价原始值(分普通可售套餐留空表示未配置赠送套餐必须显式为0)"`
ClearSuggestedRetailPrice bool `json:"clear_suggested_retail_price" description:"是否清空建议售价并恢复为未配置状态"`
CostPrice *int64 `json:"cost_price" validate:"omitempty,min=0" minimum:"0" description:"成本价(分)"`
CalendarType *string `json:"calendar_type" validate:"omitempty,oneof=natural_month by_day" description:"套餐周期类型 (natural_month:自然月, by_day:按天)"`
DurationDays *int `json:"duration_days" validate:"omitempty,min=1,max=3650" minimum:"1" maximum:"3650" description:"套餐天数(calendar_type=by_day时必填)"`
DataResetCycle *string `json:"data_reset_cycle" validate:"omitempty,oneof=daily monthly yearly none" description:"流量重置周期 (daily:每日, monthly:每月, yearly:每年, none:不重置)"`
ExpiryBase *string `json:"expiry_base" validate:"omitempty,oneof=from_activation from_purchase" description:"到期时间基准 (from_activation:实名激活时起算, from_purchase:购买时起算)"`
}
// PackageListRequest 套餐列表请求

View File

@@ -93,6 +93,11 @@ type PaymentMerchantPoolResponse struct {
TimePeriodStartedAt *time.Time `json:"time_period_started_at,omitempty" description:"时间轮询起始时间"`
RoutingEpoch int64 `json:"routing_epoch" description:"当前路由统计世代"`
MemberIDs []uint `json:"member_ids" description:"有序商户ID列表"`
EnabledMemberCount int `json:"enabled_member_count" description:"启用成员数量,即成员中当前启用的商户数量"`
MemberCount int `json:"member_count" description:"成员总数量"`
CurrentMerchantID *uint `json:"current_merchant_id,omitempty" description:"当前命中商户ID商户池停用或无可用成员时为空"`
CurrentMerchantName string `json:"current_merchant_name,omitempty" description:"当前命中商户名称;商户池停用或无可用成员时为空"`
UpdatedAt time.Time `json:"updated_at" description:"最近配置更新时间"`
Remark string `json:"remark" description:"备注"`
}

View File

@@ -26,10 +26,13 @@ type PhoneAssetAssociationResponse struct {
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 手机号—资产关联列表分页响应。

View File

@@ -24,7 +24,7 @@ type EnqueuePriorityPollingItemView struct {
ItemID uint `json:"item_id" description:"优先轮询项ID"`
TaskType string `json:"task_type" description:"轮询任务类型"`
TaskTypeName string `json:"task_type_name" description:"轮询任务类型名称"`
Status string `json:"status" description:"状态pending-待执行 processing-执行中 completed-已完成 failed-失败出队"`
Status string `json:"status" description:"状态pending-待执行 processing-执行中 completed-已完成 failed-失败出队 closed-已关闭 expired-已过期"`
StatusName string `json:"status_name" description:"状态名称"`
TriggerCount int `json:"trigger_count" description:"累计触发次数(同一卡同一任务类型的后续触发合并计数)"`
LastTriggeredAt time.Time `json:"last_triggered_at" description:"最近触发时间"`
@@ -32,42 +32,59 @@ type EnqueuePriorityPollingItemView struct {
}
// PriorityPollingItemListRequest 是优先轮询项列表查询请求。
// 时间范围按入队时间created_at取闭区间复用统一时间筛选参数与语义。
type PriorityPollingItemListRequest 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"`
CardID *uint `json:"card_id" query:"card_id" validate:"omitempty" description:"按卡ID筛选"`
TaskType *string `json:"task_type" query:"task_type" validate:"omitempty,oneof=polling:realname polling:carddata polling:package polling:card_status" enum:"polling:realname,polling:carddata,polling:package,polling:card_status" description:"按轮询任务类型筛选polling:realname-实名检查 polling:carddata-流量检查 polling:package-套餐检查 polling:card_status-卡状态检查"`
Status *string `json:"status" query:"status" validate:"omitempty,oneof=pending processing completed failed" enum:"pending,processing,completed,failed" description:"按状态筛选pending-待执行 processing-执行中 completed-已完成 failed-失败出队"`
TriggerType *string `json:"trigger_type" query:"trigger_type" validate:"omitempty,oneof=purchase_activated renewal_activated queue_activated addon_activated no_valid_package manual_trigger" enum:"purchase_activated,renewal_activated,queue_activated,addon_activated,no_valid_package,manual_trigger" description:"按触发类型筛选purchase_activated-主套餐购买后立即生效 renewal_activated-续购套餐生效 queue_activated-排队主套餐顺延生效 addon_activated-加油包生效 no_valid_package-资产无有效套餐 manual_trigger-人工入队"`
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"`
CardID *uint `json:"card_id" query:"card_id" validate:"omitempty" description:"按卡ID筛选"`
TaskType *string `json:"task_type" query:"task_type" validate:"omitempty,oneof=polling:realname polling:carddata polling:package polling:card_status" enum:"polling:realname,polling:carddata,polling:package,polling:card_status" description:"按轮询任务类型筛选polling:realname-实名检查 polling:carddata-流量检查 polling:package-套餐检查 polling:card_status-卡状态检查"`
Status *string `json:"status" query:"status" validate:"omitempty,oneof=pending processing completed failed closed expired" enum:"pending,processing,completed,failed,closed,expired" description:"按状态筛选pending-待执行 processing-执行中 completed-已完成 failed-失败出队 closed-已关闭 expired-已过期"`
TriggerType *string `json:"trigger_type" query:"trigger_type" validate:"omitempty,oneof=purchase_activated renewal_activated queue_activated addon_activated no_valid_package manual_trigger" enum:"purchase_activated,renewal_activated,queue_activated,addon_activated,no_valid_package,manual_trigger" description:"按触发类型筛选purchase_activated-主套餐购买后立即生效 renewal_activated-续购套餐生效 queue_activated-排队主套餐顺延生效 addon_activated-加油包生效 no_valid_package-资产无有效套餐 manual_trigger-人工入队"`
StartTime string `json:"start_time" query:"start_time" description:"入队时间起始(带时区的 RFC3339 秒级时间,闭区间含该时刻,如 2026-09-01T00:00:00+08:00"`
EndTime string `json:"end_time" query:"end_time" description:"入队时间结束(格式与 start_time 一致,闭区间含该时刻);开始晚于结束被拒绝"`
AbnormalOnly *bool `json:"abnormal_only" query:"abnormal_only" description:"「异常与重试」视图:仅返回失败终态、已过期、尝试次数达到上限或存在失败原因的优先项;与其他筛选取与关系"`
}
// PriorityPollingItemResponse 是优先轮询项的读侧投影。
// 不含优先级分级:本能力不提供 P0/P1/P2 分级字段。
type PriorityPollingItemResponse struct {
ID uint `json:"id" description:"优先轮询项ID"`
CardID uint `json:"card_id" description:"卡ID"`
ICCID string `json:"iccid,omitempty" description:"卡ICCID卡已不存在时为空"`
TaskType string `json:"task_type" description:"轮询任务类型"`
TaskTypeName string `json:"task_type_name" description:"轮询任务类型名称"`
Status string `json:"status" description:"状态pending-待执行 processing-执行中 completed-已完成 failed-失败出队"`
StatusName string `json:"status_name" description:"状态名称"`
TriggerType string `json:"trigger_type" description:"首次触发类型purchase_activated renewal_activated queue_activated addon_activated no_valid_package manual_trigger"`
TriggerTypeName string `json:"trigger_type_name" description:"首次触发类型名称"`
TriggerTypes string `json:"trigger_types" description:"触发来源集合(去重后的全部触发类型,英文逗号分隔)"`
TriggerCount int `json:"trigger_count" description:"累计触发次数"`
LastTriggeredAt time.Time `json:"last_triggered_at" description:"最近触发时间"`
SourceOrderID *uint `json:"source_order_id,omitempty" description:"来源订单ID"`
SourcePackageUse *uint `json:"source_package_usage_id,omitempty" description:"来源套餐使用记录ID"`
AttemptCount int `json:"attempt_count" description:"真实发起执行的次数上限3次"`
ClaimedAt *time.Time `json:"claimed_at,omitempty" description:"最近认领时间"`
ManualReason string `json:"manual_reason,omitempty" description:"人工入队原因"`
ManualOperator uint `json:"manual_operator_id,omitempty" description:"人工入队操作者账号ID"`
ManualOperatorNm string `json:"manual_operator_name,omitempty" description:"人工入队操作者名称"`
ShopIDSnapshot *uint `json:"shop_id_snapshot,omitempty" description:"触发时冻结的卡所属店铺ID平台卡为空"`
Result string `json:"result" description:"执行结果success-成功 failed-失败,未出结果时为空"`
ResultName string `json:"result_name" description:"执行结果名称"`
FailureReason string `json:"failure_reason,omitempty" description:"可安全展示的失败原因"`
CreatedAt time.Time `json:"created_at" description:"创建时间"`
UpdatedAt time.Time `json:"updated_at" description:"最近更新时间"`
ID uint `json:"id" description:"优先轮询项ID"`
CardID uint `json:"card_id" description:"卡ID"`
ICCID string `json:"iccid,omitempty" description:"卡ICCID卡已不存在时为空"`
AssetType string `json:"asset_type" description:"资产类型iot_card-物联网卡 device-设备(入队时按设备—卡绑定冻结,独立卡为卡自身)"`
AssetID *uint `json:"asset_id" description:"资产ID与 asset_type 共同构成资产身份);历史行未回填时为 null"`
DeviceNo string `json:"device_no,omitempty" description:"设备号快照(资产绑定设备时的设备虚拟号,独立卡为空)"`
TaskType string `json:"task_type" description:"轮询任务类型"`
TaskTypeName string `json:"task_type_name" description:"轮询任务类型名称"`
Status string `json:"status" description:"状态pending-待执行 processing-执行中 completed-已完成 failed-失败出队 closed-已关闭 expired-已过期"`
StatusName string `json:"status_name" description:"状态名称"`
TriggerType string `json:"trigger_type" description:"首次触发类型purchase_activated renewal_activated queue_activated addon_activated no_valid_package manual_trigger"`
TriggerTypeName string `json:"trigger_type_name" description:"首次触发类型名称"`
TriggerTypes string `json:"trigger_types" description:"触发来源集合(去重后的全部触发类型,英文逗号分隔)"`
TriggerCount int `json:"trigger_count" description:"累计触发次数"`
LastTriggeredAt time.Time `json:"last_triggered_at" description:"最近触发时间"`
SourceOrderID *uint `json:"source_order_id,omitempty" description:"来源订单ID"`
SourcePackageUse *uint `json:"source_package_usage_id,omitempty" description:"来源套餐使用记录ID"`
AttemptCount int `json:"attempt_count" description:"真实发起执行的次数"`
AttemptLimit int `json:"attempt_limit" description:"最大尝试次数(固定常量,只读;达到后记录失败终态并出队)"`
ClaimedAt *time.Time `json:"claimed_at,omitempty" description:"最近认领时间"`
StartedAt *time.Time `json:"started_at,omitempty" description:"最近一次执行开始时间(未发起执行时为 null"`
FinishedAt *time.Time `json:"finished_at,omitempty" description:"最近一次执行结束时间(未发起执行时为 null"`
DurationMS int64 `json:"duration_ms" description:"最近一次执行耗时(毫秒);执行开始或结束时间缺失时为 0"`
NextRunAt *time.Time `json:"next_run_at" description:"下一次计划执行时间;未排期为 null读侧不据此判定已过期"`
PriorityEffectiveFrom *time.Time `json:"priority_effective_from" description:"有效期起算时间(入队时间,只读);历史终态行为 null"`
DequeuedAt *time.Time `json:"dequeued_at" description:"出队时间(任一终态写入);仍在队列中时为 null"`
ManualReason string `json:"manual_reason,omitempty" description:"人工入队原因"`
ManualOperator uint `json:"manual_operator_id,omitempty" description:"人工入队操作者账号ID"`
ManualOperatorNm string `json:"manual_operator_name,omitempty" description:"人工入队操作者名称"`
ShopIDSnapshot *uint `json:"shop_id_snapshot,omitempty" description:"触发时冻结的卡所属店铺ID平台卡为空"`
AgentShopID *uint `json:"agent_shop_id_snapshot,omitempty" description:"代理归属卡所属店铺的直接上级代理店铺ID一级代理与平台卡为空"`
Result string `json:"result" description:"执行结果success-成功 failed-失败,未出结果时为空"`
ResultName string `json:"result_name" description:"执行结果名称"`
FailureReason string `json:"failure_reason,omitempty" description:"可安全展示的最近一次失败原因"`
IntegrationLogID string `json:"integration_log_id,omitempty" description:"最近一次上游交互的集成交互日志标识(不含凭证与响应原文)"`
CreatedAt time.Time `json:"created_at" description:"入队时间(创建时间)"`
UpdatedAt time.Time `json:"updated_at" description:"最近更新时间"`
}
// PriorityPollingItemListResponse 是优先轮询项列表响应。
@@ -78,3 +95,42 @@ type PriorityPollingItemListResponse struct {
// 与 pkg/response.PaginationData 一致:响应侧字段名为 size请求侧仍用 page_size。
PageSize int `json:"size" description:"每页条数"`
}
// ClosePriorityPollingItemRequest 是人工关闭优先轮询项请求。
type ClosePriorityPollingItemRequest struct {
Reason string `json:"reason" validate:"required,min=1,max=500" description:"人工关闭原因必填最长500字符写入审计"`
}
// ClosePriorityPollingItemResponse 是人工关闭优先轮询项结果。
type ClosePriorityPollingItemResponse struct {
ItemID uint `json:"item_id" description:"优先轮询项ID"`
CardID uint `json:"card_id" description:"卡ID"`
TaskType string `json:"task_type" description:"轮询任务类型"`
TaskTypeName string `json:"task_type_name" description:"轮询任务类型名称"`
Status string `json:"status" description:"关闭后的状态closed-已关闭"`
StatusName string `json:"status_name" description:"状态名称"`
DequeuedAt time.Time `json:"dequeued_at" description:"出队时间"`
Reason string `json:"reason" description:"本次人工关闭原因"`
}
// RetriggerPriorityPollingItemRequest 是失败或已过期优先项的人工重触发请求。
type RetriggerPriorityPollingItemRequest struct {
Reason string `json:"reason" validate:"required,min=1,max=500" description:"人工重触发原因必填最长500字符写入审计"`
}
// RetriggerPriorityPollingItemResponse 是人工重触发结果。
// attempt_count 恒为 0重触发为该卡该任务类型建立新的活动项尝试次数从零开始。
type RetriggerPriorityPollingItemResponse struct {
SourceItemID uint `json:"source_item_id" description:"被重触发的原终态优先轮询项ID"`
CardID uint `json:"card_id" description:"卡ID"`
TaskType string `json:"task_type" description:"轮询任务类型"`
TaskTypeName string `json:"task_type_name" description:"轮询任务类型名称"`
ItemID uint `json:"item_id" description:"新建或合并到的活动优先轮询项ID"`
Status string `json:"status" description:"活动项状态pending-待执行 processing-执行中"`
StatusName string `json:"status_name" description:"状态名称"`
AttemptCount int `json:"attempt_count" description:"当前尝试次数(新活动项恒为 0"`
TriggerCount int `json:"trigger_count" description:"累计触发次数"`
LastTriggeredAt time.Time `json:"last_triggered_at" description:"最近触发时间"`
Reason string `json:"reason" description:"本次人工重触发原因"`
Created bool `json:"created" description:"是否新建活动项false 表示已合并到既有活动项"`
}

View File

@@ -8,8 +8,10 @@ type CreateRefundRequest struct {
CustomerAccountInfo string `json:"customer_account_info" validate:"omitempty,max=1000" maxLength:"1000" description:"客户收款信息,仅客户收款信息退款方式必填,不得复用公司线下收款方式字典"`
RequestedRefundAmount int64 `json:"requested_refund_amount" validate:"required,min=1" required:"true" minimum:"1" description:"申请退款金额(分)"`
RefundVoucherKey []string `json:"refund_voucher_key" validate:"omitempty,max=5,dive,max=500" maxItems:"5" description:"退款凭证对象存储file_key列表最多5个仅客户收款信息退款方式必填通过/storage/upload-url上传图片后获得"`
RefundReason string `json:"refund_reason" validate:"omitempty,max=1000" maxLength:"1000" description:"退款原因"`
PackageUsageID *uint `json:"package_usage_id" validate:"omitempty" description:"关联套餐使用记录ID可选"`
RefundReason string `json:"refund_reason" validate:"required,max=1000" required:"true" maxLength:"1000" description:"退款原因(必填,去除首尾空白后不得为空)"`
// Remark 是申请人备注,随本次提交冻结进当次审批尝试快照;与审批备注(详情响应中的 remark语义不同。
Remark *string `json:"remark" validate:"omitempty,max=500" maxLength:"500" description:"申请人备注(可选,随本次提交冻结进审批尝试快照,不改变审批备注)"`
PackageUsageID *uint `json:"package_usage_id" validate:"omitempty" description:"关联套餐使用记录ID可选"`
}
// RefundIDRequest 退款申请ID路径参数
@@ -32,7 +34,9 @@ type ResubmitRefundRequest struct {
CustomerAccountInfo *string `json:"customer_account_info" validate:"omitempty,max=1000" maxLength:"1000" description:"客户收款信息,仅客户收款信息退款方式必填,不得复用公司线下收款方式字典"`
RequestedRefundAmount *int64 `json:"requested_refund_amount" validate:"omitempty,min=1" minimum:"1" description:"申请退款金额(分)"`
RefundVoucherKey *[]string `json:"refund_voucher_key" validate:"omitempty,max=5,dive,max=500" maxItems:"5" description:"退款凭证对象存储file_key列表重新提交时可替换客户收款信息退款方式必填最多5个"`
RefundReason *string `json:"refund_reason" validate:"omitempty,max=1000" maxLength:"1000" description:"退款原因"`
RefundReason *string `json:"refund_reason" validate:"omitempty,max=1000" maxLength:"1000" description:"退款原因(不填沿用原有原因;重提时去除首尾空白后不得为空)"`
// Remark 是本次重提的申请人备注,随本次尝试冻结;不填沿用该退款单最近一次尝试的备注。
Remark *string `json:"remark" validate:"omitempty,max=500" maxLength:"500" description:"申请人备注(可选,随本次重提冻结进新的审批尝试快照,历史尝试备注不被改写)"`
}
// ApproveRefundRequest 审批通过退款申请请求
@@ -71,51 +75,57 @@ type RefundResponse struct {
PackageUsageID *uint `json:"package_usage_id,omitempty" description:"关联套餐使用记录ID"`
// 当前退款套餐用量:按冻结套餐使用记录 → 订单主套餐 → 订单任一套餐的优先级解析,
// 只用于展示、查询与导出,不参与退款金额校验、套餐失效或佣金回溯。
RefundPackageUsedMB int64 `json:"refund_package_used_mb" description:"当前退款套餐已用量MB真实流量解析不到套餐时为0"`
RefundPackageTotalMB int64 `json:"refund_package_total_mb" description:"当前退款套餐总量MB真实流量解析不到套餐时为0"`
ShopID *uint `json:"shop_id,omitempty" description:"店铺ID"`
ShopName string `json:"shop_name,omitempty" description:"店铺名称"`
ActualReceivedAmount int64 `json:"actual_received_amount" description:"实收金额(分)"`
RequestedRefundAmount int64 `json:"requested_refund_amount" description:"申请退款金额(分)"`
ApprovedRefundAmount *int64 `json:"approved_refund_amount,omitempty" description:"审批实际退款金额(分)"`
RefundVoucherKey []string `json:"refund_voucher_key" description:"退款凭证对象存储file_key列表最多5个"`
RefundReason string `json:"refund_reason" description:"退款原因"`
Status int `json:"status" description:"状态 (1:待审批, 2:已通过, 3:已拒绝, 4:已退回, 5:原路退款处理中, 6:原路退款失败)"`
StatusName string `json:"status_name" description:"状态名称(中文)"`
Method string `json:"method" description:"退款方式 (original_route:原路退款, customer_account:客户收款信息退款, asset_wallet:退回资产钱包, agent_wallet:退回代理主钱包),空表示未接入方式的存量申请"`
MethodName string `json:"method_name" description:"退款方式中文名称"`
FrozenActualReceivedAmount int64 `json:"frozen_actual_received_amount" description:"系统派生并冻结的权威实收金额(分),作为可退金额上限"`
CustomerAccountInfo string `json:"customer_account_info" description:"客户收款信息自由文本快照,仅客户收款信息退款方式有值"`
ChannelRefundStatus int `json:"channel_refund_status" description:"渠道原路退款状态 (0:未发起, 1:处理中, 2:已成功, 3:已失败)0 表示未发起渠道退款或不适用该退款方式"`
ChannelRefundStatusName string `json:"channel_refund_status_name" description:"渠道原路退款状态中文名称"`
ChannelRefundNo string `json:"channel_refund_no" description:"渠道退款流水号,渠道明确成功或失败后回填"`
ChannelRefundRequestNo string `json:"channel_refund_request_no" description:"渠道退款请求号快照,用于幂等与对账"`
ChannelRefundAmount int64 `json:"channel_refund_amount" description:"提交渠道的退款金额快照(分)"`
ChannelRefundedAt string `json:"channel_refunded_at,omitempty" description:"渠道明确退款成功时间"`
FailureReason string `json:"failure_reason" description:"结构化失败分类稳定编码 (channel_rejected:渠道明确拒绝, credential_invalid:渠道凭证失效, insufficient_balance:渠道余额不足, timeout_unknown:超时或结果未知, approval_rejected:企业微信驳回或关闭, revoked_after_approved:企业微信通过后撤销, payment_fact_invalid:本地原支付事实不可用),空表示无失败"`
FailureReasonName string `json:"failure_reason_name" description:"失败分类中文名称"`
FailureMessage string `json:"failure_message" description:"失败安全摘要,供人工排查;不含渠道凭证等敏感内容"`
AnomalyFlag int `json:"anomaly_flag" description:"异常标记 (0:无异常, 1:有异常,需人工处理)"`
AnomalyReason string `json:"anomaly_reason" description:"异常原因说明,无异常时为空"`
LatestAttemptID uint `json:"latest_attempt_id" description:"最新审批尝试记录ID仅用于展示"`
LatestApprovalInstanceID uint `json:"latest_approval_instance_id" description:"最新通用审批实例ID仅用于展示"`
Attempts []RefundAttemptResponse `json:"attempts" description:"审批尝试记录,按提交顺序排列,历史材料不被覆盖;无尝试记录时为空数组"`
ProcessorID *uint `json:"processor_id,omitempty" description:"审批人ID"`
ProcessedAt string `json:"processed_at,omitempty" description:"审批时间"`
RejectReason string `json:"reject_reason,omitempty" description:"拒绝原因"`
Remark string `json:"remark,omitempty" description:"审批备注"`
CommissionDeducted bool `json:"commission_deducted" description:"佣金是否已回扣"`
AssetReset bool `json:"asset_reset" description:"退款后资产处理是否完成"`
SubmitterID uint `json:"submitter_id" description:"提交人账号ID"`
SubmitterName string `json:"submitter_name" description:"提交人账号名称"`
ApprovalInstanceID *uint `json:"approval_instance_id,omitempty" description:"通用审批实例ID"`
ApprovalProvider string `json:"approval_provider,omitempty" description:"审批渠道企业微信为wecom"`
ApprovalStatus *int `json:"approval_status,omitempty" description:"审批状态 (0:提交中, 1:审批中, 2:已通过, 3:已拒绝, 4:已撤销, 5:通过后撤销, 6:已删除, 7:提交失败, 8:提交结果未知)"`
ApprovalStatusName string `json:"approval_status_name,omitempty" description:"审批状态名称(中文)"`
Creator uint `json:"creator" description:"创建人ID"`
Updater uint `json:"updater" description:"更新人ID"`
CreatedAt string `json:"created_at" description:"创建时间"`
UpdatedAt string `json:"updated_at" description:"更新时间"`
RefundPackageUsedMB int64 `json:"refund_package_used_mb" description:"当前退款套餐已用量MB真实流量解析不到套餐时为0"`
RefundPackageTotalMB int64 `json:"refund_package_total_mb" description:"当前退款套餐总量MB真实流量解析不到套餐时为0"`
ShopID *uint `json:"shop_id,omitempty" description:"店铺ID"`
ShopName string `json:"shop_name,omitempty" description:"店铺名称"`
ActualReceivedAmount int64 `json:"actual_received_amount" description:"实收金额(分)"`
RequestedRefundAmount int64 `json:"requested_refund_amount" description:"申请退款金额(分)"`
ApprovedRefundAmount *int64 `json:"approved_refund_amount,omitempty" description:"审批实际退款金额(分)"`
RefundVoucherKey []string `json:"refund_voucher_key" description:"退款凭证对象存储file_key列表最多5个"`
RefundReason string `json:"refund_reason" description:"退款原因"`
Status int `json:"status" description:"状态 (1:待审批, 2:已通过, 3:已拒绝, 4:已退回, 5:原路退款处理中, 6:原路退款失败)"`
StatusName string `json:"status_name" description:"状态名称(中文)"`
Method string `json:"method" description:"退款方式 (original_route:原路退款, customer_account:客户收款信息退款, asset_wallet:退回资产钱包, agent_wallet:退回代理主钱包),空表示未接入方式的存量申请"`
MethodName string `json:"method_name" description:"退款方式中文名称"`
FrozenActualReceivedAmount int64 `json:"frozen_actual_received_amount" description:"系统派生并冻结的权威实收金额(分),作为可退金额上限"`
CustomerAccountInfo string `json:"customer_account_info" description:"客户收款信息自由文本快照,仅客户收款信息退款方式有值"`
ChannelRefundStatus int `json:"channel_refund_status" description:"渠道原路退款状态 (0:未发起, 1:处理中, 2:已成功, 3:已失败)0 表示未发起渠道退款或不适用该退款方式"`
ChannelRefundStatusName string `json:"channel_refund_status_name" description:"渠道原路退款状态中文名称"`
ChannelRefundNo string `json:"channel_refund_no" description:"渠道退款流水号,渠道明确成功或失败后回填"`
ChannelRefundRequestNo string `json:"channel_refund_request_no" description:"渠道退款请求号快照,用于幂等与对账"`
ChannelRefundAmount int64 `json:"channel_refund_amount" description:"提交渠道的退款金额快照(分)"`
ChannelRefundedAt string `json:"channel_refunded_at,omitempty" description:"渠道明确退款成功时间"`
// 结算标识:前两项是冻结的来源支付事实,第三项是财务补录的线下处理流水号,语义互不相同。
SourcePaymentNo string `json:"source_payment_no" description:"冻结的来源支付单号,取创建申请时的原成功支付记录;线下订单无线上支付记录时为空字符串"`
OriginalChannelTradeNo string `json:"original_channel_trade_no" description:"冻结的原支付渠道交易流水号,取创建申请时的原成功支付记录;线下订单无线上支付记录时为空字符串"`
OfflineSettlementNo string `json:"offline_settlement_no" description:"线下退款处理流水号或凭证编号,由授权账号补录或更正;与渠道退款流水号语义不同"`
OfflineSettledAt string `json:"offline_settled_at,omitempty" description:"线下退款处理流水号最近一次登记或更正时间"`
OfflineSettledBy uint `json:"offline_settled_by" description:"线下退款处理流水号最近一次登记或更正的操作账号ID0 表示未登记"`
FailureReason string `json:"failure_reason" description:"结构化失败分类稳定编码 (channel_rejected:渠道明确拒绝, credential_invalid:渠道凭证失效, insufficient_balance:渠道余额不足, timeout_unknown:超时或结果未知, approval_rejected:企业微信驳回或关闭, revoked_after_approved:企业微信通过后撤销, payment_fact_invalid:本地原支付事实不可用),空表示无失败"`
FailureReasonName string `json:"failure_reason_name" description:"失败分类中文名称"`
FailureMessage string `json:"failure_message" description:"失败安全摘要,供人工排查;不含渠道凭证等敏感内容"`
AnomalyFlag int `json:"anomaly_flag" description:"异常标记 (0:无异常, 1:有异常,需人工处理)"`
AnomalyReason string `json:"anomaly_reason" description:"异常原因说明,无异常时为空"`
LatestAttemptID uint `json:"latest_attempt_id" description:"最新审批尝试记录ID仅用于展示"`
LatestApprovalInstanceID uint `json:"latest_approval_instance_id" description:"最新通用审批实例ID仅用于展示"`
Attempts []RefundAttemptResponse `json:"attempts" description:"审批尝试记录,按提交顺序排列,历史材料不被覆盖;无尝试记录时为空数组"`
ProcessorID *uint `json:"processor_id,omitempty" description:"审批人ID"`
ProcessedAt string `json:"processed_at,omitempty" description:"审批时间"`
RejectReason string `json:"reject_reason,omitempty" description:"拒绝原因"`
Remark string `json:"remark,omitempty" description:"审批备注"`
CommissionDeducted bool `json:"commission_deducted" description:"佣金是否已回扣"`
AssetReset bool `json:"asset_reset" description:"退款后资产处理是否完成"`
SubmitterID uint `json:"submitter_id" description:"提交人账号ID"`
SubmitterName string `json:"submitter_name" description:"提交人账号名称"`
ApprovalInstanceID *uint `json:"approval_instance_id,omitempty" description:"通用审批实例ID"`
ApprovalProvider string `json:"approval_provider,omitempty" description:"审批渠道企业微信为wecom"`
ApprovalStatus *int `json:"approval_status,omitempty" description:"审批状态 (0:提交中, 1:审批中, 2:已通过, 3:已拒绝, 4:已撤销, 5:通过后撤销, 6:已删除, 7:提交失败, 8:提交结果未知)"`
ApprovalStatusName string `json:"approval_status_name,omitempty" description:"审批状态名称(中文)"`
Creator uint `json:"creator" description:"创建人ID"`
Updater uint `json:"updater" description:"更新人ID"`
CreatedAt string `json:"created_at" description:"创建时间"`
UpdatedAt string `json:"updated_at" description:"更新时间"`
}
// RefundListResponse 退款申请列表分页响应
@@ -135,6 +145,7 @@ type RefundAttemptResponse struct {
RefundAmount int64 `json:"refund_amount" description:"本次提交冻结的申请退款金额(分)"`
FrozenActualReceivedAmount int64 `json:"frozen_actual_received_amount" description:"本次提交冻结的权威实收金额(分)"`
RefundReason string `json:"refund_reason" description:"本次提交的退款原因"`
Remark string `json:"remark" description:"本次提交冻结的申请人备注快照,未填写时为空;与审批备注(详情响应中的 remark不是同一字段"`
CustomerAccountInfo string `json:"customer_account_info" description:"本次冻结的客户收款信息快照,非客户收款信息退款方式为空"`
CustomerVoucherKey []string `json:"customer_voucher_key" description:"客户收款凭证对象存储file_key列表仅返回对象键引用"`
ChannelRefundRequestNo string `json:"channel_refund_request_no" description:"本次提交使用的渠道退款请求号快照,用于幂等与对账"`
@@ -144,3 +155,44 @@ type RefundAttemptResponse struct {
ApprovalStatusName string `json:"approval_status_name" description:"通用审批实例状态中文名称"`
CreatedAt string `json:"created_at" description:"创建时间"`
}
// RefundOrderOptionsRequest 按来源订单查询可选退款方式请求。
type RefundOrderOptionsRequest struct {
OrderID uint `json:"order_id" query:"order_id" validate:"required,min=1" required:"true" minimum:"1" description:"来源订单ID"`
}
// RefundMethodOptionResponse 描述一种可选退款方式及其当前可用性。
type RefundMethodOptionResponse struct {
Method string `json:"method" description:"退款方式 (original_route:原路退款, customer_account:客户收款信息退款, asset_wallet:退回资产钱包, agent_wallet:退回代理主钱包)"`
MethodName string `json:"method_name" description:"退款方式中文名称"`
Available bool `json:"available" description:"该方式当前是否可用"`
Unavailable string `json:"unavailable_reason" description:"不可用原因;可用时为空字符串"`
}
// RefundCapabilityResponse 是原路退款能力校验结果投影。
type RefundCapabilityResponse struct {
Available bool `json:"available" description:"原路退款能力校验是否通过(凭证完整性、服务商类型与渠道可退时限)"`
Unavailable string `json:"unavailable_reason" description:"不通过原因;通过时为空字符串"`
}
// RefundOrderOptionsResponse 按来源订单查询可选退款方式响应。
type RefundOrderOptionsResponse struct {
OrderID uint `json:"order_id" description:"来源订单ID"`
OrderNo string `json:"order_no" description:"来源订单号"`
OrderPaymentType string `json:"order_payment_type" description:"来源订单支付方式 (wechat:微信, alipay:支付宝, wallet:钱包, offline:后台线下)"`
Methods []RefundMethodOptionResponse `json:"methods" description:"可选退款方式集合,含每种方式的可用性与不可用原因;判定事实缺失时为空数组"`
MerchantID *uint `json:"merchant_id,omitempty" description:"原收款商户ID无实际收款商户时为空"`
MerchantName string `json:"merchant_name" description:"原收款商户名称快照,无实际收款商户时为空字符串"`
OriginalChannelTradeNo string `json:"original_channel_trade_no" description:"原支付渠道交易流水号,无线上支付记录时为空字符串"`
RefundCapability RefundCapabilityResponse `json:"refund_capability" description:"原路退款能力校验结果"`
// UnavailableReason 在判定所需事实缺失(如无原成功支付记录或订单支付方式不支持退款)时说明原因,
// 使调用方得到不可用原因而不是请求失败。
UnavailableReason string `json:"unavailable_reason" description:"整体判定不可用时的原因,可用时为空字符串"`
}
// OfflineSettlementRequest 登记或更正线下退款处理流水号请求。
type OfflineSettlementRequest struct {
ID uint `json:"-" params:"id" path:"id" validate:"required" description:"退款申请ID"`
// OfflineSettlementNo 记录财务实际执行的线下退款处理流水号或凭证编号;重复提交即更正,历史值由审计留存。
OfflineSettlementNo string `json:"offline_settlement_no" validate:"required,max=128" required:"true" maxLength:"128" description:"线下退款处理流水号或凭证编号(必填,去除首尾空白后不得为空)"`
}

View File

@@ -117,8 +117,10 @@ type ShopResponse struct {
Status int `json:"status" description:"状态 (0:禁用, 1:启用)"`
StatusName string `json:"status_name" description:"状态名称(中文)"`
ClientLoginDisabled bool `json:"client_login_disabled" description:"是否禁止该店铺资产发起新的 C 端登录"`
CreatedAt string `json:"created_at" description:"创建时间"`
UpdatedAt string `json:"updated_at" description:"更新时间"`
// 直接下级代理数量为只读投影:未删除且上级店铺为该店铺的店铺数,无下级返回 0。
DownstreamAgentCount int64 `json:"downstream_agent_count" description:"直接下级代理数量(未删除且上级店铺标识等于该店铺的店铺数),无下级返回 0"`
CreatedAt string `json:"created_at" description:"创建时间"`
UpdatedAt string `json:"updated_at" description:"更新时间"`
}
// ShopPageResult 店铺分页响应

View File

@@ -32,6 +32,10 @@ type WeComBusinessFieldResponse struct {
Name string `json:"name" description:"字段中文名称"`
ValueType string `json:"value_type" description:"字段值类型 (string:字符串, integer:整数, money:两位小数的元金额字符串, file_list:对象存储文件引用列表)"`
Description string `json:"description" description:"字段取值说明"`
// RequiredMapping 为 true 表示该字段必须配置控件映射:场景映射校验在缺失映射时明确失败,
// 表单构建在快照缺值时明确失败并提示缺失控件MUST NOT 静默丢弃。
// 仅本变更新增的字段标记为 true既有未映射的可选控件保持既有静默跳过行为。
RequiredMapping bool `json:"required_mapping" description:"是否必须配置控件映射true 表示缺失映射或快照缺值时提交明确失败"`
}
// WeComBusinessFieldListResponse 企业微信审批场景可映射业务字段列表响应。

View File

@@ -58,8 +58,13 @@ type CommissionWithdrawalRequestAttempt struct {
InvoiceKeys datatypes.JSON `gorm:"column:invoice_keys;type:jsonb;not null;default:'[]';comment:本次申请级发票对象存储Key列表" json:"invoice_keys"`
SubmittedByAccountID uint `gorm:"column:submitted_by_account_id;type:bigint;not null;comment:本次实际提交账号ID" json:"submitted_by_account_id"`
ApprovalInstanceID *uint `gorm:"column:approval_instance_id;type:bigint;comment:本次尝试关联的通用审批实例ID" json:"approval_instance_id,omitempty"`
ReleasedAt *time.Time `gorm:"column:released_at;comment:本次冻结释放时间,空表示未结算" json:"released_at,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamptz;not null;autoCreateTime" json:"created_at"`
// 资料资格校验留痕:本次提交依据的有效资格版本与当次校验结果,随尝试冻结,历史尝试不被改写。
QualificationVersionID uint `gorm:"column:qualification_version_id;type:bigint;not null;default:0;comment:本次依据的有效提现资料资格版本ID0-资格不存在或历史尝试" json:"qualification_version_id"`
QualificationCheckedAt *time.Time `gorm:"column:qualification_checked_at;comment:本次资料资格校验时间" json:"qualification_checked_at,omitempty"`
QualificationPassed int `gorm:"column:qualification_passed;type:smallint;not null;default:0;comment:本次资料资格校验是否通过 0-未通过 1-通过" json:"qualification_passed"`
QualificationFailureReason string `gorm:"column:qualification_failure_reason;type:varchar(64);not null;default:'';comment:未通过时的稳定原因编码" json:"qualification_failure_reason"`
ReleasedAt *time.Time `gorm:"column:released_at;comment:本次冻结释放时间,空表示未结算" json:"released_at,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamptz;not null;autoCreateTime" json:"created_at"`
}
// TableName 指定提现审批尝试记录表名。

View File

@@ -12,9 +12,12 @@ import (
// Version 是配置版本而非乐观锁,更新事务内递增并参与频率去重键,旧版本通知保留原快照不被改写。
// 范围四维统一用 JSONB 字符串数组:空数组表示该维度未配置即全量,已配置而资产该维度无值时不命中。
type H5PopupConfiguration struct {
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
Title string `gorm:"column:title;type:varchar(100);not null" json:"title"`
Content string `gorm:"column:content;type:varchar(2000);not null" json:"content"`
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
Title string `gorm:"column:title;type:varchar(100);not null" json:"title"`
Content string `gorm:"column:content;type:varchar(2000);not null" json:"content"`
// PopupType 是运营弹窗类型(套餐政策推广/通用公告),必填单选。
// 它决定候选排序的第一顺位类别,类别顺序由查询侧的显式排序表达式表达,不依赖取值字典序。
PopupType string `gorm:"column:popup_type;type:varchar(20);not null;default:'announcement'" json:"popup_type"`
Pages StringJSONBArray `gorm:"column:pages;type:jsonb;not null;default:'[]'" json:"pages"`
ShopIDs StringJSONBArray `gorm:"column:shop_ids;type:jsonb;not null;default:'[]'" json:"shop_ids"`
DeviceTypes StringJSONBArray `gorm:"column:device_types;type:jsonb;not null;default:'[]'" json:"device_types"`

View File

@@ -8,26 +8,26 @@ import (
// OrderPackageInvalidateTask 订单套餐批量失效任务模型
type OrderPackageInvalidateTask struct {
ID uint `gorm:"column:id;primaryKey" json:"id"`
TaskNo string `gorm:"column:task_no;type:varchar(50);uniqueIndex;not null;comment:任务编号" json:"task_no"`
Status int `gorm:"column:status;type:int;not null;default:1;comment:任务状态 (1:待处理, 2:处理中, 3:已完成, 4:失败)" json:"status"`
TotalCount int `gorm:"column:total_count;type:int;not null;default:0;comment:总行数" json:"total_count"`
SuccessCount int `gorm:"column:success_count;type:int;not null;default:0;comment:成功数" json:"success_count"`
FailCount int `gorm:"column:fail_count;type:int;not null;default:0;comment:失败数" json:"fail_count"`
ID uint `gorm:"column:id;primaryKey" json:"id"`
TaskNo string `gorm:"column:task_no;type:varchar(50);uniqueIndex;not null;comment:任务编号" json:"task_no"`
Status int `gorm:"column:status;type:int;not null;default:1;comment:任务状态 (1:待处理, 2:处理中, 3:已完成, 4:失败)" json:"status"`
TotalCount int `gorm:"column:total_count;type:int;not null;default:0;comment:总行数" json:"total_count"`
SuccessCount int `gorm:"column:success_count;type:int;not null;default:0;comment:成功数" json:"success_count"`
FailCount int `gorm:"column:fail_count;type:int;not null;default:0;comment:失败数" json:"fail_count"`
FailedItems ImportResultItems `gorm:"column:failed_items;type:jsonb;not null;default:'[]';comment:失败记录详情(jsonb)" json:"failed_items"`
FileName string `gorm:"column:file_name;type:varchar(255);not null;default:'';comment:原始文件名" json:"file_name"`
StorageKey string `gorm:"column:storage_key;type:varchar(500);not null;default:'';comment:CSV 文件对象存储路径" json:"storage_key"`
VoucherKeys StringJSONBArray `gorm:"column:voucher_keys;type:jsonb;not null;default:'[]';comment:支付凭证对象存储Key列表最多5个" json:"voucher_keys"`
Remark string `gorm:"column:remark;type:text;not null;default:'';comment:运营备注(创建时填写,只读)" json:"remark"`
CreatorName string `gorm:"column:creator_name;type:varchar(100);not null;default:'';comment:操作人姓名快照" json:"creator_name"`
ErrorMessage string `gorm:"column:error_message;type:text;not null;default:'';comment:任务级错误信息" json:"error_message"`
StartedAt *time.Time `gorm:"column:started_at;comment:开始处理时间" json:"started_at"`
CompletedAt *time.Time `gorm:"column:completed_at;comment:完成时间" json:"completed_at"`
Creator uint `gorm:"column:creator;not null;default:0;comment:创建人ID" json:"creator"`
Updater uint `gorm:"column:updater;not null;default:0;comment:更新人ID" json:"updater"`
CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;index" json:"deleted_at,omitempty"`
FileName string `gorm:"column:file_name;type:varchar(255);not null;default:'';comment:原始文件名" json:"file_name"`
StorageKey string `gorm:"column:storage_key;type:varchar(500);not null;default:'';comment:CSV 文件对象存储路径" json:"storage_key"`
VoucherKeys StringJSONBArray `gorm:"column:voucher_keys;type:jsonb;not null;default:'[]';comment:支付凭证对象存储Key列表最多5个" json:"voucher_keys"`
Remark string `gorm:"column:remark;type:text;not null;default:'';comment:运营备注(创建时填写,只读)" json:"remark"`
CreatorName string `gorm:"column:creator_name;type:varchar(100);not null;default:'';comment:操作人姓名快照" json:"creator_name"`
ErrorMessage string `gorm:"column:error_message;type:text;not null;default:'';comment:任务级错误信息" json:"error_message"`
StartedAt *time.Time `gorm:"column:started_at;comment:开始处理时间" json:"started_at"`
CompletedAt *time.Time `gorm:"column:completed_at;comment:完成时间" json:"completed_at"`
Creator uint `gorm:"column:creator;not null;default:0;comment:创建人ID" json:"creator"`
Updater uint `gorm:"column:updater;not null;default:0;comment:更新人ID" json:"updater"`
CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;index" json:"deleted_at,omitempty"`
}
// TableName 指定表名

View File

@@ -10,11 +10,11 @@ import (
// 说明:记录微信用户使用过哪些设备号/IMEI一个设备号可以被多个微信用户使用过
type PersonalCustomerDevice struct {
gorm.Model
CustomerID uint `gorm:"column:customer_id;type:bigint;not null;comment:关联个人客户ID" json:"customer_id"`
VirtualNo string `gorm:"column:virtual_no;type:varchar(50);not null;comment:设备虚拟号/IMEI" json:"virtual_no"`
BindAt time.Time `gorm:"column:bind_at;type:timestamp;not null;comment:绑定时间" json:"bind_at"`
CustomerID uint `gorm:"column:customer_id;type:bigint;not null;comment:关联个人客户ID" json:"customer_id"`
VirtualNo string `gorm:"column:virtual_no;type:varchar(50);not null;comment:设备虚拟号/IMEI" json:"virtual_no"`
BindAt time.Time `gorm:"column:bind_at;type:timestamp;not null;comment:绑定时间" json:"bind_at"`
LastUsedAt *time.Time `gorm:"column:last_used_at;type:timestamp;comment:最后使用时间" json:"last_used_at"`
Status int `gorm:"column:status;type:int;not null;default:1;comment:状态 0=禁用 1=启用" json:"status"`
Status int `gorm:"column:status;type:int;not null;default:1;comment:状态 0=禁用 1=启用" json:"status"`
}
// TableName 指定表名

View File

@@ -10,12 +10,12 @@ import (
// 说明记录微信用户使用过哪些ICCID一个ICCID可以被多个微信用户使用过
type PersonalCustomerICCID struct {
gorm.Model
CustomerID uint `gorm:"column:customer_id;type:bigint;not null;comment:关联个人客户ID" json:"customer_id"`
ICCID string `gorm:"column:iccid;type:varchar(20);not null;comment:ICCID20位数字" json:"iccid"`
BindAt time.Time `gorm:"column:bind_at;type:timestamp;not null;comment:绑定时间" json:"bind_at"`
CustomerID uint `gorm:"column:customer_id;type:bigint;not null;comment:关联个人客户ID" json:"customer_id"`
ICCID string `gorm:"column:iccid;type:varchar(20);not null;comment:ICCID20位数字" json:"iccid"`
BindAt time.Time `gorm:"column:bind_at;type:timestamp;not null;comment:绑定时间" json:"bind_at"`
LastUsedAt *time.Time `gorm:"column:last_used_at;type:timestamp;comment:最后使用时间" json:"last_used_at"`
Status int `gorm:"column:status;type:int;not null;default:1;comment:状态 0=禁用 1=启用" json:"status"`
ICCID19 string `gorm:"column:iccid_19;type:varchar(19);comment:ICCID前19位用于19位运营商精确查询" json:"iccid_19,omitempty"`
Status int `gorm:"column:status;type:int;not null;default:1;comment:状态 0=禁用 1=启用" json:"status"`
ICCID19 string `gorm:"column:iccid_19;type:varchar(19);comment:ICCID前19位用于19位运营商精确查询" json:"iccid_19,omitempty"`
}
// TableName 指定表名

View File

@@ -10,11 +10,11 @@ import (
// 说明:一个微信用户可以绑定多个手机号
type PersonalCustomerPhone struct {
gorm.Model
CustomerID uint `gorm:"column:customer_id;type:bigint;not null;comment:关联个人客户ID" json:"customer_id"`
Phone string `gorm:"column:phone;type:varchar(20);not null;comment:手机号" json:"phone"`
IsPrimary bool `gorm:"column:is_primary;type:boolean;not null;default:false;comment:是否主手机号" json:"is_primary"`
CustomerID uint `gorm:"column:customer_id;type:bigint;not null;comment:关联个人客户ID" json:"customer_id"`
Phone string `gorm:"column:phone;type:varchar(20);not null;comment:手机号" json:"phone"`
IsPrimary bool `gorm:"column:is_primary;type:boolean;not null;default:false;comment:是否主手机号" json:"is_primary"`
VerifiedAt *time.Time `gorm:"column:verified_at;type:timestamp;comment:验证通过时间" json:"verified_at"`
Status int `gorm:"column:status;type:int;not null;default:1;comment:状态 0=禁用 1=启用" json:"status"`
Status int `gorm:"column:status;type:int;not null;default:1;comment:状态 0=禁用 1=启用" json:"status"`
}
// TableName 指定表名

View File

@@ -22,6 +22,9 @@ type PhoneAssetAssociation struct {
InvalidationMethod string `gorm:"column:invalidation_method;type:varchar(30);not null;default:'';comment:失效方式" json:"invalidation_method"`
InvalidationReason string `gorm:"column:invalidation_reason;type:varchar(500);not null;default:'';comment:失效原因" json:"invalidation_reason"`
Invalidator uint `gorm:"column:invalidator;type:bigint;not null;default:0;comment:失效操作人账号ID" json:"invalidator"`
// InvalidatorNameSnapshot 是解绑当时的后台账号名称快照,只读投影字段。
// 仅 status = 0 时写入有效关系为空MUST NOT 以创建人或更新时间填充账号改名后无法由账号ID反推名称
InvalidatorNameSnapshot string `gorm:"column:invalidator_name_snapshot;type:varchar(100);not null;default:'';comment:最近解绑人名称快照,仅已失效关系写入" json:"invalidator_name_snapshot"`
}
// TableName 指定手机号—资产关联表名。

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 指定表名

View File

@@ -48,6 +48,13 @@ type RefundRequest struct {
FrozenActualReceivedAmount int64 `gorm:"column:frozen_actual_received_amount;type:bigint;not null;default:0;comment:冻结的权威实收金额(分)" json:"frozen_actual_received_amount"`
CustomerAccountInfo string `gorm:"column:customer_account_info;type:text;not null;default:'';comment:客户收款信息自由文本快照" json:"customer_account_info"`
// 结算标识:来源支付事实在创建或重提时冻结,线下处理流水号由财务补录(写审计),二者语义不同。
SourcePaymentNo string `gorm:"column:source_payment_no;type:varchar(64);not null;default:'';comment:冻结的来源支付单号,线下订单为空" json:"source_payment_no"`
OriginalChannelTradeNo string `gorm:"column:original_channel_trade_no;type:varchar(100);not null;default:'';comment:冻结的原支付渠道交易流水号(列宽与 tb_payment.third_party_trade_no 一致),线下订单为空" json:"original_channel_trade_no"`
OfflineSettlementNo string `gorm:"column:offline_settlement_no;type:varchar(128);not null;default:'';comment:线下退款处理流水号或凭证编号,由授权账号补录或更正" json:"offline_settlement_no"`
OfflineSettledAt *time.Time `gorm:"column:offline_settled_at;comment:线下退款处理流水号最近登记或更正时间" json:"offline_settled_at,omitempty"`
OfflineSettledBy uint `gorm:"column:offline_settled_by;not null;default:0;comment:线下退款处理流水号最近登记或更正的操作账号ID0-未登记" json:"offline_settled_by"`
// 审批尝试引用,仅用于列表与详情展示
LatestAttemptID uint `gorm:"column:latest_attempt_id;type:bigint;not null;default:0;comment:最新审批尝试记录ID仅用于展示" json:"latest_attempt_id"`
LatestApprovalInstanceID uint `gorm:"column:latest_approval_instance_id;type:bigint;not null;default:0;comment:最新通用审批实例ID仅用于展示" json:"latest_approval_instance_id"`
@@ -81,20 +88,22 @@ func (RefundRequest) TableName() string {
// 每次提交或重提新增一条不可变记录,冻结当次方式、金额、冻结实收、原因、客户收款信息、
// 凭证与套餐使用快照;主键同时作为通用审批业务标识,使同一退款单每次提交持有独立审批实例。
type RefundRequestAttempt struct {
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
RefundID uint `gorm:"column:refund_id;not null;index" json:"refund_id"`
AttemptNo int `gorm:"column:attempt_no;type:int;not null" json:"attempt_no"`
Method string `gorm:"column:method;type:varchar(20);not null" json:"method"`
RefundAmount int64 `gorm:"column:refund_amount;type:bigint;not null" json:"refund_amount"`
FrozenActualReceivedAmount int64 `gorm:"column:frozen_actual_received_amount;type:bigint;not null" json:"frozen_actual_received_amount"`
RefundReason string `gorm:"column:refund_reason;type:text;not null;default:''" json:"refund_reason"`
CustomerAccountInfo string `gorm:"column:customer_account_info;type:text;not null;default:''" json:"customer_account_info"`
CustomerVoucherKeys StringJSONBArray `gorm:"column:customer_voucher_keys;type:jsonb;not null" json:"customer_voucher_keys"`
PackageUsageSnapshot datatypes.JSON `gorm:"column:package_usage_snapshot;type:jsonb;not null" json:"package_usage_snapshot"`
ChannelRefundRequestNo string `gorm:"column:channel_refund_request_no;type:varchar(64);not null;default:''" json:"channel_refund_request_no"`
SubmittedByAccountID uint `gorm:"column:submitted_by_account_id;not null" json:"submitted_by_account_id"`
ApprovalInstanceID *uint `gorm:"column:approval_instance_id" json:"approval_instance_id,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamptz;not null;autoCreateTime" json:"created_at"`
ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
RefundID uint `gorm:"column:refund_id;not null;index" json:"refund_id"`
AttemptNo int `gorm:"column:attempt_no;type:int;not null" json:"attempt_no"`
Method string `gorm:"column:method;type:varchar(20);not null" json:"method"`
RefundAmount int64 `gorm:"column:refund_amount;type:bigint;not null" json:"refund_amount"`
FrozenActualReceivedAmount int64 `gorm:"column:frozen_actual_received_amount;type:bigint;not null" json:"frozen_actual_received_amount"`
RefundReason string `gorm:"column:refund_reason;type:text;not null;default:''" json:"refund_reason"`
// Remark 是本次提交的申请人备注,逐次冻结;与退款主表 remark审批备注语义不同不得复用。
Remark string `gorm:"column:remark;type:text;not null;default:''" json:"remark"`
CustomerAccountInfo string `gorm:"column:customer_account_info;type:text;not null;default:''" json:"customer_account_info"`
CustomerVoucherKeys StringJSONBArray `gorm:"column:customer_voucher_keys;type:jsonb;not null" json:"customer_voucher_keys"`
PackageUsageSnapshot datatypes.JSON `gorm:"column:package_usage_snapshot;type:jsonb;not null" json:"package_usage_snapshot"`
ChannelRefundRequestNo string `gorm:"column:channel_refund_request_no;type:varchar(64);not null;default:''" json:"channel_refund_request_no"`
SubmittedByAccountID uint `gorm:"column:submitted_by_account_id;not null" json:"submitted_by_account_id"`
ApprovalInstanceID *uint `gorm:"column:approval_instance_id" json:"approval_instance_id,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamptz;not null;autoCreateTime" json:"created_at"`
}
// TableName 指定审批尝试记录表名。