93 lines
2.7 KiB
Go
93 lines
2.7 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"go.uber.org/zap"
|
|
"gorm.io/gorm"
|
|
|
|
"veza-backend-api/internal/models"
|
|
)
|
|
|
|
// AnnouncementService handles global announcements (v0.803 ADM1-04)
|
|
type AnnouncementService struct {
|
|
db *gorm.DB
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewAnnouncementService creates a new AnnouncementService
|
|
func NewAnnouncementService(db *gorm.DB, logger *zap.Logger) *AnnouncementService {
|
|
return &AnnouncementService{db: db, logger: logger}
|
|
}
|
|
|
|
// CreateAnnouncementRequest is the request for creating an announcement
|
|
type CreateAnnouncementRequest struct {
|
|
Title string `json:"title" binding:"required"`
|
|
Content string `json:"content" binding:"required"`
|
|
Type string `json:"type"` // info, warning, error
|
|
IsActive bool `json:"is_active"`
|
|
StartsAt *time.Time `json:"starts_at"`
|
|
EndsAt *time.Time `json:"ends_at"`
|
|
}
|
|
|
|
// List returns all announcements (admin)
|
|
func (s *AnnouncementService) List(ctx context.Context) ([]models.Announcement, error) {
|
|
var list []models.Announcement
|
|
if err := s.db.WithContext(ctx).Order("created_at DESC").Find(&list).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to list announcements: %w", err)
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
// Create creates an announcement
|
|
func (s *AnnouncementService) Create(ctx context.Context, createdBy uuid.UUID, req CreateAnnouncementRequest) (*models.Announcement, error) {
|
|
a := &models.Announcement{
|
|
Title: req.Title,
|
|
Content: req.Content,
|
|
Type: req.Type,
|
|
IsActive: req.IsActive,
|
|
CreatedBy: &createdBy,
|
|
}
|
|
if req.Type == "" {
|
|
a.Type = "info"
|
|
}
|
|
if req.StartsAt != nil {
|
|
a.StartsAt = *req.StartsAt
|
|
} else {
|
|
a.StartsAt = time.Now()
|
|
}
|
|
a.EndsAt = req.EndsAt
|
|
if err := s.db.WithContext(ctx).Create(a).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to create announcement: %w", err)
|
|
}
|
|
return a, nil
|
|
}
|
|
|
|
// Delete deletes an announcement
|
|
func (s *AnnouncementService) Delete(ctx context.Context, id uuid.UUID) error {
|
|
result := s.db.WithContext(ctx).Delete(&models.Announcement{}, "id = ?", id)
|
|
if result.Error != nil {
|
|
return fmt.Errorf("failed to delete announcement: %w", result.Error)
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return fmt.Errorf("announcement not found")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetActive returns currently active announcements (public)
|
|
func (s *AnnouncementService) GetActive(ctx context.Context) ([]models.Announcement, error) {
|
|
now := time.Now()
|
|
var list []models.Announcement
|
|
if err := s.db.WithContext(ctx).
|
|
Where("is_active = ? AND starts_at <= ?", true, now).
|
|
Where("ends_at IS NULL OR ends_at > ?", now).
|
|
Order("starts_at DESC").
|
|
Find(&list).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get active announcements: %w", err)
|
|
}
|
|
return list, nil
|
|
}
|