// Package approval 定义业务用例依赖的渠道无关审批接缝。 package approval import ( "context" stderrors "errors" "time" "gorm.io/gorm" ) // 审批恢复适配器方法见文件末尾。 // PrepareRequest 是业务写入前执行审批渠道可用性检查的请求。 type PrepareRequest struct { BusinessType string SubmitterAccountID uint CorrelationID string } // Preparation 是渠道可用性检查返回的短期、不透明准备凭据。 type Preparation struct { provider string businessType string submitterAccountID uint correlationID string expiresAt time.Time issuer *CreationService providerContext ProviderPreparation } // CreateRequest 是业务事务内创建通用审批实例的请求。 type CreateRequest struct { Preparation Preparation BusinessType string BusinessID uint SubmitterAccountID uint SubmitterSnapshot []byte RequestSnapshot []byte CorrelationID string } // Reference 是业务表保存的通用审批实例引用。 type Reference struct { InstanceID uint Status int } // Port 是退款、线下充值等业务用例唯一依赖的审批创建接缝。 // Prepare 必须在业务事务前确认 Adapter、场景和发起身份可用;CreateInTx 必须复核准备凭据并使用调用方事务写入审批事实。 type Port interface { Prepare(ctx context.Context, request PrepareRequest) (Preparation, error) CreateInTx(ctx context.Context, tx *gorm.DB, request CreateRequest) (Reference, error) } // ProviderPreparation 是渠道 Adapter 在事务前完成场景和发起身份检查后返回的内部准备结果。 // ChannelContext 只能包含后续写入渠道专属表所需的安全快照,不得包含密钥或访问令牌。 type ProviderPreparation struct { Provider string ChannelContext []byte } // ProviderPort 定义具体审批渠道对通用创建用例提供的防腐接缝。 type ProviderPort interface { Prepare(ctx context.Context, request PrepareRequest) (ProviderPreparation, error) CreateContextInTx(ctx context.Context, tx *gorm.DB, preparation ProviderPreparation, instanceID uint) error } // SubmissionRequestedEvent 是渠道提交 Worker 接收的通用申请事件。 type SubmissionRequestedEvent struct { EventID string `json:"event_id"` InstanceID uint `json:"instance_id"` BusinessType string `json:"business_type"` BusinessID uint `json:"business_id"` SubmitterAccountID uint `json:"submitter_account_id"` Provider string `json:"provider"` CorrelationID string `json:"correlation_id"` OccurredAt time.Time `json:"occurred_at"` } // SubmissionEventWriter 在调用方业务事务中追加渠道提交 Outbox。 type SubmissionEventWriter interface { Append(ctx context.Context, tx *gorm.DB, event SubmissionRequestedEvent) error } type RecoveryPort interface { EnqueueSubmittedSync(ctx context.Context, tx *gorm.DB, instanceID uint) error EnqueueUnknownConfirm(ctx context.Context, tx *gorm.DB, instanceID uint) error RecoverSubmissionEvent(ctx context.Context, tx *gorm.DB, instanceID uint) (bool, error) } // RecoveryAdapter 将恢复动作委托给基础设施实现。 type RecoveryAdapter struct { SyncFunc func(context.Context, *gorm.DB, uint) error ConfirmFunc func(context.Context, *gorm.DB, uint) error RecoverFunc func(context.Context, *gorm.DB, uint) (bool, error) } func (a RecoveryAdapter) SyncSubmitted(ctx context.Context, tx *gorm.DB, id uint) error { if a.SyncFunc == nil { return stderrors.New("审批原实例同步接缝未配置") } return a.SyncFunc(ctx, tx, id) } func (a RecoveryAdapter) ConfirmUnknown(ctx context.Context, tx *gorm.DB, id uint) error { if a.ConfirmFunc == nil { return stderrors.New("审批结果确认接缝未配置") } return a.ConfirmFunc(ctx, tx, id) } func (a RecoveryAdapter) RecoverSubmissionEvent(ctx context.Context, tx *gorm.DB, id uint) (bool, error) { if a.RecoverFunc == nil { return false, stderrors.New("审批提交事件恢复接缝未配置") } return a.RecoverFunc(ctx, tx, id) }