feat: 메시지 미리보기 API 구현 (#120)
Some checks failed
SPMS_API/pipeline/head There was a failure building this commit

Reviewed-on: https://git.ipstein.myds.me/SPMS/SPMS_API/pulls/121
This commit is contained in:
김선규 2026-02-10 08:31:19 +00:00
commit 975ed77d18
6 changed files with 89 additions and 1 deletions

View File

@ -12,10 +12,12 @@ namespace SPMS.API.Controllers;
public class MessageController : ControllerBase
{
private readonly IMessageValidationService _validationService;
private readonly IMessageService _messageService;
public MessageController(IMessageValidationService validationService)
public MessageController(IMessageValidationService validationService, IMessageService messageService)
{
_validationService = validationService;
_messageService = messageService;
}
[HttpPost("validate")]
@ -26,6 +28,15 @@ public class MessageController : ControllerBase
return Ok(ApiResponse<MessageValidationResultDto>.Success(result));
}
[HttpPost("preview")]
[SwaggerOperation(Summary = "메시지 미리보기", Description = "메시지 템플릿에 변수를 치환하여 미리보기를 생성합니다.")]
public async Task<IActionResult> PreviewAsync([FromBody] MessagePreviewRequestDto request)
{
var serviceId = GetServiceId();
var result = await _messageService.PreviewAsync(serviceId, request);
return Ok(ApiResponse<MessagePreviewResponseDto>.Success(result));
}
private long GetServiceId()
{
if (HttpContext.Items.TryGetValue("ServiceId", out var serviceIdObj) && serviceIdObj is long serviceId)

View File

@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace SPMS.Application.DTOs.Message;
public class MessagePreviewRequestDto
{
[Required]
public string MessageCode { get; set; } = string.Empty;
public Dictionary<string, string>? Variables { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace SPMS.Application.DTOs.Message;
public class MessagePreviewResponseDto
{
public string Title { get; set; } = string.Empty;
public string Body { get; set; } = string.Empty;
public string? ImageUrl { get; set; }
public string? LinkUrl { get; set; }
}

View File

@ -20,6 +20,7 @@ public static class DependencyInjection
services.AddScoped<IFileService, FileService>();
services.AddScoped<IPushService, PushService>();
services.AddSingleton<IMessageValidationService, MessageValidationService>();
services.AddScoped<IMessageService, MessageService>();
return services;
}

View File

@ -0,0 +1,8 @@
using SPMS.Application.DTOs.Message;
namespace SPMS.Application.Interfaces;
public interface IMessageService
{
Task<MessagePreviewResponseDto> PreviewAsync(long serviceId, MessagePreviewRequestDto request);
}

View File

@ -0,0 +1,48 @@
using SPMS.Application.DTOs.Message;
using SPMS.Application.Interfaces;
using SPMS.Domain.Common;
using SPMS.Domain.Exceptions;
using SPMS.Domain.Interfaces;
namespace SPMS.Application.Services;
public class MessageService : IMessageService
{
private readonly IMessageRepository _messageRepository;
public MessageService(IMessageRepository messageRepository)
{
_messageRepository = messageRepository;
}
public async Task<MessagePreviewResponseDto> PreviewAsync(long serviceId, MessagePreviewRequestDto request)
{
var message = await _messageRepository.GetByMessageCodeAndServiceAsync(request.MessageCode, serviceId);
if (message == null)
throw new SpmsException(ErrorCodes.MessageNotFound, "존재하지 않는 메시지 코드입니다.", 404);
var title = ApplyVariables(message.Title, request.Variables);
var body = ApplyVariables(message.Body, request.Variables);
return new MessagePreviewResponseDto
{
Title = title,
Body = body,
ImageUrl = message.ImageUrl,
LinkUrl = message.LinkUrl
};
}
private static string ApplyVariables(string template, Dictionary<string, string>? variables)
{
if (variables == null || variables.Count == 0)
return template;
var result = template;
foreach (var (key, value) in variables)
{
result = result.Replace($"{{{{{key}}}}}", value);
}
return result;
}
}