turash/bugulma/backend/internal/service/verification_service.go

191 lines
5.6 KiB
Go

package service
import (
"context"
"fmt"
"time"
"bugulma/backend/internal/domain"
"github.com/google/uuid"
)
type VerificationService struct {
trustService *TrustService
orgService *OrganizationService
}
func NewVerificationService(trustService *TrustService, orgService *OrganizationService) *VerificationService {
return &VerificationService{
trustService: trustService,
orgService: orgService,
}
}
type VerificationQueueFilters struct {
Status *domain.VerificationStatus
DataType *string
OrganizationID *string
}
// GetVerificationQueue retrieves organizations pending verification
func (s *VerificationService) GetVerificationQueue(ctx context.Context, filters VerificationQueueFilters) ([]*domain.VerifiedData, error) {
// Get all pending verifications
verifiedDataList, err := s.trustService.GetPendingVerifications(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get pending verifications: %w", err)
}
// Apply filters
var filtered []*domain.VerifiedData
for _, vd := range verifiedDataList {
if filters.Status != nil && vd.Status != *filters.Status {
continue
}
if filters.DataType != nil && vd.DataType != *filters.DataType {
continue
}
if filters.OrganizationID != nil && vd.OrganizationID != *filters.OrganizationID {
continue
}
filtered = append(filtered, vd)
}
return filtered, nil
}
// VerifyOrganization verifies an organization
func (s *VerificationService) VerifyOrganization(ctx context.Context, orgID string, verifiedBy string, notes string) error {
// Create verified data entry for organization
now := time.Now()
verifiedData := &domain.VerifiedData{
ID: uuid.New().String(),
OrganizationID: orgID,
DataType: "organization",
DataID: orgID,
Status: domain.VerificationVerified,
VerifiedBy: verifiedBy,
VerifiedAt: &now,
Notes: notes,
}
if err := s.trustService.VerifyData(ctx, verifiedData.ID, verifiedBy, notes); err != nil {
// If verified data doesn't exist, create it
if err := s.trustService.SubmitForVerification(ctx, verifiedData); err != nil {
return fmt.Errorf("failed to submit for verification: %w", err)
}
// Now verify it
if err := s.trustService.VerifyData(ctx, verifiedData.ID, verifiedBy, notes); err != nil {
return fmt.Errorf("failed to verify: %w", err)
}
}
// Update organization verified status
org, err := s.orgService.GetByID(ctx, orgID)
if err != nil {
return fmt.Errorf("failed to get organization: %w", err)
}
org.Verified = true
if err := s.orgService.Update(ctx, org); err != nil {
return fmt.Errorf("failed to update organization: %w", err)
}
return nil
}
// RejectVerification rejects an organization verification
func (s *VerificationService) RejectVerification(ctx context.Context, orgID string, reason string, notes string) error {
// Get existing verified data for this organization
orgVerifications, err := s.trustService.GetVerifiedDataByOrganization(ctx, orgID)
if err != nil {
return fmt.Errorf("failed to get verifications: %w", err)
}
var verifiedData *domain.VerifiedData
for _, vd := range orgVerifications {
if vd.DataType == "organization" && vd.DataID == orgID {
verifiedData = vd
break
}
}
if verifiedData == nil {
// Create new verified data entry
verifiedData = &domain.VerifiedData{
ID: uuid.New().String(),
OrganizationID: orgID,
DataType: "organization",
DataID: orgID,
Status: domain.VerificationRejected,
Notes: fmt.Sprintf("Reason: %s. Notes: %s", reason, notes),
}
if err := s.trustService.SubmitForVerification(ctx, verifiedData); err != nil {
return fmt.Errorf("failed to create verification entry: %w", err)
}
} else {
// Update existing
verifiedData.Status = domain.VerificationRejected
verifiedData.Notes = fmt.Sprintf("Reason: %s. Notes: %s", reason, notes)
if err := s.trustService.UpdateVerifiedData(ctx, verifiedData); err != nil {
return fmt.Errorf("failed to update verification: %w", err)
}
}
return nil
}
// BulkVerify verifies multiple organizations
func (s *VerificationService) BulkVerify(ctx context.Context, orgIDs []string, verifiedBy string) error {
for _, orgID := range orgIDs {
if err := s.VerifyOrganization(ctx, orgID, verifiedBy, "Bulk verification"); err != nil {
return fmt.Errorf("failed to verify organization %s: %w", orgID, err)
}
}
return nil
}
// GetVerificationStats retrieves verification statistics
func (s *VerificationService) GetVerificationStats(ctx context.Context) (map[string]interface{}, error) {
// Get all verifications
allVerifications, err := s.trustService.GetAllVerifications(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get verifications: %w", err)
}
stats := map[string]interface{}{
"total": len(allVerifications),
"pending": 0,
"verified": 0,
"rejected": 0,
"unverified": 0,
"average_time_days": 0,
}
var totalDays int64
var verifiedCount int
for _, vd := range allVerifications {
switch vd.Status {
case domain.VerificationPending:
stats["pending"] = stats["pending"].(int) + 1
case domain.VerificationVerified:
stats["verified"] = stats["verified"].(int) + 1
if vd.VerifiedAt != nil {
// Calculate days from verification time (simplified - would need creation time from elsewhere)
verifiedCount++
}
case domain.VerificationRejected:
stats["rejected"] = stats["rejected"].(int) + 1
case domain.VerificationUnverified:
stats["unverified"] = stats["unverified"].(int) + 1
}
}
if verifiedCount > 0 {
stats["average_time_days"] = float64(totalDays) / float64(verifiedCount)
}
return stats, nil
}