153 lines
4.7 KiB
Go
153 lines
4.7 KiB
Go
package services
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"lost-and-found/internal/models"
|
|
"lost-and-found/internal/repositories"
|
|
"lost-and-found/internal/utils"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type VerificationService struct {
|
|
verificationRepo *repositories.ClaimVerificationRepository
|
|
claimRepo *repositories.ClaimRepository
|
|
itemRepo *repositories.ItemRepository
|
|
}
|
|
|
|
func NewVerificationService(db *gorm.DB) *VerificationService {
|
|
return &VerificationService{
|
|
verificationRepo: repositories.NewClaimVerificationRepository(db),
|
|
claimRepo: repositories.NewClaimRepository(db),
|
|
itemRepo: repositories.NewItemRepository(db),
|
|
}
|
|
}
|
|
|
|
// VerificationResult represents the verification result
|
|
type VerificationResult struct {
|
|
SimilarityScore float64 `json:"similarity_score"`
|
|
MatchLevel string `json:"match_level"`
|
|
MatchedKeywords []string `json:"matched_keywords"`
|
|
Details map[string]string `json:"details"`
|
|
Recommendation string `json:"recommendation"`
|
|
}
|
|
|
|
// VerifyClaimDescription verifies claim description against item description
|
|
func (s *VerificationService) VerifyClaimDescription(claimID uint) (*VerificationResult, error) {
|
|
claim, err := s.claimRepo.FindByID(claimID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
item, err := s.itemRepo.FindByID(claim.ItemID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Calculate similarity between claim description and item description
|
|
similarity := utils.CalculateStringSimilarity(claim.Description, item.Description)
|
|
similarityPercent := similarity * 100
|
|
|
|
// Extract matched keywords
|
|
claimKeywords := utils.ExtractKeywords(claim.Description)
|
|
itemKeywords := utils.ExtractKeywords(item.Description)
|
|
matchedKeywords := utils.FindMatchedKeywords(claimKeywords, itemKeywords)
|
|
|
|
// Determine match level
|
|
matchLevel := "low"
|
|
recommendation := "REJECT - Deskripsi tidak cocok"
|
|
|
|
if similarityPercent >= 70.0 {
|
|
matchLevel = "high"
|
|
recommendation = "APPROVE - Deskripsi sangat cocok"
|
|
} else if similarityPercent >= 50.0 {
|
|
matchLevel = "medium"
|
|
recommendation = "REVIEW - Perlu verifikasi lebih lanjut"
|
|
}
|
|
|
|
// Create or update verification record
|
|
verification, _ := s.verificationRepo.FindByClaimID(claimID)
|
|
if verification == nil {
|
|
verification = &models.ClaimVerification{
|
|
ClaimID: claimID,
|
|
SimilarityScore: similarityPercent,
|
|
MatchedKeywords: stringSliceToJSON(matchedKeywords),
|
|
IsAutoMatched: false,
|
|
}
|
|
s.verificationRepo.Create(verification)
|
|
} else {
|
|
verification.SimilarityScore = similarityPercent
|
|
verification.MatchedKeywords = stringSliceToJSON(matchedKeywords)
|
|
s.verificationRepo.Update(verification)
|
|
}
|
|
|
|
return &VerificationResult{
|
|
SimilarityScore: similarityPercent,
|
|
MatchLevel: matchLevel,
|
|
MatchedKeywords: matchedKeywords,
|
|
Details: map[string]string{
|
|
"claim_description": claim.Description,
|
|
"item_description": item.Description,
|
|
"matched_count": string(len(matchedKeywords)),
|
|
},
|
|
Recommendation: recommendation,
|
|
}, nil
|
|
}
|
|
|
|
// GetVerificationByClaimID gets verification data for a claim
|
|
func (s *VerificationService) GetVerificationByClaimID(claimID uint) (*models.ClaimVerification, error) {
|
|
verification, err := s.verificationRepo.FindByClaimID(claimID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if verification == nil {
|
|
return nil, errors.New("verification not found")
|
|
}
|
|
return verification, nil
|
|
}
|
|
|
|
// GetHighMatchVerifications gets all high match verifications
|
|
func (s *VerificationService) GetHighMatchVerifications() ([]models.ClaimVerificationResponse, error) {
|
|
verifications, err := s.verificationRepo.FindHighMatches()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var responses []models.ClaimVerificationResponse
|
|
for _, v := range verifications {
|
|
responses = append(responses, v.ToResponse())
|
|
}
|
|
|
|
return responses, nil
|
|
}
|
|
|
|
// CompareDescriptions provides detailed comparison between two descriptions
|
|
func (s *VerificationService) CompareDescriptions(desc1, desc2 string) map[string]interface{} {
|
|
similarity := utils.CalculateStringSimilarity(desc1, desc2)
|
|
|
|
keywords1 := utils.ExtractKeywords(desc1)
|
|
keywords2 := utils.ExtractKeywords(desc2)
|
|
matchedKeywords := utils.FindMatchedKeywords(keywords1, keywords2)
|
|
|
|
return map[string]interface{}{
|
|
"similarity_score": similarity * 100,
|
|
"description_1": desc1,
|
|
"description_2": desc2,
|
|
"keywords_1": keywords1,
|
|
"keywords_2": keywords2,
|
|
"matched_keywords": matchedKeywords,
|
|
"total_keywords_1": len(keywords1),
|
|
"total_keywords_2": len(keywords2),
|
|
"matched_count": len(matchedKeywords),
|
|
}
|
|
}
|
|
|
|
// Helper function to convert string slice to JSON
|
|
func stringSliceToJSON(slice []string) string {
|
|
if len(slice) == 0 {
|
|
return "[]"
|
|
}
|
|
data, _ := json.Marshal(slice)
|
|
return string(data)
|
|
} |