收口审计治理与套餐任务进展

Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展
Confidence: medium
Scope-risk: broad
Directive: 后续修改需保持审计事件与业务事务边界一致
Tested: git diff --cached --check
Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
2026-08-05 14:30:54 +08:00
parent b3499adfca
commit 5e552d99bc
178 changed files with 16797 additions and 5674 deletions

View File

@@ -18,9 +18,23 @@ import (
// CreateCommand 描述已通过订单与金额校验的退款审批申请。
type CreateCommand struct {
Refund *model.RefundRequest
Order *model.Order
SubmitterAccountID uint
}
// ApplicationAudit 描述退款申请、审批、订单和提交人的同事务审计事实。
type ApplicationAudit struct {
Refund *model.RefundRequest
Order *model.Order
Approval *model.ApprovalInstance
Submitter *model.Account
}
// AuditWriter 接收退款申请事务内审计事实。
type AuditWriter interface {
WriteRefundApplication(ctx context.Context, tx *gorm.DB, audit ApplicationAudit) error
}
// CreateResult 返回原子保存后的退款申请和初始审批状态。
type CreateResult struct {
Refund *model.RefundRequest
@@ -32,19 +46,20 @@ type CreateResult struct {
type CreationService struct {
db *gorm.DB
approval approvalapp.Port
audit AuditWriter
}
// NewCreationService 创建退款审批申请用例。
func NewCreationService(db *gorm.DB, approval approvalapp.Port) *CreationService {
return &CreationService{db: db, approval: approval}
func NewCreationService(db *gorm.DB, approval approvalapp.Port, audit AuditWriter) *CreationService {
return &CreationService{db: db, approval: approval, audit: audit}
}
// Execute 在业务写入前校验审批渠道,并在同一事务冻结退款事实和审批事实。
func (s *CreationService) Execute(ctx context.Context, command CreateCommand) (*CreateResult, error) {
if s == nil || s.db == nil || s.approval == nil {
if s == nil || s.db == nil || s.approval == nil || s.audit == nil {
return nil, errors.New(errors.CodeServiceUnavailable, "退款审批能力未配置")
}
if command.Refund == nil || command.Refund.OrderID == 0 || command.SubmitterAccountID == 0 ||
if command.Refund == nil || command.Order == nil || command.Refund.OrderID == 0 || command.Order.ID != command.Refund.OrderID || command.SubmitterAccountID == 0 ||
command.Refund.Creator != command.SubmitterAccountID || strings.TrimSpace(command.Refund.RefundNo) == "" {
return nil, errors.New(errors.CodeInvalidParam)
}
@@ -100,7 +115,13 @@ func (s *CreationService) Execute(ctx context.Context, command CreateCommand) (*
}
command.Refund.ApprovalInstanceID = &reference.InstanceID
approvalStatus = reference.Status
return nil
var approval model.ApprovalInstance
if err := tx.WithContext(ctx).First(&approval, reference.InstanceID).Error; err != nil {
return errors.Wrap(errors.CodeDatabaseError, err, "查询退款审批审计快照失败")
}
return s.audit.WriteRefundApplication(ctx, tx, ApplicationAudit{
Refund: command.Refund, Order: command.Order, Approval: &approval, Submitter: account,
})
})
if err != nil {
return nil, err