Files
junhong_cmp_fiber/internal/model/package_silence.go
邹进 62ec94adec
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Failing after 38s
refactor: 出库时间更名为首次购买套餐时间,换货新资产不再按换货完成时间记录
- 字段 outbound_at → first_purchase_at,记录表 tb_asset_outbound_record → tb_asset_first_purchase_record,接口 /outbound-records → /first-purchase-records,筛选参数与导出列同步更名
- 换货后的新资产不因换货写入,在当前世代真正支付套餐订单时才记录;记录来源只保留 order / backfill,去掉换货单字段
- 迁移 000266 重命名列、表、索引与约束;同步 Spec、设计、任务与前端接口变更说明

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 16:47:02 +09:00

242 lines
22 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package model
import (
"time"
"gorm.io/datatypes"
"gorm.io/gorm"
)
// PackageSilenceExtensionPolicy 沉默期延期政策。
// 匹配优先级:指定套餐 > 套餐系列 > 全部套餐;同一优先级适用范围与生效时间段不得重叠。
type PackageSilenceExtensionPolicy struct {
ID uint `gorm:"column:id;primaryKey" json:"id"`
Name string `gorm:"column:name;type:varchar(100);not null;comment:政策名称" json:"name"`
ScopeType string `gorm:"column:scope_type;type:varchar(20);not null;comment:适用范围 all/series/package" json:"scope_type"`
ScopeIDs UintJSONBArray `gorm:"column:scope_ids;type:jsonb;not null;default:'[]';comment:系列或套餐ID列表" json:"scope_ids"`
UnitPrice int64 `gorm:"column:unit_price;type:bigint;not null;comment:单价(分/月)" json:"unit_price"`
FreeExtensionLimit int `gorm:"column:free_extension_limit;type:int;not null;default:1;comment:免费延期次数" json:"free_extension_limit"`
PaidMaxMonths int `gorm:"column:paid_max_months;type:int;not null;default:6;comment:付费延期累计最多月数" json:"paid_max_months"`
SingleMaxMonths *int `gorm:"column:single_max_months;type:int;comment:单次付费延期最多月数" json:"single_max_months,omitempty"`
ApprovalExemptTypes StringJSONBArray `gorm:"column:approval_exempt_types;type:jsonb;not null;default:'[]';comment:免审批场景" json:"approval_exempt_types"`
EffectiveFrom time.Time `gorm:"column:effective_from;not null;comment:生效时间" json:"effective_from"`
EffectiveTo *time.Time `gorm:"column:effective_to;comment:失效时间" json:"effective_to,omitempty"`
Status int `gorm:"column:status;type:smallint;not null;default:1;comment:状态 0-停用 1-启用" json:"status"`
Remark string `gorm:"column:remark;type:varchar(500);not null;default:'';comment:备注" json:"remark"`
Creator uint `gorm:"column:creator;not null;default:0" json:"creator"`
Updater uint `gorm:"column:updater;not null;default:0" 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:"-"`
}
// TableName 指定表名
func (PackageSilenceExtensionPolicy) TableName() string {
return "tb_package_silence_extension_policy"
}
// PackageSilenceRecord 套餐沉默期变更流水(只新增不修改)。
type PackageSilenceRecord struct {
ID uint `gorm:"column:id;primaryKey" json:"id"`
PackageUsageID uint `gorm:"column:package_usage_id;not null" json:"package_usage_id"`
EventType string `gorm:"column:event_type;type:varchar(30);not null" json:"event_type"`
TriggerSource string `gorm:"column:trigger_source;type:varchar(40);not null;default:''" json:"trigger_source"`
AssetType string `gorm:"column:asset_type;type:varchar(20);not null;default:''" json:"asset_type"`
AssetID uint `gorm:"column:asset_id;not null;default:0" json:"asset_id"`
BeforeStatus *string `gorm:"column:before_status;type:varchar(16)" json:"before_status,omitempty"`
AfterStatus *string `gorm:"column:after_status;type:varchar(16)" json:"after_status,omitempty"`
BeforeDeadlineAt *time.Time `gorm:"column:before_deadline_at" json:"before_deadline_at,omitempty"`
AfterDeadlineAt *time.Time `gorm:"column:after_deadline_at" json:"after_deadline_at,omitempty"`
PeriodDays *int `gorm:"column:period_days" json:"period_days,omitempty"`
DefaultDaysSnapshot *int `gorm:"column:default_days_snapshot" json:"default_days_snapshot,omitempty"`
IsAdjusted bool `gorm:"column:is_adjusted;not null;default:false" json:"is_adjusted"`
ChangeDays int `gorm:"column:change_days;not null;default:0" json:"change_days"`
OperatorID uint `gorm:"column:operator_id;not null;default:0" json:"operator_id"`
OperatorType string `gorm:"column:operator_type;type:varchar(20);not null;default:''" json:"operator_type"`
Reason string `gorm:"column:reason;type:varchar(500);not null;default:''" json:"reason"`
ApprovalInstanceID *uint `gorm:"column:approval_instance_id" json:"approval_instance_id,omitempty"`
BatchID *uint `gorm:"column:batch_id" json:"batch_id,omitempty"`
ExtensionID *uint `gorm:"column:extension_id" json:"extension_id,omitempty"`
ExchangeOrderID *uint `gorm:"column:exchange_order_id" json:"exchange_order_id,omitempty"`
ExchangeNo string `gorm:"column:exchange_no;type:varchar(64);not null;default:''" json:"exchange_no"`
RealnameAt *time.Time `gorm:"column:realname_at" json:"realname_at,omitempty"`
Extra datatypes.JSON `gorm:"column:extra;type:jsonb;not null;default:'{}'" json:"extra"`
CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP" json:"created_at"`
}
// TableName 指定表名
func (PackageSilenceRecord) TableName() string {
return "tb_package_silence_record"
}
// PackageSilenceExtensionBatch 沉默期申请批次:每次延期或购买时调整都建一个批次,企微审批实例关联批次。
type PackageSilenceExtensionBatch struct {
ID uint `gorm:"column:id;primaryKey" json:"id"`
BatchNo string `gorm:"column:batch_no;type:varchar(40);not null" json:"batch_no"`
Path string `gorm:"column:path;type:varchar(20);not null" json:"path"`
ExtensionType string `gorm:"column:extension_type;type:varchar(30);not null" json:"extension_type"`
ApprovalRequired bool `gorm:"column:approval_required;not null;default:false" json:"approval_required"`
Reason string `gorm:"column:reason;type:varchar(1000);not null;default:''" json:"reason"`
EvidenceRefs StringJSONBArray `gorm:"column:evidence_refs;type:jsonb;not null;default:'[]'" json:"evidence_refs"`
Basis string `gorm:"column:basis;type:varchar(1000);not null;default:''" json:"basis"`
ImportFileKey string `gorm:"column:import_file_key;type:varchar(500);not null;default:''" json:"import_file_key"`
PolicyID *uint `gorm:"column:policy_id" json:"policy_id,omitempty"`
PolicyNameSnapshot string `gorm:"column:policy_name_snapshot;type:varchar(100);not null;default:''" json:"policy_name_snapshot"`
UnitPriceSnapshot int64 `gorm:"column:unit_price_snapshot;not null;default:0" json:"unit_price_snapshot"`
ApprovalExemptTypesSnapshot StringJSONBArray `gorm:"column:approval_exempt_types_snapshot;type:jsonb;not null;default:'[]'" json:"approval_exempt_types_snapshot"`
FreeExtensionLimitSnapshot int `gorm:"column:free_extension_limit_snapshot;not null;default:1" json:"free_extension_limit_snapshot"`
PaidMaxMonthsSnapshot int `gorm:"column:paid_max_months_snapshot;not null;default:0" json:"paid_max_months_snapshot"`
SingleMaxMonthsSnapshot *int `gorm:"column:single_max_months_snapshot" json:"single_max_months_snapshot,omitempty"`
AdjustPackageUsageID *uint `gorm:"column:adjust_package_usage_id" json:"adjust_package_usage_id,omitempty"`
AdjustDefaultDays *int `gorm:"column:adjust_default_days" json:"adjust_default_days,omitempty"`
AdjustRequestedDays *int `gorm:"column:adjust_requested_days" json:"adjust_requested_days,omitempty"`
Amount int64 `gorm:"column:amount;not null;default:0" json:"amount"`
OfflinePaymentMethodID *uint `gorm:"column:offline_payment_method_id" json:"offline_payment_method_id,omitempty"`
OfflinePaymentMethodCode *string `gorm:"column:offline_payment_method_code;type:varchar(64)" json:"offline_payment_method_code,omitempty"`
OfflinePaymentMethodName *string `gorm:"column:offline_payment_method_name;type:varchar(100)" json:"offline_payment_method_name,omitempty"`
OfflineTradeNo *string `gorm:"column:offline_trade_no;type:varchar(128)" json:"offline_trade_no,omitempty"`
OfflinePaidAmount *int64 `gorm:"column:offline_paid_amount" json:"offline_paid_amount,omitempty"`
OfflinePaidAt *time.Time `gorm:"column:offline_paid_at" json:"offline_paid_at,omitempty"`
PaymentVoucherKeys StringJSONBArray `gorm:"column:payment_voucher_keys;type:jsonb;not null;default:'[]'" json:"payment_voucher_keys"`
RequestedBy uint `gorm:"column:requested_by;not null;default:0" json:"requested_by"`
RequestedByType string `gorm:"column:requested_by_type;type:varchar(20);not null;default:''" json:"requested_by_type"`
RequestedAt time.Time `gorm:"column:requested_at;not null" json:"requested_at"`
ApprovalInstanceID *uint `gorm:"column:approval_instance_id" json:"approval_instance_id,omitempty"`
ApprovalStatus string `gorm:"column:approval_status;type:varchar(20);not null;default:''" json:"approval_status"`
ApprovalFinishedAt *time.Time `gorm:"column:approval_finished_at" json:"approval_finished_at,omitempty"`
Status string `gorm:"column:status;type:varchar(30);not null" json:"status"`
RequestedCount int `gorm:"column:requested_count;not null;default:0" json:"requested_count"`
SucceededCount int `gorm:"column:succeeded_count;not null;default:0" json:"succeeded_count"`
FailedCount int `gorm:"column:failed_count;not null;default:0" json:"failed_count"`
CompletedAt *time.Time `gorm:"column:completed_at" json:"completed_at,omitempty"`
ShopIDTag uint `gorm:"column:shop_id_tag;not null;default:0" json:"shop_id_tag"`
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"`
}
// TableName 指定表名
func (PackageSilenceExtensionBatch) TableName() string {
return "tb_package_silence_extension_batch"
}
// PackageSilenceExtension 沉默期延期明细(延期事实),以明细状态条件更新保证幂等。
type PackageSilenceExtension struct {
ID uint `gorm:"column:id;primaryKey" json:"id"`
BatchID uint `gorm:"column:batch_id;not null" json:"batch_id"`
RowNo int `gorm:"column:row_no;not null;default:1" json:"row_no"`
PackageUsageID uint `gorm:"column:package_usage_id;not null" json:"package_usage_id"`
PackageID uint `gorm:"column:package_id;not null;default:0" json:"package_id"`
PackageNameSnapshot string `gorm:"column:package_name_snapshot;type:varchar(255);not null;default:''" json:"package_name_snapshot"`
AssetType string `gorm:"column:asset_type;type:varchar(20);not null;default:''" json:"asset_type"`
AssetID uint `gorm:"column:asset_id;not null;default:0" json:"asset_id"`
AssetIdentifierSnapshot string `gorm:"column:asset_identifier_snapshot;type:varchar(100);not null;default:''" json:"asset_identifier_snapshot"`
ExtensionType string `gorm:"column:extension_type;type:varchar(30);not null" json:"extension_type"`
InputDays int `gorm:"column:input_days;not null" json:"input_days"`
Months int `gorm:"column:months;not null" json:"months"`
ExtensionDays int `gorm:"column:extension_days;not null" json:"extension_days"`
UnitPriceSnapshot int64 `gorm:"column:unit_price_snapshot;not null;default:0" json:"unit_price_snapshot"`
Amount int64 `gorm:"column:amount;not null;default:0" json:"amount"`
ExtensionOrderID *uint `gorm:"column:extension_order_id" json:"extension_order_id,omitempty"`
BeforeDeadlineAt *time.Time `gorm:"column:before_deadline_at" json:"before_deadline_at,omitempty"`
AfterDeadlineAt *time.Time `gorm:"column:after_deadline_at" json:"after_deadline_at,omitempty"`
Status string `gorm:"column:status;type:varchar(20);not null" json:"status"`
FailureCode string `gorm:"column:failure_code;type:varchar(64);not null;default:''" json:"failure_code"`
FailureSummary string `gorm:"column:failure_summary;type:varchar(500);not null;default:''" json:"failure_summary"`
ExecutedAt *time.Time `gorm:"column:executed_at" json:"executed_at,omitempty"`
HandledBy uint `gorm:"column:handled_by;not null;default:0" json:"handled_by"`
HandledAt *time.Time `gorm:"column:handled_at" json:"handled_at,omitempty"`
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"`
}
// TableName 指定表名
func (PackageSilenceExtension) TableName() string {
return "tb_package_silence_extension"
}
// PackageSilenceExtensionOrder 沉默期延期订单(交易记录),在线支付复用 tb_payment(order_type = silence_extension)。
type PackageSilenceExtensionOrder struct {
ID uint `gorm:"column:id;primaryKey" json:"id"`
OrderNo string `gorm:"column:order_no;type:varchar(40);not null" json:"order_no"`
BatchID uint `gorm:"column:batch_id;not null" json:"batch_id"`
PackageUsageID uint `gorm:"column:package_usage_id;not null" json:"package_usage_id"`
PackageID uint `gorm:"column:package_id;not null" json:"package_id"`
PackageNameSnapshot string `gorm:"column:package_name_snapshot;type:varchar(255);not null;default:''" json:"package_name_snapshot"`
AssetType string `gorm:"column:asset_type;type:varchar(20);not null" json:"asset_type"`
AssetID uint `gorm:"column:asset_id;not null" json:"asset_id"`
AssetIdentifierSnapshot string `gorm:"column:asset_identifier_snapshot;type:varchar(100);not null;default:''" json:"asset_identifier_snapshot"`
ShopID uint `gorm:"column:shop_id;not null;default:0" json:"shop_id"`
CustomerID *uint `gorm:"column:customer_id" json:"customer_id,omitempty"`
Source string `gorm:"column:source;type:varchar(20);not null" json:"source"`
CreatedBy *uint `gorm:"column:created_by" json:"created_by,omitempty"`
EvidenceRefs StringJSONBArray `gorm:"column:evidence_refs;type:jsonb;not null;default:'[]'" json:"evidence_refs"`
InputDays int `gorm:"column:input_days;not null" json:"input_days"`
Months int `gorm:"column:months;not null" json:"months"`
ExtensionDays int `gorm:"column:extension_days;not null" json:"extension_days"`
PolicyID *uint `gorm:"column:policy_id" json:"policy_id,omitempty"`
PolicyNameSnapshot string `gorm:"column:policy_name_snapshot;type:varchar(100);not null;default:''" json:"policy_name_snapshot"`
UnitPrice int64 `gorm:"column:unit_price;not null" json:"unit_price"`
ApprovalExemptTypesSnapshot StringJSONBArray `gorm:"column:approval_exempt_types_snapshot;type:jsonb;not null;default:'[]'" json:"approval_exempt_types_snapshot"`
FreeExtensionLimitSnapshot int `gorm:"column:free_extension_limit_snapshot;not null;default:1" json:"free_extension_limit_snapshot"`
PaidMaxMonthsSnapshot int `gorm:"column:paid_max_months_snapshot;not null;default:0" json:"paid_max_months_snapshot"`
SingleMaxMonthsSnapshot *int `gorm:"column:single_max_months_snapshot" json:"single_max_months_snapshot,omitempty"`
Amount int64 `gorm:"column:amount;not null" json:"amount"`
BeforeDeadlineAt time.Time `gorm:"column:before_deadline_at;not null" json:"before_deadline_at"`
ExpectedDeadlineAt time.Time `gorm:"column:expected_deadline_at;not null" json:"expected_deadline_at"`
Status string `gorm:"column:status;type:varchar(20);not null" json:"status"`
PaymentMethod string `gorm:"column:payment_method;type:varchar(20);not null" json:"payment_method"`
OfflinePaymentMethodID *uint `gorm:"column:offline_payment_method_id" json:"offline_payment_method_id,omitempty"`
OfflinePaymentMethodCode *string `gorm:"column:offline_payment_method_code;type:varchar(64)" json:"offline_payment_method_code,omitempty"`
OfflinePaymentMethodName *string `gorm:"column:offline_payment_method_name;type:varchar(100)" json:"offline_payment_method_name,omitempty"`
OfflineTradeNo *string `gorm:"column:offline_trade_no;type:varchar(128)" json:"offline_trade_no,omitempty"`
PaymentVoucherKeys StringJSONBArray `gorm:"column:payment_voucher_keys;type:jsonb;not null;default:'[]'" json:"payment_voucher_keys"`
ApprovalRequired bool `gorm:"column:approval_required;not null;default:false" json:"approval_required"`
ApprovalInstanceID *uint `gorm:"column:approval_instance_id" json:"approval_instance_id,omitempty"`
PaidPaymentID *uint `gorm:"column:paid_payment_id" json:"paid_payment_id,omitempty"`
PaidAmount *int64 `gorm:"column:paid_amount" json:"paid_amount,omitempty"`
PaidAt *time.Time `gorm:"column:paid_at" json:"paid_at,omitempty"`
ExpireAt *time.Time `gorm:"column:expire_at" json:"expire_at,omitempty"`
ExtensionID *uint `gorm:"column:extension_id" json:"extension_id,omitempty"`
CompletedAt *time.Time `gorm:"column:completed_at" json:"completed_at,omitempty"`
ClosedAt *time.Time `gorm:"column:closed_at" json:"closed_at,omitempty"`
CloseReason string `gorm:"column:close_reason;type:varchar(200);not null;default:''" json:"close_reason"`
ExceptionCode string `gorm:"column:exception_code;type:varchar(64);not null;default:''" json:"exception_code"`
ExceptionSummary string `gorm:"column:exception_summary;type:varchar(500);not null;default:''" json:"exception_summary"`
RefundNo *string `gorm:"column:refund_no;type:varchar(64)" json:"refund_no,omitempty"`
RefundAmount *int64 `gorm:"column:refund_amount" json:"refund_amount,omitempty"`
RefundedAt *time.Time `gorm:"column:refunded_at" json:"refunded_at,omitempty"`
RefundReason *string `gorm:"column:refund_reason;type:varchar(500)" json:"refund_reason,omitempty"`
RequestID *string `gorm:"column:request_id;type:varchar(64)" json:"request_id,omitempty"`
ShopIDTag uint `gorm:"column:shop_id_tag;not null;default:0" json:"shop_id_tag"`
EnterpriseIDTag *uint `gorm:"column:enterprise_id_tag" json:"enterprise_id_tag,omitempty"`
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"`
}
// TableName 指定表名
func (PackageSilenceExtensionOrder) TableName() string {
return "tb_package_silence_extension_order"
}
// AssetFirstPurchaseRecord 资产首次购买套餐记录:每个世代一条,只新增与填写结束信息。
type AssetFirstPurchaseRecord struct {
ID uint `gorm:"column:id;primaryKey" json:"id"`
AssetType string `gorm:"column:asset_type;type:varchar(20);not null" json:"asset_type"`
AssetID uint `gorm:"column:asset_id;not null" json:"asset_id"`
AssetIdentifierSnapshot string `gorm:"column:asset_identifier_snapshot;type:varchar(100);not null;default:''" json:"asset_identifier_snapshot"`
Generation int `gorm:"column:generation;not null" json:"generation"`
FirstPurchaseAt time.Time `gorm:"column:first_purchase_at;not null" json:"first_purchase_at"`
Source string `gorm:"column:source;type:varchar(20);not null" json:"source"`
OrderID *uint `gorm:"column:order_id" json:"order_id,omitempty"`
OrderNo string `gorm:"column:order_no;type:varchar(40);not null;default:''" json:"order_no"`
ShopID *uint `gorm:"column:shop_id" json:"shop_id,omitempty"`
EndedAt *time.Time `gorm:"column:ended_at" json:"ended_at,omitempty"`
EndReason string `gorm:"column:end_reason;type:varchar(40);not null;default:''" json:"end_reason"`
CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP" json:"created_at"`
}
// TableName 指定表名
func (AssetFirstPurchaseRecord) TableName() string {
return "tb_asset_first_purchase_record"
}