Files
serega404 926688cd2e
Backend CI / build-and-test (push) Successful in 51s
Frontend CI / build-and-check (push) Failing after 5m11s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Successful in 14s
🚀 Create and publish a Docker image / Build & publish backend image (push) Successful in 1m20s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Successful in 23s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Successful in 11s
feat: добавил напоминания о лекциях
2026-05-16 11:19:31 +03:00

121 lines
4.3 KiB
C#

using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using UniVerse.Application.DTOs.Common;
using UniVerse.Application.DTOs.Notifications;
using UniVerse.Application.Interfaces;
using UniVerse.Domain.Entities;
using UniVerse.Infrastructure.Data;
namespace UniVerse.Infrastructure.Notifications;
public class NotificationService : INotificationService
{
private readonly AppDbContext _db;
private readonly IEnumerable<INotificationProvider> _providers;
private readonly INotificationScheduler _scheduler;
private readonly ILogger<NotificationService> _logger;
public NotificationService(
AppDbContext db,
IEnumerable<INotificationProvider> providers,
INotificationScheduler scheduler,
ILogger<NotificationService> logger)
{
_db = db;
_providers = providers;
_scheduler = scheduler;
_logger = logger;
}
public async Task SendAsync(NotificationMessage message, CancellationToken cancellationToken = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(message.Channel);
ArgumentException.ThrowIfNullOrWhiteSpace(message.Recipient);
ArgumentException.ThrowIfNullOrWhiteSpace(message.Subject);
ArgumentException.ThrowIfNullOrWhiteSpace(message.Body);
var provider = _providers.FirstOrDefault(p => string.Equals(p.Channel, message.Channel, StringComparison.OrdinalIgnoreCase))
?? throw new InvalidOperationException($"Notification provider for channel '{message.Channel}' is not registered.");
_logger.LogInformation("Dispatching notification through {Channel} to {Recipient}", message.Channel, message.Recipient);
await provider.SendAsync(message, cancellationToken);
}
public Task<ScheduledNotificationResponse> ScheduleAsync(ScheduleNotificationRequest request, CancellationToken cancellationToken = default)
{
var message = new NotificationMessage(
request.Channel,
request.Recipient,
request.Subject,
request.Body,
request.RecipientName,
request.Metadata);
return _scheduler.ScheduleAsync(message, request.SendAt, cancellationToken: cancellationToken);
}
public async Task<UserNotificationDto> CreateUserNotificationAsync(
int userId,
string type,
string title,
string body,
CancellationToken cancellationToken = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(type);
ArgumentException.ThrowIfNullOrWhiteSpace(title);
ArgumentException.ThrowIfNullOrWhiteSpace(body);
var notification = new UserNotification
{
UserId = userId,
Type = type,
Title = title,
Body = body
};
_db.UserNotifications.Add(notification);
await _db.SaveChangesAsync(cancellationToken);
return ToDto(notification);
}
public async Task<PagedResult<UserNotificationDto>> GetUserNotificationsAsync(
int userId,
PaginationRequest pagination,
CancellationToken cancellationToken = default)
{
var query = _db.UserNotifications.Where(n => n.UserId == userId);
var total = await query.CountAsync(cancellationToken);
var items = await query
.OrderByDescending(n => n.CreatedAt)
.Skip((pagination.Page - 1) * pagination.PageSize)
.Take(pagination.PageSize)
.Select(n => new UserNotificationDto(
n.Id,
n.Type,
n.Title,
n.Body,
n.IsRead,
n.CreatedAt))
.ToListAsync(cancellationToken);
return PagedResult<UserNotificationDto>.Create(items, total, pagination.Page, pagination.PageSize);
}
public async Task MarkAllReadAsync(int userId, CancellationToken cancellationToken = default)
{
await _db.UserNotifications
.Where(n => n.UserId == userId && !n.IsRead)
.ExecuteUpdateAsync(setters => setters.SetProperty(n => n.IsRead, true), cancellationToken);
}
private static UserNotificationDto ToDto(UserNotification notification) => new(
notification.Id,
notification.Type,
notification.Title,
notification.Body,
notification.IsRead,
notification.CreatedAt
);
}