207 lines
6.1 KiB
Go
207 lines
6.1 KiB
Go
package services
|
|
|
|
import (
|
|
"errors"
|
|
"lost-and-found/internal/models"
|
|
"lost-and-found/internal/repositories"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type LostItemService struct {
|
|
lostItemRepo *repositories.LostItemRepository
|
|
categoryRepo *repositories.CategoryRepository
|
|
auditLogRepo *repositories.AuditLogRepository
|
|
}
|
|
|
|
func NewLostItemService(db *gorm.DB) *LostItemService {
|
|
return &LostItemService{
|
|
lostItemRepo: repositories.NewLostItemRepository(db),
|
|
categoryRepo: repositories.NewCategoryRepository(db),
|
|
auditLogRepo: repositories.NewAuditLogRepository(db),
|
|
}
|
|
}
|
|
|
|
// CreateLostItemRequest represents create lost item data
|
|
type CreateLostItemRequest struct {
|
|
Name string `json:"name" binding:"required"`
|
|
CategoryID uint `json:"category_id" binding:"required"`
|
|
Color string `json:"color"`
|
|
Location string `json:"location"`
|
|
Description string `json:"description" binding:"required"`
|
|
DateLost time.Time `json:"date_lost" binding:"required"`
|
|
}
|
|
|
|
// UpdateLostItemRequest represents update lost item data
|
|
type UpdateLostItemRequest struct {
|
|
Name string `json:"name"`
|
|
CategoryID uint `json:"category_id"`
|
|
Color string `json:"color"`
|
|
Location string `json:"location"`
|
|
Description string `json:"description"`
|
|
DateLost time.Time `json:"date_lost"`
|
|
}
|
|
|
|
// GetAllLostItems gets all lost items
|
|
func (s *LostItemService) GetAllLostItems(page, limit int, status, category, search string, userID *uint) ([]models.LostItemResponse, int64, error) {
|
|
lostItems, total, err := s.lostItemRepo.FindAll(page, limit, status, category, search, userID)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
var responses []models.LostItemResponse
|
|
for _, lostItem := range lostItems {
|
|
responses = append(responses, lostItem.ToResponse())
|
|
}
|
|
|
|
return responses, total, nil
|
|
}
|
|
|
|
// GetLostItemByID gets lost item by ID
|
|
func (s *LostItemService) GetLostItemByID(id uint) (*models.LostItem, error) {
|
|
return s.lostItemRepo.FindByID(id)
|
|
}
|
|
|
|
// CreateLostItem creates a new lost item report
|
|
func (s *LostItemService) CreateLostItem(userID uint, req CreateLostItemRequest, ipAddress, userAgent string) (*models.LostItem, error) {
|
|
// Verify category exists
|
|
if _, err := s.categoryRepo.FindByID(req.CategoryID); err != nil {
|
|
return nil, errors.New("invalid category")
|
|
}
|
|
|
|
lostItem := &models.LostItem{
|
|
UserID: userID,
|
|
Name: req.Name,
|
|
CategoryID: req.CategoryID,
|
|
Color: req.Color,
|
|
Location: req.Location,
|
|
Description: req.Description,
|
|
DateLost: req.DateLost,
|
|
Status: models.LostItemStatusActive,
|
|
}
|
|
|
|
if err := s.lostItemRepo.Create(lostItem); err != nil {
|
|
return nil, errors.New("failed to create lost item report")
|
|
}
|
|
|
|
// Log audit
|
|
s.auditLogRepo.Log(&userID, models.ActionCreate, models.EntityLostItem, &lostItem.ID,
|
|
"Lost item report created: "+lostItem.Name, ipAddress, userAgent)
|
|
|
|
// Load with relations
|
|
return s.lostItemRepo.FindByID(lostItem.ID)
|
|
}
|
|
|
|
// UpdateLostItem updates a lost item report
|
|
func (s *LostItemService) UpdateLostItem(userID, lostItemID uint, req UpdateLostItemRequest, ipAddress, userAgent string) (*models.LostItem, error) {
|
|
lostItem, err := s.lostItemRepo.FindByID(lostItemID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Only owner can update
|
|
if lostItem.UserID != userID {
|
|
return nil, errors.New("unauthorized to update this lost item report")
|
|
}
|
|
|
|
// Only active reports can be updated
|
|
if !lostItem.IsActive() {
|
|
return nil, errors.New("cannot update non-active lost item report")
|
|
}
|
|
|
|
// Update fields
|
|
if req.Name != "" {
|
|
lostItem.Name = req.Name
|
|
}
|
|
if req.CategoryID != 0 {
|
|
// Verify category exists
|
|
if _, err := s.categoryRepo.FindByID(req.CategoryID); err != nil {
|
|
return nil, errors.New("invalid category")
|
|
}
|
|
lostItem.CategoryID = req.CategoryID
|
|
}
|
|
if req.Color != "" {
|
|
lostItem.Color = req.Color
|
|
}
|
|
if req.Location != "" {
|
|
lostItem.Location = req.Location
|
|
}
|
|
if req.Description != "" {
|
|
lostItem.Description = req.Description
|
|
}
|
|
if !req.DateLost.IsZero() {
|
|
lostItem.DateLost = req.DateLost
|
|
}
|
|
|
|
if err := s.lostItemRepo.Update(lostItem); err != nil {
|
|
return nil, errors.New("failed to update lost item report")
|
|
}
|
|
|
|
// Log audit
|
|
s.auditLogRepo.Log(&userID, models.ActionUpdate, models.EntityLostItem, &lostItemID,
|
|
"Lost item report updated: "+lostItem.Name, ipAddress, userAgent)
|
|
|
|
return lostItem, nil
|
|
}
|
|
|
|
// UpdateLostItemStatus updates lost item status
|
|
func (s *LostItemService) UpdateLostItemStatus(userID, lostItemID uint, status string, ipAddress, userAgent string) error {
|
|
lostItem, err := s.lostItemRepo.FindByID(lostItemID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Only owner can update
|
|
if lostItem.UserID != userID {
|
|
return errors.New("unauthorized to update this lost item report")
|
|
}
|
|
|
|
if err := s.lostItemRepo.UpdateStatus(lostItemID, status); err != nil {
|
|
return errors.New("failed to update lost item status")
|
|
}
|
|
|
|
// Log audit
|
|
s.auditLogRepo.Log(&userID, models.ActionUpdate, models.EntityLostItem, &lostItemID,
|
|
"Lost item status updated to: "+status, ipAddress, userAgent)
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeleteLostItem deletes a lost item report
|
|
func (s *LostItemService) DeleteLostItem(userID, lostItemID uint, ipAddress, userAgent string) error {
|
|
lostItem, err := s.lostItemRepo.FindByID(lostItemID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Only owner can delete
|
|
if lostItem.UserID != userID {
|
|
return errors.New("unauthorized to delete this lost item report")
|
|
}
|
|
|
|
if err := s.lostItemRepo.Delete(lostItemID); err != nil {
|
|
return errors.New("failed to delete lost item report")
|
|
}
|
|
|
|
// Log audit
|
|
s.auditLogRepo.Log(&userID, models.ActionDelete, models.EntityLostItem, &lostItemID,
|
|
"Lost item report deleted: "+lostItem.Name, ipAddress, userAgent)
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetLostItemsByUser gets lost items by user
|
|
func (s *LostItemService) GetLostItemsByUser(userID uint, page, limit int) ([]models.LostItemResponse, int64, error) {
|
|
lostItems, total, err := s.lostItemRepo.FindByUser(userID, page, limit)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
var responses []models.LostItemResponse
|
|
for _, lostItem := range lostItems {
|
|
responses = append(responses, lostItem.ToResponse())
|
|
}
|
|
|
|
return responses, total, nil
|
|
} |