2025-11-23 22:49:46 +07:00

159 lines
4.2 KiB
Go

// internal/repositories/item_repo.go
package repositories
import (
"errors"
"lost-and-found/internal/models"
"time"
"gorm.io/gorm"
)
type ItemRepository struct {
db *gorm.DB
}
func NewItemRepository(db *gorm.DB) *ItemRepository {
return &ItemRepository{db: db}
}
// Create creates a new item
func (r *ItemRepository) Create(item *models.Item) error {
return r.db.Create(item).Error
}
// FindByID finds item by ID
func (r *ItemRepository) FindByID(id uint) (*models.Item, error) {
var item models.Item
err := r.db.Preload("Category").Preload("Reporter").Preload("Reporter.Role").First(&item, id).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("item not found")
}
return nil, err
}
return &item, nil
}
// FindAll returns all items with filters
func (r *ItemRepository) FindAll(page, limit int, status, category, search string) ([]models.Item, int64, error) {
var items []models.Item
var total int64
query := r.db.Model(&models.Item{})
// Apply filters
if status != "" {
query = query.Where("status = ?", status)
}
if category != "" {
query = query.Joins("JOIN categories ON categories.id = items.category_id").Where("categories.slug = ?", category)
}
if search != "" {
query = query.Where("name ILIKE ? OR location ILIKE ?", "%"+search+"%", "%"+search+"%")
}
// Count total
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
// Get paginated results
offset := (page - 1) * limit
err := query.Preload("Category").Preload("Reporter").Preload("Reporter.Role").
Order("date_found DESC").
Offset(offset).Limit(limit).Find(&items).Error
if err != nil {
return nil, 0, err
}
return items, total, nil
}
// Update updates item data
func (r *ItemRepository) Update(item *models.Item) error {
return r.db.Save(item).Error
}
// UpdateStatus updates item status
func (r *ItemRepository) UpdateStatus(id uint, status string) error {
return r.db.Model(&models.Item{}).Where("id = ?", id).Update("status", status).Error
}
// Delete soft deletes an item
func (r *ItemRepository) Delete(id uint) error {
return r.db.Delete(&models.Item{}, id).Error
}
// FindExpired finds expired items
func (r *ItemRepository) FindExpired() ([]models.Item, error) {
var items []models.Item
now := time.Now()
err := r.db.Where("expires_at <= ? AND status = ?", now, models.ItemStatusUnclaimed).
Preload("Category").Find(&items).Error
return items, err
}
// ArchiveItem moves item to archive
func (r *ItemRepository) ArchiveItem(item *models.Item, reason string, claimedBy *uint) error {
return r.db.Transaction(func(tx *gorm.DB) error {
// Create archive record
archive := models.CreateFromItem(item, reason, claimedBy)
if err := tx.Create(archive).Error; err != nil {
return err
}
// Update item status
if err := tx.Model(item).Updates(map[string]interface{}{
"status": models.ItemStatusExpired,
}).Error; err != nil {
return err
}
return nil
})
}
// CountByStatus counts items by status
func (r *ItemRepository) CountByStatus(status string) (int64, error) {
var count int64
err := r.db.Model(&models.Item{}).Where("status = ?", status).Count(&count).Error
return count, err
}
// FindByReporter finds items by reporter ID
func (r *ItemRepository) FindByReporter(reporterID uint, page, limit int) ([]models.Item, int64, error) {
var items []models.Item
var total int64
query := r.db.Model(&models.Item{}).Where("reporter_id = ?", reporterID)
// Count total
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
// Get paginated results
offset := (page - 1) * limit
err := query.Preload("Category").Order("date_found DESC").
Offset(offset).Limit(limit).Find(&items).Error
if err != nil {
return nil, 0, err
}
return items, total, nil
}
// SearchForMatching searches items for matching with lost items
func (r *ItemRepository) SearchForMatching(categoryID uint, name, color string) ([]models.Item, error) {
var items []models.Item
query := r.db.Where("status = ? AND category_id = ?", models.ItemStatusUnclaimed, categoryID)
if name != "" {
query = query.Where("name ILIKE ?", "%"+name+"%")
}
err := query.Preload("Category").Order("date_found DESC").Limit(10).Find(&items).Error
return items, err
}