package approval import ( "context" "strings" "gorm.io/gorm" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" ) // ConfirmSubmissionFailed 在业务消费事务内锁定审批实例并确认其仍为“提交失败”,返回可对外展示的失败原因。 // 实例已不是提交失败(例如被恢复重放)时 ok 为 false,业务消费者应不改变业务单。 // 原因只返回固定白名单文案,禁止透传企微原文或内部错误。 func ConfirmSubmissionFailed(ctx context.Context, tx *gorm.DB, instanceID uint) (string, bool, error) { var row struct { Status int `gorm:"column:status"` LastError string `gorm:"column:last_error"` } result := tx.WithContext(ctx).Raw( `SELECT ai.status, COALESCE(wc.last_error, '') AS last_error FROM tb_approval_instance ai LEFT JOIN tb_wecom_approval_context wc ON wc.approval_instance_id = ai.id WHERE ai.id = ? FOR UPDATE OF ai`, instanceID).Scan(&row) if result.Error != nil { return "", false, errors.Wrap(errors.CodeDatabaseError, result.Error, "锁定提交失败审批实例失败") } if result.RowsAffected == 0 { return "", false, errors.New(errors.CodeNotFound, "审批实例不存在") } if row.Status != constants.ApprovalStatusSubmissionFailed { return "", false, nil } return SubmissionFailureReason(row.LastError), true, nil } // SubmissionFailureReason 把企微提交失败原文转换为稳定白名单文案。 func SubmissionFailureReason(lastError string) string { if strings.TrimSpace(lastError) == "" { return constants.ApprovalSubmissionFailedStatusName } return constants.ApprovalSubmissionFailedReason }