2025-11-17 12:17:44 +07:00

128 lines
4.1 KiB
Go

package models
import (
"time"
"gorm.io/gorm"
)
// MatchResult represents auto-matching result between lost item and found item
type MatchResult struct {
ID uint `gorm:"primaryKey" json:"id"`
LostItemID uint `gorm:"not null" json:"lost_item_id"`
LostItem LostItem `gorm:"foreignKey:LostItemID" json:"lost_item,omitempty"`
ItemID uint `gorm:"not null" json:"item_id"`
Item Item `gorm:"foreignKey:ItemID" json:"item,omitempty"`
SimilarityScore float64 `gorm:"type:decimal(5,2)" json:"similarity_score"` // Percentage match (0-100)
MatchedFields string `gorm:"type:text" json:"matched_fields"` // JSON of matched fields
MatchedAt time.Time `gorm:"not null" json:"matched_at"`
IsNotified bool `gorm:"default:false" json:"is_notified"` // Was user notified?
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
// TableName specifies the table name for MatchResult model
func (MatchResult) TableName() string {
return "match_results"
}
// BeforeCreate hook
func (mr *MatchResult) BeforeCreate(tx *gorm.DB) error {
if mr.MatchedAt.IsZero() {
mr.MatchedAt = time.Now()
}
return nil
}
// IsHighMatch checks if similarity score is high (>= 70%)
func (mr *MatchResult) IsHighMatch() bool {
return mr.SimilarityScore >= 70.0
}
// IsMediumMatch checks if similarity score is medium (50-69%)
func (mr *MatchResult) IsMediumMatch() bool {
return mr.SimilarityScore >= 50.0 && mr.SimilarityScore < 70.0
}
// IsLowMatch checks if similarity score is low (< 50%)
func (mr *MatchResult) IsLowMatch() bool {
return mr.SimilarityScore < 50.0
}
// GetMatchLevel returns the match level as string
func (mr *MatchResult) GetMatchLevel() string {
if mr.IsHighMatch() {
return "high"
} else if mr.IsMediumMatch() {
return "medium"
}
return "low"
}
// MatchResultResponse represents match result data for API responses
type MatchResultResponse struct {
ID uint `json:"id"`
LostItemID uint `json:"lost_item_id"`
LostItemName string `json:"lost_item_name"`
ItemID uint `json:"item_id"`
ItemName string `json:"item_name"`
ItemPhotoURL string `json:"item_photo_url"`
ItemLocation string `json:"item_location"`
ItemDateFound time.Time `json:"item_date_found"`
ItemStatus string `json:"item_status"`
SimilarityScore float64 `json:"similarity_score"`
MatchLevel string `json:"match_level"`
MatchedFields string `json:"matched_fields"`
MatchedAt time.Time `json:"matched_at"`
IsNotified bool `json:"is_notified"`
}
// ToResponse converts MatchResult to MatchResultResponse
func (mr *MatchResult) ToResponse() MatchResultResponse {
lostItemName := ""
if mr.LostItem.ID != 0 {
lostItemName = mr.LostItem.Name
}
itemName := ""
itemPhotoURL := ""
itemLocation := ""
itemDateFound := time.Time{}
itemStatus := ""
if mr.Item.ID != 0 {
itemName = mr.Item.Name
itemPhotoURL = mr.Item.PhotoURL
itemLocation = mr.Item.Location
itemDateFound = mr.Item.DateFound
itemStatus = mr.Item.Status
}
return MatchResultResponse{
ID: mr.ID,
LostItemID: mr.LostItemID,
LostItemName: lostItemName,
ItemID: mr.ItemID,
ItemName: itemName,
ItemPhotoURL: itemPhotoURL,
ItemLocation: itemLocation,
ItemDateFound: itemDateFound,
ItemStatus: itemStatus,
SimilarityScore: mr.SimilarityScore,
MatchLevel: mr.GetMatchLevel(),
MatchedFields: mr.MatchedFields,
MatchedAt: mr.MatchedAt,
IsNotified: mr.IsNotified,
}
}
// ItemMatchResponse represents simplified item data for matching display
type ItemMatchResponse struct {
ID uint `json:"id"`
Name string `json:"name"`
PhotoURL string `json:"photo_url"`
Location string `json:"location"`
DateFound time.Time `json:"date_found"`
Status string `json:"status"`
Similarity float64 `json:"similarity"`
}