168 lines
5.7 KiB
Go
168 lines
5.7 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/gochat/gochat/internal/model"
|
|
)
|
|
|
|
// NotificationRepo implements GORM repository for Notification.
|
|
// Reference: Chatwoot app/models/notification.rb
|
|
type NotificationRepo struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewNotificationRepo creates a new Notification repository.
|
|
func NewNotificationRepo(db *gorm.DB) *NotificationRepo {
|
|
return &NotificationRepo{db: db}
|
|
}
|
|
|
|
// FindByID retrieves a notification by primary key.
|
|
func (r *NotificationRepo) FindByID(ctx context.Context, id uint) (*model.Notification, error) {
|
|
var n model.Notification
|
|
err := r.db.WithContext(ctx).First(&n, id).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &n, nil
|
|
}
|
|
|
|
// ListByUser retrieves all notifications for a user with pagination.
|
|
func (r *NotificationRepo) ListByUser(ctx context.Context, userID uint, offset, limit int) ([]model.Notification, int64, error) {
|
|
var notifications []model.Notification
|
|
var total int64
|
|
|
|
db := r.db.WithContext(ctx).Where("user_id = ?", userID)
|
|
if err := db.Model(&model.Notification{}).Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
if err := db.Order("created_at DESC").Offset(offset).Limit(limit).Find(¬ifications).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return notifications, total, nil
|
|
}
|
|
|
|
// ListByUserAndAccount retrieves notifications for a user within an account.
|
|
func (r *NotificationRepo) ListByUserAndAccount(ctx context.Context, userID uint, accountID uint, offset, limit int) ([]model.Notification, int64, error) {
|
|
var notifications []model.Notification
|
|
var total int64
|
|
|
|
db := r.db.WithContext(ctx).Where("user_id = ? AND account_id = ?", userID, accountID)
|
|
if err := db.Model(&model.Notification{}).Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
if err := db.Order("created_at DESC").Offset(offset).Limit(limit).Find(¬ifications).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return notifications, total, nil
|
|
}
|
|
|
|
// Create inserts a new notification.
|
|
func (r *NotificationRepo) Create(ctx context.Context, notification *model.Notification) error {
|
|
return r.db.WithContext(ctx).Create(notification).Error
|
|
}
|
|
|
|
// Update modifies an existing notification.
|
|
func (r *NotificationRepo) Update(ctx context.Context, notification *model.Notification) error {
|
|
return r.db.WithContext(ctx).Save(notification).Error
|
|
}
|
|
|
|
// MarkRead marks a single notification as read.
|
|
func (r *NotificationRepo) MarkRead(ctx context.Context, id uint) error {
|
|
now := time.Now()
|
|
result := r.db.WithContext(ctx).Model(&model.Notification{}).
|
|
Where("id = ?", id).
|
|
Update("read_at", now)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return gorm.ErrRecordNotFound
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MarkAllReadByUser marks all unread notifications for a user as read.
|
|
func (r *NotificationRepo) MarkAllReadByUser(ctx context.Context, userID uint) error {
|
|
now := time.Now()
|
|
return r.db.WithContext(ctx).Model(&model.Notification{}).
|
|
Where("user_id = ? AND read_at IS NULL", userID).
|
|
Update("read_at", now).Error
|
|
}
|
|
|
|
// MarkAllReadByUserAndAccount marks all unread notifications for a user within an account as read.
|
|
func (r *NotificationRepo) MarkAllReadByUserAndAccount(ctx context.Context, userID uint, accountID uint) error {
|
|
now := time.Now()
|
|
return r.db.WithContext(ctx).Model(&model.Notification{}).
|
|
Where("user_id = ? AND account_id = ? AND read_at IS NULL", userID, accountID).
|
|
Update("read_at", now).Error
|
|
}
|
|
|
|
// Delete soft-deletes a notification.
|
|
func (r *NotificationRepo) Delete(ctx context.Context, id uint) error {
|
|
return r.db.WithContext(ctx).Delete(&model.Notification{}, id).Error
|
|
}
|
|
|
|
// CountUnreadByUser counts unread notifications for a user.
|
|
func (r *NotificationRepo) CountUnreadByUser(ctx context.Context, userID uint) (int64, error) {
|
|
var count int64
|
|
err := r.db.WithContext(ctx).Model(&model.Notification{}).
|
|
Where("user_id = ? AND read_at IS NULL", userID).
|
|
Count(&count).Error
|
|
return count, err
|
|
}
|
|
|
|
// Snooze sets the snoozed_until timestamp and clears read_at for a notification.
|
|
// Returns the updated notification.
|
|
// Reference: Chatwoot notifications_controller.rb#snooze
|
|
func (r *NotificationRepo) Snooze(ctx context.Context, id, userID, accountID uint, snoozedUntil time.Time) (*model.Notification, error) {
|
|
result := r.db.WithContext(ctx).Model(&model.Notification{}).
|
|
Where("id = ? AND user_id = ? AND account_id = ?", id, userID, accountID).
|
|
Updates(map[string]interface{}{"snoozed_until": snoozedUntil, "read_at": nil})
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, gorm.ErrRecordNotFound
|
|
}
|
|
var notif model.Notification
|
|
if err := r.db.WithContext(ctx).First(¬if, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return ¬if, nil
|
|
}
|
|
|
|
// MarkUnread clears read_at for a notification, marking it as unread.
|
|
// Returns the updated notification.
|
|
// Reference: Chatwoot notifications_controller.rb#unread
|
|
func (r *NotificationRepo) MarkUnread(ctx context.Context, id, userID, accountID uint) (*model.Notification, error) {
|
|
result := r.db.WithContext(ctx).Model(&model.Notification{}).
|
|
Where("id = ? AND user_id = ? AND account_id = ?", id, userID, accountID).
|
|
Update("read_at", nil)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, gorm.ErrRecordNotFound
|
|
}
|
|
var notif model.Notification
|
|
if err := r.db.WithContext(ctx).First(¬if, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return ¬if, nil
|
|
}
|
|
|
|
// DeleteAllByUser soft-deletes all notifications for a user within an account.
|
|
// Reference: Chatwoot notifications_controller.rb#destroy_all
|
|
func (r *NotificationRepo) DeleteAllByUser(ctx context.Context, userID, accountID uint) error {
|
|
return r.db.WithContext(ctx).
|
|
Where("user_id = ? AND account_id = ?", userID, accountID).
|
|
Delete(&model.Notification{}).Error
|
|
} |