Files
junhong_cmp_fiber/internal/infrastructure/audit/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

82 lines
3.4 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 audit
import (
"context"
"strconv"
"gorm.io/gorm"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/pkg/auditcontext"
"github.com/break/junhong_cmp_fiber/pkg/constants"
)
// SilenceAuditInput 是沉默期相关审计事实。
type SilenceAuditInput struct {
ActionCode string
Summary string
Usage *model.PackageUsage
BeforeData map[string]any
AfterData map[string]any
Metadata map[string]any
}
// AppendSilenceUsage 在调用方事务内追加一条套餐记录级沉默期审计。
// 请求上下文没有操作者时(Worker、定时任务、回调)按系统任务记录。
func (w *Writer) AppendSilenceUsage(ctx context.Context, tx *gorm.DB, input SilenceAuditInput) error {
if w == nil || input.Usage == nil || input.Usage.ID == 0 {
return nil
}
resource := PackageUsageResource(input.Usage, constants.AuditResourceRelationPrimary,
constants.AuditResourceRolePackageUsageTarget, input.BeforeData, input.AfterData)
return w.Append(ctx, tx, silenceAppendInput(ctx, input.ActionCode, input.Summary, input.Metadata, []ResourceInput{resource}))
}
// AppendSilenceResource 追加一条主资源为非套餐记录(套餐、政策、配置、首次购买套餐记录)的沉默期审计。
func (w *Writer) AppendSilenceResource(ctx context.Context, tx *gorm.DB, actionCode, summary string, resource ResourceInput, metadata map[string]any) error {
if w == nil {
return nil
}
resource.Relation = constants.AuditResourceRelationPrimary
if resource.Role == "" {
resource.Role = constants.AuditResourceRoleConfig
}
return w.Append(ctx, tx, silenceAppendInput(ctx, actionCode, summary, metadata, []ResourceInput{resource}))
}
// SilencePolicyResource 构造延期政策审计资源。
func SilencePolicyResource(policy *model.PackageSilenceExtensionPolicy, beforeData, afterData map[string]any) ResourceInput {
id := strconv.FormatUint(uint64(policy.ID), 10)
return ResourceInput{
Type: AuditResourcePackageSilencePolicy, ID: &id, Key: id, DisplayName: policy.Name,
IdentitySnapshot: map[string]any{"id": policy.ID, "name": policy.Name, "scope_type": policy.ScopeType, "status": policy.Status},
BeforeData: beforeData, AfterData: afterData,
}
}
// AssetFirstPurchaseResource 构造首次购买套餐记录审计资源。
func AssetFirstPurchaseResource(record *model.AssetFirstPurchaseRecord, afterData map[string]any) ResourceInput {
id := strconv.FormatUint(uint64(record.ID), 10)
return ResourceInput{
Type: AuditResourceAssetFirstPurchaseRecord, ID: &id, Key: id, DisplayName: record.AssetIdentifierSnapshot,
Role: constants.AuditResourceRoleConfig,
IdentitySnapshot: map[string]any{
"id": record.ID, "asset_type": record.AssetType, "asset_id": record.AssetID,
"generation": record.Generation, "source": record.Source,
},
AfterData: afterData,
}
}
func silenceAppendInput(ctx context.Context, actionCode, summary string, metadata map[string]any, resources []ResourceInput) AppendInput {
input := AppendInput{
ActionCode: actionCode, Summary: summary, ScopeType: constants.AuditScopePlatform,
Result: constants.AuditResultSuccess, Metadata: metadata, Resources: resources,
}
if auditcontext.From(ctx).ActorID == "" {
input.Actor = ActorInput{Kind: constants.AuditActorSystemTask, ID: "package_silence", Name: "沉默期规则"}
input.Source = constants.AuditSourceWorker
}
return input
}