Files
backend/internal/service/verification_service.go

177 lines
5.8 KiB
Go
Raw Normal View History

package service
import (
"context"
"fmt"
"time"
apperrors "carrot_bbs/internal/errors"
"carrot_bbs/internal/model"
"carrot_bbs/internal/repository"
)
type VerificationService interface {
SubmitVerification(ctx context.Context, userID string, identity model.UserIdentity, realName, studentID, employeeID, department, proofMaterials string) (*model.VerificationRecord, error)
GetVerificationStatus(ctx context.Context, userID string) (*VerificationStatusResponse, error)
GetVerificationRecords(ctx context.Context, userID string, page, pageSize int) ([]*model.VerificationRecord, int64, error)
}
type VerificationStatusResponse struct {
UserID string `json:"user_id"`
Identity string `json:"identity"`
VerificationStatus string `json:"verification_status"`
HasPendingRequest bool `json:"has_pending_request"`
LatestRecord *model.VerificationRecord `json:"latest_record,omitempty"`
}
type verificationServiceImpl struct {
verificationRepo repository.VerificationRepository
userRepo repository.UserRepository
}
func NewVerificationService(
verificationRepo repository.VerificationRepository,
userRepo repository.UserRepository,
) VerificationService {
return &verificationServiceImpl{
verificationRepo: verificationRepo,
userRepo: userRepo,
}
}
func (s *verificationServiceImpl) SubmitVerification(ctx context.Context, userID string, identity model.UserIdentity, realName, studentID, employeeID, department, proofMaterials string) (*model.VerificationRecord, error) {
user, err := s.userRepo.GetByID(userID)
if err != nil {
return nil, apperrors.ErrUserNotFound
}
if user.VerificationStatus == model.VerificationStatusApproved {
return nil, apperrors.ErrAlreadyVerified
}
existing, err := s.verificationRepo.GetPendingByUserID(userID)
if err == nil && existing != nil {
return nil, apperrors.ErrVerificationPending
}
record := &model.VerificationRecord{
UserID: userID,
Identity: identity,
Status: model.VerificationStatusPending,
RealName: realName,
StudentID: studentID,
EmployeeID: employeeID,
Department: department,
ProofMaterials: proofMaterials,
}
if err := s.verificationRepo.Create(record); err != nil {
return nil, fmt.Errorf("创建认证记录失败: %w", err)
}
user.VerificationStatus = model.VerificationStatusPending
user.Identity = identity
if err := s.userRepo.Update(user); err != nil {
return nil, fmt.Errorf("更新用户状态失败: %w", err)
}
return record, nil
}
func (s *verificationServiceImpl) GetVerificationStatus(ctx context.Context, userID string) (*VerificationStatusResponse, error) {
user, err := s.userRepo.GetByID(userID)
if err != nil {
return nil, apperrors.ErrUserNotFound
}
response := &VerificationStatusResponse{
UserID: userID,
Identity: string(user.Identity),
VerificationStatus: string(user.VerificationStatus),
HasPendingRequest: false,
}
latestRecord, err := s.verificationRepo.GetLatestByUserID(userID)
if err == nil && latestRecord != nil {
response.LatestRecord = latestRecord
response.HasPendingRequest = latestRecord.Status == model.VerificationStatusPending
}
return response, nil
}
func (s *verificationServiceImpl) GetVerificationRecords(ctx context.Context, userID string, page, pageSize int) ([]*model.VerificationRecord, int64, error) {
return s.verificationRepo.GetRecordsByUserID(userID, page, pageSize)
}
type AdminVerificationService interface {
ListVerifications(ctx context.Context, page, pageSize int, status, keyword string) ([]*model.VerificationRecord, int64, error)
GetVerificationDetail(ctx context.Context, id string) (*model.VerificationRecord, error)
ReviewVerification(ctx context.Context, reviewerID string, recordID string, approve bool, rejectReason string) (*model.VerificationRecord, error)
}
type adminVerificationServiceImpl struct {
verificationRepo repository.VerificationRepository
userRepo repository.UserRepository
}
func NewAdminVerificationService(
verificationRepo repository.VerificationRepository,
userRepo repository.UserRepository,
) AdminVerificationService {
return &adminVerificationServiceImpl{
verificationRepo: verificationRepo,
userRepo: userRepo,
}
}
func (s *adminVerificationServiceImpl) ListVerifications(ctx context.Context, page, pageSize int, status, keyword string) ([]*model.VerificationRecord, int64, error) {
return s.verificationRepo.List(page, pageSize, status, keyword)
}
func (s *adminVerificationServiceImpl) GetVerificationDetail(ctx context.Context, id string) (*model.VerificationRecord, error) {
return s.verificationRepo.GetByID(id)
}
func (s *adminVerificationServiceImpl) ReviewVerification(ctx context.Context, reviewerID string, recordID string, approve bool, rejectReason string) (*model.VerificationRecord, error) {
record, err := s.verificationRepo.GetByID(recordID)
if err != nil {
return nil, apperrors.ErrVerificationNotFound
}
if record.Status != model.VerificationStatusPending {
return nil, apperrors.ErrVerificationAlreadyHandled
}
if approve {
record.Status = model.VerificationStatusApproved
} else {
record.Status = model.VerificationStatusRejected
record.RejectReason = rejectReason
}
now := time.Now()
record.ReviewedBy = &reviewerID
record.ReviewedAt = &now
if err := s.verificationRepo.Update(record); err != nil {
return nil, fmt.Errorf("更新认证记录失败: %w", err)
}
user, err := s.userRepo.GetByID(record.UserID)
if err != nil {
return record, nil
}
if approve {
user.VerificationStatus = model.VerificationStatusApproved
user.Identity = record.Identity
} else {
user.VerificationStatus = model.VerificationStatusRejected
}
_ = s.userRepo.Update(user)
return record, nil
}