149 lines
3.6 KiB
Go
149 lines
3.6 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/google/uuid"
|
|
|
|
"veza-backend-api/internal/database"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// NotificationService handles notification operations
|
|
type NotificationService struct {
|
|
db *database.Database
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// Notification represents a notification
|
|
type Notification struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
|
Type string `json:"type" db:"type"`
|
|
Title string `json:"title" db:"title"`
|
|
Content string `json:"content" db:"content"`
|
|
Link string `json:"link" db:"link"`
|
|
Read bool `json:"read" db:"read"`
|
|
CreatedAt string `json:"created_at" db:"created_at"`
|
|
}
|
|
|
|
// NewNotificationService creates a new notification service
|
|
func NewNotificationService(db *database.Database, logger *zap.Logger) *NotificationService {
|
|
return &NotificationService{
|
|
db: db,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// CreateNotification creates a new notification
|
|
func (ns *NotificationService) CreateNotification(userID uuid.UUID, notificationType, title, content, link string) error {
|
|
ctx := context.Background()
|
|
|
|
_, err := ns.db.ExecContext(ctx, `
|
|
INSERT INTO notifications (user_id, type, title, content, link)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
`, userID, notificationType, title, content, link)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create notification: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetNotifications retrieves notifications for a user
|
|
func (ns *NotificationService) GetNotifications(userID uuid.UUID, unreadOnly bool) ([]Notification, error) {
|
|
ctx := context.Background()
|
|
|
|
query := `
|
|
SELECT id, user_id, type, title, content, link, read, created_at
|
|
FROM notifications
|
|
WHERE user_id = $1
|
|
`
|
|
args := []interface{}{userID}
|
|
|
|
if unreadOnly {
|
|
query += " AND read = FALSE"
|
|
}
|
|
|
|
query += " ORDER BY created_at DESC LIMIT 50"
|
|
|
|
rows, err := ns.db.QueryContext(ctx, query, args...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get notifications: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var notifications []Notification
|
|
for rows.Next() {
|
|
var notification Notification
|
|
if err := rows.Scan(
|
|
¬ification.ID,
|
|
¬ification.UserID,
|
|
¬ification.Type,
|
|
¬ification.Title,
|
|
¬ification.Content,
|
|
¬ification.Link,
|
|
¬ification.Read,
|
|
¬ification.CreatedAt,
|
|
); err != nil {
|
|
continue
|
|
}
|
|
notifications = append(notifications, notification)
|
|
}
|
|
|
|
return notifications, nil
|
|
}
|
|
|
|
// MarkAsRead marks a notification as read
|
|
func (ns *NotificationService) MarkAsRead(userID uuid.UUID, notificationID uuid.UUID) error {
|
|
ctx := context.Background()
|
|
|
|
_, err := ns.db.ExecContext(ctx, `
|
|
UPDATE notifications
|
|
SET read = TRUE
|
|
WHERE id = $1 AND user_id = $2
|
|
`, notificationID, userID)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to mark notification as read: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// MarkAllAsRead marks all notifications as read for a user
|
|
func (ns *NotificationService) MarkAllAsRead(userID uuid.UUID) error {
|
|
ctx := context.Background()
|
|
|
|
_, err := ns.db.ExecContext(ctx, `
|
|
UPDATE notifications
|
|
SET read = TRUE
|
|
WHERE user_id = $1 AND read = FALSE
|
|
`, userID)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to mark all notifications as read: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetUnreadCount returns the count of unread notifications
|
|
func (ns *NotificationService) GetUnreadCount(userID uuid.UUID) (int, error) {
|
|
ctx := context.Background()
|
|
|
|
var count int
|
|
err := ns.db.QueryRowContext(ctx, `
|
|
SELECT COUNT(*)
|
|
FROM notifications
|
|
WHERE user_id = $1 AND read = FALSE
|
|
`, userID).Scan(&count)
|
|
|
|
if err != nil {
|
|
return 0, fmt.Errorf("failed to get unread count: %w", err)
|
|
}
|
|
|
|
return count, nil
|
|
}
|