improvement: 메시지 상세/프리뷰 응답 강화 (#226) #227
|
|
@ -41,7 +41,7 @@ public class MessageController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("info")]
|
||||
[SwaggerOperation(Summary = "메시지 상세 조회", Description = "메시지 코드로 상세 정보를 조회합니다. 템플릿 변수 목록을 포함합니다.")]
|
||||
[SwaggerOperation(Summary = "메시지 상세 조회", Description = "메시지 코드로 상세 정보를 조회합니다. 서비스 정보(service_name, service_code), 작성자(created_by_name), 발송 상태(latest_send_status), 템플릿 변수 목록을 포함합니다.")]
|
||||
public async Task<IActionResult> GetInfoAsync([FromBody] MessageInfoRequestDto request)
|
||||
{
|
||||
var serviceId = GetServiceId();
|
||||
|
|
@ -67,7 +67,7 @@ public class MessageController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("preview")]
|
||||
[SwaggerOperation(Summary = "메시지 미리보기", Description = "메시지 템플릿에 변수를 치환하여 미리보기를 생성합니다.")]
|
||||
[SwaggerOperation(Summary = "메시지 미리보기", Description = "메시지 템플릿에 변수를 치환하여 미리보기를 생성합니다. 응답에 link_type을 포함합니다.")]
|
||||
public async Task<IActionResult> PreviewAsync([FromBody] MessagePreviewRequestDto request)
|
||||
{
|
||||
var serviceId = GetServiceId();
|
||||
|
|
|
|||
|
|
@ -31,6 +31,18 @@ public class MessageInfoResponseDto
|
|||
[JsonPropertyName("is_active")]
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
[JsonPropertyName("service_name")]
|
||||
public string ServiceName { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("service_code")]
|
||||
public string ServiceCode { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("created_by_name")]
|
||||
public string CreatedByName { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("latest_send_status")]
|
||||
public string LatestSendStatus { get; set; } = "pending";
|
||||
|
||||
[JsonPropertyName("created_at")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SPMS.Application.DTOs.Message;
|
||||
|
||||
public class MessagePreviewRequestDto
|
||||
{
|
||||
[Required]
|
||||
[JsonPropertyName("message_code")]
|
||||
public string MessageCode { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("variables")]
|
||||
public Dictionary<string, string>? Variables { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,21 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SPMS.Application.DTOs.Message;
|
||||
|
||||
public class MessagePreviewResponseDto
|
||||
{
|
||||
[JsonPropertyName("title")]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("body")]
|
||||
public string Body { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("image_url")]
|
||||
public string? ImageUrl { get; set; }
|
||||
|
||||
[JsonPropertyName("link_url")]
|
||||
public string? LinkUrl { get; set; }
|
||||
|
||||
[JsonPropertyName("link_type")]
|
||||
public string? LinkType { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ public class MessageService : IMessageService
|
|||
if (string.IsNullOrWhiteSpace(request.MessageCode))
|
||||
throw new SpmsException(ErrorCodes.BadRequest, "메시지 코드는 필수입니다.", 400);
|
||||
|
||||
var message = await _messageRepository.GetByMessageCodeAndServiceAsync(request.MessageCode, serviceId);
|
||||
var message = await _messageRepository.GetByMessageCodeWithDetailsAsync(request.MessageCode, serviceId);
|
||||
if (message == null)
|
||||
throw new SpmsException(ErrorCodes.MessageNotFound, "존재하지 않는 메시지 코드입니다.", 404);
|
||||
|
||||
|
|
@ -119,6 +119,8 @@ public class MessageService : IMessageService
|
|||
data = JsonSerializer.Deserialize<JsonElement>(message.CustomData);
|
||||
}
|
||||
|
||||
var (totalSend, successCount) = await _messageRepository.GetSendStatsAsync(message.Id);
|
||||
|
||||
return new MessageInfoResponseDto
|
||||
{
|
||||
MessageCode = message.MessageCode,
|
||||
|
|
@ -130,6 +132,10 @@ public class MessageService : IMessageService
|
|||
Data = data,
|
||||
Variables = variables,
|
||||
IsActive = !message.IsDeleted,
|
||||
ServiceName = message.Service.ServiceName,
|
||||
ServiceCode = message.Service.ServiceCode,
|
||||
CreatedByName = message.CreatedByAdmin.Name,
|
||||
LatestSendStatus = DetermineSendStatus(totalSend, successCount),
|
||||
CreatedAt = message.CreatedAt
|
||||
};
|
||||
}
|
||||
|
|
@ -163,7 +169,8 @@ public class MessageService : IMessageService
|
|||
Title = title,
|
||||
Body = body,
|
||||
ImageUrl = message.ImageUrl,
|
||||
LinkUrl = message.LinkUrl
|
||||
LinkUrl = message.LinkUrl,
|
||||
LinkType = message.LinkType
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ public interface IMessageRepository : IRepository<Message>
|
|||
Task<(IReadOnlyList<MessageListProjection> Items, int TotalCount)> GetPagedForListAsync(
|
||||
long? serviceId, int page, int size,
|
||||
string? keyword = null, bool? isActive = null, string? sendStatus = null);
|
||||
Task<Message?> GetByMessageCodeWithDetailsAsync(string messageCode, long serviceId);
|
||||
Task<(int TotalSendCount, int SuccessCount)> GetSendStatsAsync(long messageId);
|
||||
}
|
||||
|
||||
public class MessageListProjection
|
||||
|
|
|
|||
|
|
@ -54,6 +54,29 @@ public class MessageRepository : Repository<Message>, IMessageRepository
|
|||
return (items, totalCount);
|
||||
}
|
||||
|
||||
public async Task<Message?> GetByMessageCodeWithDetailsAsync(string messageCode, long serviceId)
|
||||
{
|
||||
return await _dbSet
|
||||
.Include(m => m.Service)
|
||||
.Include(m => m.CreatedByAdmin)
|
||||
.FirstOrDefaultAsync(m => m.MessageCode == messageCode && m.ServiceId == serviceId && !m.IsDeleted);
|
||||
}
|
||||
|
||||
public async Task<(int TotalSendCount, int SuccessCount)> GetSendStatsAsync(long messageId)
|
||||
{
|
||||
var stats = await _context.PushSendLogs
|
||||
.Where(l => l.MessageId == messageId)
|
||||
.GroupBy(_ => 1)
|
||||
.Select(g => new
|
||||
{
|
||||
Total = g.Count(),
|
||||
Success = g.Count(l => l.Status == PushResult.Success)
|
||||
})
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
return stats != null ? (stats.Total, stats.Success) : (0, 0);
|
||||
}
|
||||
|
||||
public async Task<(IReadOnlyList<MessageListProjection> Items, int TotalCount)> GetPagedForListAsync(
|
||||
long? serviceId, int page, int size,
|
||||
string? keyword = null, bool? isActive = null, string? sendStatus = null)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user