153 lines
6.2 KiB
C#
153 lines
6.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Sozsoft.Notifications.Domain;
|
|
using Sozsoft.Notifications.Entities;
|
|
using Sozsoft.Notifications.Enums;
|
|
using Volo.Abp;
|
|
using Volo.Abp.Application.Services;
|
|
using Volo.Abp.Domain.Entities;
|
|
using Volo.Abp.Domain.Repositories;
|
|
using Volo.Abp.Identity;
|
|
|
|
namespace Sozsoft.Notifications.Application;
|
|
|
|
/// <summary>
|
|
/// Kullanicinin kendi bildirimleri: liste, okundu isaretleme ve tarayici kanallarinda gosterim
|
|
/// isareti. Her sorgu <c>UserId</c> ile kendi kayitlarina kapalidir.
|
|
/// </summary>
|
|
[Authorize]
|
|
public class NotificationAppService : ReadOnlyAppService<
|
|
Notification,
|
|
NotificationDto,
|
|
Guid,
|
|
NotificationFilterRequestDto>
|
|
{
|
|
private readonly IRepository<Notification, Guid> repository;
|
|
private readonly IRepository<NotificationRule, Guid> repositoryRule;
|
|
private readonly INotificationManager notificationManager;
|
|
private readonly IRepository<IdentityUser, Guid> repositoryUser;
|
|
|
|
public NotificationAppService(
|
|
IRepository<Notification, Guid> repository,
|
|
IRepository<NotificationRule, Guid> repositoryRule,
|
|
INotificationManager notificationManager,
|
|
IRepository<IdentityUser, Guid> repositoryUser) : base(repository)
|
|
{
|
|
this.repository = repository;
|
|
this.repositoryRule = repositoryRule;
|
|
this.notificationManager = notificationManager;
|
|
this.repositoryUser = repositoryUser;
|
|
}
|
|
|
|
/// <summary>Bir kuraldan elle bildirim uretir; Bildirim Kurallari ekranindaki "Create" komutu.</summary>
|
|
public async Task CreateNotificationByNotificationRuleIdAsync(NotificationRequestDto input)
|
|
{
|
|
var notificationRule = await repositoryRule.FindAsync(input.Id)
|
|
?? throw new EntityNotFoundException(L["RecordNotFound"]);
|
|
|
|
await notificationManager.SendNotificationAsync(notificationRule.NotificationTypeId, input.Message);
|
|
}
|
|
|
|
protected override async Task<IQueryable<Notification>> CreateFilteredQueryAsync(NotificationFilterRequestDto input)
|
|
{
|
|
var query = await base.CreateFilteredQueryAsync(input);
|
|
|
|
input.Channels ??= [];
|
|
var now = Clock.Now.AddDays(-1);
|
|
query = query
|
|
.AsNoTracking()
|
|
.Include(a => a.NotificationType)
|
|
.Where(a => a.UserId == CurrentUser.Id)
|
|
.Where(a => input.Channels.Contains(a.NotificationChannel))
|
|
.WhereIf(input.IsRead.HasValue, a => a.IsRead == input.IsRead)
|
|
.WhereIf(!input.IsListRequest && !input.Channels.IsNullOrEmpty() && input.Channels!.Contains(NotificationChannels.UiToast), a => a.CreationTime >= now);
|
|
|
|
return query;
|
|
}
|
|
|
|
protected override async Task<List<NotificationDto>> MapToGetListOutputDtosAsync(List<Notification> entities)
|
|
{
|
|
var dtos = new List<NotificationDto>();
|
|
var userIds = entities.Select(a => a.CreatorId).Distinct().ToArray();
|
|
var query = await repositoryUser.GetQueryableAsync();
|
|
var users = await query.AsNoTracking().Where(a => userIds.Contains(a.Id)).Select(a => new { a.Id, Fullname = $"{a.Name} {a.Surname}".Trim(), a.TenantId }).ToDictionaryAsync(x => x.Id, x => x);
|
|
|
|
foreach (var entity in entities)
|
|
{
|
|
var dto = await MapToGetListOutputDtoAsync(entity);
|
|
if (entity.CreatorId.HasValue && users.TryGetValue(entity.CreatorId.Value, out var user))
|
|
{
|
|
dto.CreatorFullname = user.Fullname;
|
|
dto.TenantId = user.TenantId;
|
|
}
|
|
dtos.Add(dto);
|
|
}
|
|
|
|
return dtos;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bir kanaldaki tum kayitlari okundu/okunmadi yapar. Kullaniciya henuz iletilmemis kayit
|
|
/// okunamaz; isaretleme onlari atlar ve gonderim gerceklestiginde tekrar okunabilir olurlar.
|
|
/// </summary>
|
|
public async Task<int> UpdateReadAllAsync(string notificationChannel, bool isRead)
|
|
{
|
|
var query = await repository.GetQueryableAsync();
|
|
var readTime = isRead ? Clock.Now : (DateTime?)null;
|
|
var affectedRows = await query
|
|
.Where(a => a.UserId == CurrentUser.Id && a.NotificationChannel == notificationChannel && a.IsRead == !isRead)
|
|
.Where(a => !isRead || a.IsSent)
|
|
.ExecuteUpdateAsync(b => b
|
|
.SetProperty(u => u.IsRead, isRead)
|
|
.SetProperty(u => u.ReadTime, readTime)
|
|
);
|
|
|
|
return affectedRows;
|
|
}
|
|
|
|
/// <summary>Secili kayitlari okundu/okunmadi yapar; kural <see cref="UpdateReadAllAsync"/> ile aynidir.</summary>
|
|
public async Task<int> UpdateReadManyAsync(List<Guid> notificationIds, bool isRead)
|
|
{
|
|
if (notificationIds.Count == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
var query = await repository.GetQueryableAsync();
|
|
var readTime = isRead ? Clock.Now : (DateTime?)null;
|
|
|
|
return await query
|
|
.Where(a => a.UserId == CurrentUser.Id && notificationIds.Contains(a.Id) && a.IsRead != isRead)
|
|
.Where(a => !isRead || a.IsSent)
|
|
.ExecuteUpdateAsync(setters => setters
|
|
.SetProperty(a => a.IsRead, isRead)
|
|
.SetProperty(a => a.ReadTime, readTime));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tarayici kanallarinda (toast, masaustu) gosterim isaretidir; gosterilen kayit iletilmis
|
|
/// sayilir. Diger kanallarin gonderimi <c>NotificationWorker</c>'a aittir.
|
|
/// </summary>
|
|
public async Task<int> UpdateSentManyAsync(List<Guid> notificationIds, bool isSent)
|
|
{
|
|
if (notificationIds.Count == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
var query = await repository.GetQueryableAsync();
|
|
return await query
|
|
.Where(a => a.UserId == CurrentUser.Id && notificationIds.Contains(a.Id) && a.IsSent != isSent)
|
|
.Where(a => NotificationChannels.BrowserChannels.Contains(a.NotificationChannel))
|
|
.ExecuteUpdateAsync(setters => setters.SetProperty(a => a.IsSent, isSent));
|
|
}
|
|
|
|
[RemoteService(false)]
|
|
public override Task<NotificationDto> GetAsync(Guid id) => throw new NotImplementedException();
|
|
[RemoteService(false)]
|
|
protected override Task<Notification> GetEntityByIdAsync(Guid id) => throw new NotImplementedException();
|
|
}
|