Compare commits
4 Commits
4f806ecdb1
...
3fc3bb8144
| Author | SHA1 | Date | |
|---|---|---|---|
| 3fc3bb8144 | |||
| efd6615809 | |||
| 355d3269c0 | |||
|
|
b56170f10c |
|
|
@ -4,6 +4,7 @@ using Microsoft.EntityFrameworkCore;
|
||||||
using Swashbuckle.AspNetCore.Annotations;
|
using Swashbuckle.AspNetCore.Annotations;
|
||||||
using SPMS.Domain.Common;
|
using SPMS.Domain.Common;
|
||||||
using SPMS.Infrastructure;
|
using SPMS.Infrastructure;
|
||||||
|
using SPMS.Infrastructure.Messaging;
|
||||||
|
|
||||||
namespace SPMS.API.Controllers;
|
namespace SPMS.API.Controllers;
|
||||||
|
|
||||||
|
|
@ -14,10 +15,17 @@ namespace SPMS.API.Controllers;
|
||||||
public class PublicController : ControllerBase
|
public class PublicController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly AppDbContext _dbContext;
|
private readonly AppDbContext _dbContext;
|
||||||
|
private readonly RabbitMQConnection _rabbitConnection;
|
||||||
|
private readonly RabbitMQInitializer _rabbitInitializer;
|
||||||
|
|
||||||
public PublicController(AppDbContext dbContext)
|
public PublicController(
|
||||||
|
AppDbContext dbContext,
|
||||||
|
RabbitMQConnection rabbitConnection,
|
||||||
|
RabbitMQInitializer rabbitInitializer)
|
||||||
{
|
{
|
||||||
_dbContext = dbContext;
|
_dbContext = dbContext;
|
||||||
|
_rabbitConnection = rabbitConnection;
|
||||||
|
_rabbitInitializer = rabbitInitializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("health")]
|
[HttpPost("health")]
|
||||||
|
|
@ -39,11 +47,26 @@ public class PublicController : ControllerBase
|
||||||
allHealthy = false;
|
allHealthy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Redis 연결 확인 (Phase 2에서 구현 예정)
|
// 2. Redis 연결 확인 (Phase 3-2에서 구현 예정)
|
||||||
checks["redis"] = new { status = "not_configured" };
|
checks["redis"] = new { status = "not_configured" };
|
||||||
|
|
||||||
// 3. RabbitMQ 연결 확인 (Phase 2에서 구현 예정)
|
// 3. RabbitMQ 연결 확인
|
||||||
checks["rabbitmq"] = new { status = "not_configured" };
|
var rabbitConnected = _rabbitConnection.IsConnected;
|
||||||
|
var rabbitInitialized = _rabbitInitializer.IsInitialized;
|
||||||
|
if (rabbitConnected && rabbitInitialized)
|
||||||
|
{
|
||||||
|
checks["rabbitmq"] = new { status = "healthy" };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
checks["rabbitmq"] = new
|
||||||
|
{
|
||||||
|
status = "unhealthy",
|
||||||
|
connected = rabbitConnected,
|
||||||
|
initialized = rabbitInitialized
|
||||||
|
};
|
||||||
|
allHealthy = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (allHealthy)
|
if (allHealthy)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,15 @@ public class PushController : ControllerBase
|
||||||
return Ok(ApiResponse.Success());
|
return Ok(ApiResponse.Success());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("log")]
|
||||||
|
[SwaggerOperation(Summary = "발송 로그 조회", Description = "푸시 발송 이력을 페이지 단위로 조회합니다.")]
|
||||||
|
public async Task<IActionResult> GetLogAsync([FromBody] PushLogRequestDto request)
|
||||||
|
{
|
||||||
|
var serviceId = GetServiceId();
|
||||||
|
var result = await _pushService.GetLogAsync(serviceId, request);
|
||||||
|
return Ok(ApiResponse<PushLogResponseDto>.Success(result));
|
||||||
|
}
|
||||||
|
|
||||||
private long GetServiceId()
|
private long GetServiceId()
|
||||||
{
|
{
|
||||||
if (HttpContext.Items.TryGetValue("ServiceId", out var serviceIdObj) && serviceIdObj is long serviceId)
|
if (HttpContext.Items.TryGetValue("ServiceId", out var serviceIdObj) && serviceIdObj is long serviceId)
|
||||||
|
|
|
||||||
27
SPMS.Application/DTOs/Push/PushLogRequestDto.cs
Normal file
27
SPMS.Application/DTOs/Push/PushLogRequestDto.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SPMS.Application.DTOs.Push;
|
||||||
|
|
||||||
|
public class PushLogRequestDto
|
||||||
|
{
|
||||||
|
[JsonPropertyName("page")]
|
||||||
|
public int Page { get; set; } = 1;
|
||||||
|
|
||||||
|
[JsonPropertyName("size")]
|
||||||
|
public int Size { get; set; } = 20;
|
||||||
|
|
||||||
|
[JsonPropertyName("message_code")]
|
||||||
|
public string? MessageCode { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("device_id")]
|
||||||
|
public long? DeviceId { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("status")]
|
||||||
|
public string? Status { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("start_date")]
|
||||||
|
public string? StartDate { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("end_date")]
|
||||||
|
public string? EndDate { get; set; }
|
||||||
|
}
|
||||||
34
SPMS.Application/DTOs/Push/PushLogResponseDto.cs
Normal file
34
SPMS.Application/DTOs/Push/PushLogResponseDto.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using SPMS.Application.DTOs.Notice;
|
||||||
|
|
||||||
|
namespace SPMS.Application.DTOs.Push;
|
||||||
|
|
||||||
|
public class PushLogResponseDto
|
||||||
|
{
|
||||||
|
[JsonPropertyName("items")]
|
||||||
|
public List<PushLogItemDto> Items { get; set; } = [];
|
||||||
|
|
||||||
|
[JsonPropertyName("pagination")]
|
||||||
|
public PaginationDto Pagination { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PushLogItemDto
|
||||||
|
{
|
||||||
|
[JsonPropertyName("send_id")]
|
||||||
|
public long SendId { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("message_code")]
|
||||||
|
public string MessageCode { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[JsonPropertyName("device_id")]
|
||||||
|
public long DeviceId { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("status")]
|
||||||
|
public string Status { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[JsonPropertyName("fail_reason")]
|
||||||
|
public string? FailReason { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("sent_at")]
|
||||||
|
public DateTime SentAt { get; set; }
|
||||||
|
}
|
||||||
14
SPMS.Application/DTOs/Push/PushSendRequestDto.cs
Normal file
14
SPMS.Application/DTOs/Push/PushSendRequestDto.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace SPMS.Application.DTOs.Push;
|
||||||
|
|
||||||
|
public class PushSendRequestDto
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string MessageCode { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public long DeviceId { get; set; }
|
||||||
|
|
||||||
|
public Dictionary<string, string>? Variables { get; set; }
|
||||||
|
}
|
||||||
8
SPMS.Application/DTOs/Push/PushSendResponseDto.cs
Normal file
8
SPMS.Application/DTOs/Push/PushSendResponseDto.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace SPMS.Application.DTOs.Push;
|
||||||
|
|
||||||
|
public class PushSendResponseDto
|
||||||
|
{
|
||||||
|
public string RequestId { get; set; } = string.Empty;
|
||||||
|
public string SendType { get; set; } = string.Empty;
|
||||||
|
public string Status { get; set; } = "queued";
|
||||||
|
}
|
||||||
15
SPMS.Application/DTOs/Push/PushSendTagRequestDto.cs
Normal file
15
SPMS.Application/DTOs/Push/PushSendTagRequestDto.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace SPMS.Application.DTOs.Push;
|
||||||
|
|
||||||
|
public class PushSendTagRequestDto
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string MessageCode { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[MinLength(1)]
|
||||||
|
public List<int> Tags { get; set; } = [];
|
||||||
|
|
||||||
|
public string TagMatch { get; set; } = "or";
|
||||||
|
}
|
||||||
|
|
@ -8,4 +8,5 @@ public interface IPushService
|
||||||
Task<PushSendResponseDto> SendByTagAsync(long serviceId, PushSendTagRequestDto request);
|
Task<PushSendResponseDto> SendByTagAsync(long serviceId, PushSendTagRequestDto request);
|
||||||
Task<PushScheduleResponseDto> ScheduleAsync(long serviceId, PushScheduleRequestDto request);
|
Task<PushScheduleResponseDto> ScheduleAsync(long serviceId, PushScheduleRequestDto request);
|
||||||
Task CancelScheduleAsync(PushScheduleCancelRequestDto request);
|
Task CancelScheduleAsync(PushScheduleCancelRequestDto request);
|
||||||
|
Task<PushLogResponseDto> GetLogAsync(long serviceId, PushLogRequestDto request);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
|
using System.Globalization;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using SPMS.Application.DTOs.Notice;
|
||||||
using SPMS.Application.DTOs.Push;
|
using SPMS.Application.DTOs.Push;
|
||||||
using SPMS.Application.Interfaces;
|
using SPMS.Application.Interfaces;
|
||||||
using SPMS.Domain.Common;
|
using SPMS.Domain.Common;
|
||||||
|
using SPMS.Domain.Enums;
|
||||||
using SPMS.Domain.Exceptions;
|
using SPMS.Domain.Exceptions;
|
||||||
using SPMS.Domain.Interfaces;
|
using SPMS.Domain.Interfaces;
|
||||||
|
|
||||||
|
|
@ -12,15 +15,18 @@ public class PushService : IPushService
|
||||||
private readonly IMessageRepository _messageRepository;
|
private readonly IMessageRepository _messageRepository;
|
||||||
private readonly IPushQueueService _pushQueueService;
|
private readonly IPushQueueService _pushQueueService;
|
||||||
private readonly IScheduleCancelStore _scheduleCancelStore;
|
private readonly IScheduleCancelStore _scheduleCancelStore;
|
||||||
|
private readonly IPushSendLogRepository _pushSendLogRepository;
|
||||||
|
|
||||||
public PushService(
|
public PushService(
|
||||||
IMessageRepository messageRepository,
|
IMessageRepository messageRepository,
|
||||||
IPushQueueService pushQueueService,
|
IPushQueueService pushQueueService,
|
||||||
IScheduleCancelStore scheduleCancelStore)
|
IScheduleCancelStore scheduleCancelStore,
|
||||||
|
IPushSendLogRepository pushSendLogRepository)
|
||||||
{
|
{
|
||||||
_messageRepository = messageRepository;
|
_messageRepository = messageRepository;
|
||||||
_pushQueueService = pushQueueService;
|
_pushQueueService = pushQueueService;
|
||||||
_scheduleCancelStore = scheduleCancelStore;
|
_scheduleCancelStore = scheduleCancelStore;
|
||||||
|
_pushSendLogRepository = pushSendLogRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<PushSendResponseDto> SendAsync(long serviceId, PushSendRequestDto request)
|
public async Task<PushSendResponseDto> SendAsync(long serviceId, PushSendRequestDto request)
|
||||||
|
|
@ -186,6 +192,77 @@ public class PushService : IPushService
|
||||||
await _scheduleCancelStore.MarkCancelledAsync(request.ScheduleId);
|
await _scheduleCancelStore.MarkCancelledAsync(request.ScheduleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<PushLogResponseDto> GetLogAsync(long serviceId, PushLogRequestDto request)
|
||||||
|
{
|
||||||
|
long? messageId = null;
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.MessageCode))
|
||||||
|
{
|
||||||
|
var message = await _messageRepository.GetByMessageCodeAndServiceAsync(request.MessageCode, serviceId);
|
||||||
|
if (message != null)
|
||||||
|
messageId = message.Id;
|
||||||
|
else
|
||||||
|
return new PushLogResponseDto
|
||||||
|
{
|
||||||
|
Items = [],
|
||||||
|
Pagination = new PaginationDto
|
||||||
|
{
|
||||||
|
Page = request.Page,
|
||||||
|
Size = request.Size,
|
||||||
|
TotalCount = 0,
|
||||||
|
TotalPages = 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
PushResult? status = null;
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.Status))
|
||||||
|
{
|
||||||
|
status = request.Status.ToLowerInvariant() switch
|
||||||
|
{
|
||||||
|
"success" => PushResult.Success,
|
||||||
|
"failed" => PushResult.Failed,
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime? startDate = null;
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.StartDate) &&
|
||||||
|
DateTime.TryParseExact(request.StartDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var parsedStart))
|
||||||
|
startDate = parsedStart;
|
||||||
|
|
||||||
|
DateTime? endDate = null;
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.EndDate) &&
|
||||||
|
DateTime.TryParseExact(request.EndDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var parsedEnd))
|
||||||
|
endDate = parsedEnd;
|
||||||
|
|
||||||
|
var (items, totalCount) = await _pushSendLogRepository.GetPagedWithMessageAsync(
|
||||||
|
serviceId, request.Page, request.Size,
|
||||||
|
messageId, request.DeviceId, status,
|
||||||
|
startDate, endDate);
|
||||||
|
|
||||||
|
var totalPages = (int)Math.Ceiling((double)totalCount / request.Size);
|
||||||
|
|
||||||
|
return new PushLogResponseDto
|
||||||
|
{
|
||||||
|
Items = items.Select(l => new PushLogItemDto
|
||||||
|
{
|
||||||
|
SendId = l.Id,
|
||||||
|
MessageCode = l.Message?.MessageCode ?? string.Empty,
|
||||||
|
DeviceId = l.DeviceId,
|
||||||
|
Status = l.Status.ToString().ToLowerInvariant(),
|
||||||
|
FailReason = l.FailReason,
|
||||||
|
SentAt = l.SentAt
|
||||||
|
}).ToList(),
|
||||||
|
Pagination = new PaginationDto
|
||||||
|
{
|
||||||
|
Page = request.Page,
|
||||||
|
Size = request.Size,
|
||||||
|
TotalCount = totalCount,
|
||||||
|
TotalPages = totalPages
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static string ApplyVariables(string template, Dictionary<string, string>? variables)
|
private static string ApplyVariables(string template, Dictionary<string, string>? variables)
|
||||||
{
|
{
|
||||||
if (variables == null || variables.Count == 0)
|
if (variables == null || variables.Count == 0)
|
||||||
|
|
|
||||||
13
SPMS.Domain/Interfaces/IPushSendLogRepository.cs
Normal file
13
SPMS.Domain/Interfaces/IPushSendLogRepository.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
using SPMS.Domain.Entities;
|
||||||
|
using SPMS.Domain.Enums;
|
||||||
|
|
||||||
|
namespace SPMS.Domain.Interfaces;
|
||||||
|
|
||||||
|
public interface IPushSendLogRepository : IRepository<PushSendLog>
|
||||||
|
{
|
||||||
|
Task<(IReadOnlyList<PushSendLog> Items, int TotalCount)> GetPagedWithMessageAsync(
|
||||||
|
long serviceId, int page, int size,
|
||||||
|
long? messageId = null, long? deviceId = null,
|
||||||
|
PushResult? status = null,
|
||||||
|
DateTime? startDate = null, DateTime? endDate = null);
|
||||||
|
}
|
||||||
|
|
@ -39,6 +39,7 @@ public static class DependencyInjection
|
||||||
services.AddScoped<IDeviceRepository, DeviceRepository>();
|
services.AddScoped<IDeviceRepository, DeviceRepository>();
|
||||||
services.AddScoped<IFileRepository, FileRepository>();
|
services.AddScoped<IFileRepository, FileRepository>();
|
||||||
services.AddScoped<IMessageRepository, MessageRepository>();
|
services.AddScoped<IMessageRepository, MessageRepository>();
|
||||||
|
services.AddScoped<IPushSendLogRepository, PushSendLogRepository>();
|
||||||
|
|
||||||
// External Services
|
// External Services
|
||||||
services.AddScoped<IJwtService, JwtService>();
|
services.AddScoped<IJwtService, JwtService>();
|
||||||
|
|
@ -57,7 +58,8 @@ public static class DependencyInjection
|
||||||
// RabbitMQ
|
// RabbitMQ
|
||||||
services.Configure<RabbitMQSettings>(configuration.GetSection(RabbitMQSettings.SectionName));
|
services.Configure<RabbitMQSettings>(configuration.GetSection(RabbitMQSettings.SectionName));
|
||||||
services.AddSingleton<RabbitMQConnection>();
|
services.AddSingleton<RabbitMQConnection>();
|
||||||
services.AddHostedService<RabbitMQInitializer>();
|
services.AddSingleton<RabbitMQInitializer>();
|
||||||
|
services.AddHostedService(sp => sp.GetRequiredService<RabbitMQInitializer>());
|
||||||
services.AddScoped<IPushQueueService, PushQueueService>();
|
services.AddScoped<IPushQueueService, PushQueueService>();
|
||||||
|
|
||||||
// Push Senders
|
// Push Senders
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ public class RabbitMQConnection : IAsyncDisposable
|
||||||
private readonly SemaphoreSlim _semaphore = new(1, 1);
|
private readonly SemaphoreSlim _semaphore = new(1, 1);
|
||||||
private IConnection? _connection;
|
private IConnection? _connection;
|
||||||
|
|
||||||
|
public bool IsConnected => _connection is { IsOpen: true };
|
||||||
|
|
||||||
public RabbitMQConnection(
|
public RabbitMQConnection(
|
||||||
IOptions<RabbitMQSettings> settings,
|
IOptions<RabbitMQSettings> settings,
|
||||||
ILogger<RabbitMQConnection> logger)
|
ILogger<RabbitMQConnection> logger)
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,14 @@ using SPMS.Application.Settings;
|
||||||
|
|
||||||
namespace SPMS.Infrastructure.Messaging;
|
namespace SPMS.Infrastructure.Messaging;
|
||||||
|
|
||||||
public class RabbitMQInitializer : IHostedService
|
public class RabbitMQInitializer : BackgroundService
|
||||||
{
|
{
|
||||||
private readonly RabbitMQConnection _connection;
|
private readonly RabbitMQConnection _connection;
|
||||||
private readonly RabbitMQSettings _settings;
|
private readonly RabbitMQSettings _settings;
|
||||||
private readonly ILogger<RabbitMQInitializer> _logger;
|
private readonly ILogger<RabbitMQInitializer> _logger;
|
||||||
|
private static readonly TimeSpan RetryInterval = TimeSpan.FromSeconds(30);
|
||||||
|
|
||||||
|
public bool IsInitialized { get; private set; }
|
||||||
|
|
||||||
public RabbitMQInitializer(
|
public RabbitMQInitializer(
|
||||||
RabbitMQConnection connection,
|
RabbitMQConnection connection,
|
||||||
|
|
@ -22,19 +25,26 @@ public class RabbitMQInitializer : IHostedService
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartAsync(CancellationToken cancellationToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
try
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
await InitializeAsync(cancellationToken);
|
try
|
||||||
}
|
{
|
||||||
catch (Exception ex)
|
await InitializeAsync(stoppingToken);
|
||||||
{
|
IsInitialized = true;
|
||||||
_logger.LogWarning(ex, "RabbitMQ 초기화 실패 — 서버는 계속 실행됩니다. 메시지 발송 시 재연결을 시도합니다.");
|
_logger.LogInformation("RabbitMQ 초기화 완료");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "RabbitMQ 초기화 실패 — {RetrySeconds}초 후 재시도합니다.", RetryInterval.TotalSeconds);
|
||||||
|
await Task.Delay(RetryInterval, stoppingToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InitializeAsync(CancellationToken cancellationToken)
|
private async Task InitializeAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await using var channel = await _connection.CreateChannelAsync(cancellationToken);
|
await using var channel = await _connection.CreateChannelAsync(cancellationToken);
|
||||||
|
|
||||||
|
|
@ -87,6 +97,4 @@ public class RabbitMQInitializer : IHostedService
|
||||||
_logger.LogInformation("Queue 선언 및 바인딩 완료: {Queue} → {Exchange} (routing_key: schedule)",
|
_logger.LogInformation("Queue 선언 및 바인딩 완료: {Queue} → {Exchange} (routing_key: schedule)",
|
||||||
_settings.ScheduleQueue, _settings.Exchange);
|
_settings.ScheduleQueue, _settings.Exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SPMS.Domain.Entities;
|
||||||
|
using SPMS.Domain.Enums;
|
||||||
|
using SPMS.Domain.Interfaces;
|
||||||
|
|
||||||
|
namespace SPMS.Infrastructure.Persistence.Repositories;
|
||||||
|
|
||||||
|
public class PushSendLogRepository : Repository<PushSendLog>, IPushSendLogRepository
|
||||||
|
{
|
||||||
|
public PushSendLogRepository(AppDbContext context) : base(context) { }
|
||||||
|
|
||||||
|
public async Task<(IReadOnlyList<PushSendLog> Items, int TotalCount)> GetPagedWithMessageAsync(
|
||||||
|
long serviceId, int page, int size,
|
||||||
|
long? messageId = null, long? deviceId = null,
|
||||||
|
PushResult? status = null,
|
||||||
|
DateTime? startDate = null, DateTime? endDate = null)
|
||||||
|
{
|
||||||
|
var query = _dbSet
|
||||||
|
.Include(l => l.Message)
|
||||||
|
.Where(l => l.ServiceId == serviceId);
|
||||||
|
|
||||||
|
if (messageId.HasValue)
|
||||||
|
query = query.Where(l => l.MessageId == messageId.Value);
|
||||||
|
|
||||||
|
if (deviceId.HasValue)
|
||||||
|
query = query.Where(l => l.DeviceId == deviceId.Value);
|
||||||
|
|
||||||
|
if (status.HasValue)
|
||||||
|
query = query.Where(l => l.Status == status.Value);
|
||||||
|
|
||||||
|
if (startDate.HasValue)
|
||||||
|
query = query.Where(l => l.SentAt >= startDate.Value);
|
||||||
|
|
||||||
|
if (endDate.HasValue)
|
||||||
|
query = query.Where(l => l.SentAt < endDate.Value.AddDays(1));
|
||||||
|
|
||||||
|
var totalCount = await query.CountAsync();
|
||||||
|
|
||||||
|
var items = await query
|
||||||
|
.OrderByDescending(l => l.SentAt)
|
||||||
|
.Skip((page - 1) * size)
|
||||||
|
.Take(size)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return (items, totalCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user