improvement: 메시지 발송 상태 집계 규칙 고정 (#178) #228

Merged
seonkyu.kim merged 1 commits from improvement/#178-send-status-rule into develop 2026-02-25 06:11:48 +00:00
4 changed files with 27 additions and 14 deletions

View File

@ -32,7 +32,7 @@ public class MessageController : ControllerBase
}
[HttpPost("list")]
[SwaggerOperation(Summary = "메시지 목록 조회", Description = "메시지 목록을 페이지 단위로 조회합니다. X-Service-Code 헤더가 있으면 해당 서비스만, 없으면 전체 서비스 메시지를 반환합니다. send_status 필터(complete/pending/failed)를 지원합니다.")]
[SwaggerOperation(Summary = "메시지 목록 조회", Description = "메시지 목록을 페이지 단위로 조회합니다. X-Service-Code 헤더가 있으면 해당 서비스만, 없으면 전체 서비스 메시지를 반환합니다. send_status 필터(complete/pending/failed)를 지원합니다. 발송 상태는 통일된 SendStatus 규칙(pending=미발송, complete=1건 이상 성공, failed=전건 실패)으로 판정됩니다.")]
public async Task<IActionResult> GetListAsync([FromBody] MessageListRequestDto request)
{
var serviceId = GetServiceIdOrNull();
@ -41,7 +41,7 @@ public class MessageController : ControllerBase
}
[HttpPost("info")]
[SwaggerOperation(Summary = "메시지 상세 조회", Description = "메시지 코드로 상세 정보를 조회합니다. 서비스 정보(service_name, service_code), 작성자(created_by_name), 발송 상태(latest_send_status), 템플릿 변수 목록을 포함합니다.")]
[SwaggerOperation(Summary = "메시지 상세 조회", Description = "메시지 코드로 상세 정보를 조회합니다. 서비스 정보(service_name, service_code), 작성자(created_by_name), 발송 상태(latest_send_status), 템플릿 변수 목록을 포함합니다. 발송 상태는 통일된 SendStatus 규칙(pending=미발송, complete=1건 이상 성공, failed=전건 실패)으로 판정됩니다.")]
public async Task<IActionResult> GetInfoAsync([FromBody] MessageInfoRequestDto request)
{
var serviceId = GetServiceId();

View File

@ -4,6 +4,7 @@ using SPMS.Application.DTOs.Message;
using SPMS.Application.DTOs.Notice;
using SPMS.Application.Interfaces;
using SPMS.Domain.Common;
using SPMS.Domain.Enums;
using SPMS.Domain.Exceptions;
using SPMS.Domain.Interfaces;
@ -84,7 +85,7 @@ public class MessageService : IMessageService
CreatedAt = p.CreatedAt,
ServiceName = p.ServiceName,
ServiceCode = p.ServiceCode,
LatestSendStatus = DetermineSendStatus(p.TotalSendCount, p.SuccessCount)
LatestSendStatus = SendStatus.Determine(p.TotalSendCount, p.SuccessCount)
}).ToList(),
Pagination = new PaginationDto
{
@ -96,12 +97,6 @@ public class MessageService : IMessageService
};
}
private static string DetermineSendStatus(int totalSend, int successCount)
{
if (totalSend == 0) return "pending";
return successCount > 0 ? "complete" : "failed";
}
public async Task<MessageInfoResponseDto> GetInfoAsync(long serviceId, MessageInfoRequestDto request)
{
if (string.IsNullOrWhiteSpace(request.MessageCode))
@ -135,7 +130,7 @@ public class MessageService : IMessageService
ServiceName = message.Service.ServiceName,
ServiceCode = message.Service.ServiceCode,
CreatedByName = message.CreatedByAdmin.Name,
LatestSendStatus = DetermineSendStatus(totalSend, successCount),
LatestSendStatus = SendStatus.Determine(totalSend, successCount),
CreatedAt = message.CreatedAt
};
}

View File

@ -0,0 +1,18 @@
namespace SPMS.Domain.Enums;
/// <summary>
/// 메시지 발송 상태 판정 규칙 (PRD FR-MSG-006)
/// 목록/상세/통계 API에서 동일 규칙을 적용해야 함
/// </summary>
public static class SendStatus
{
public const string Pending = "pending";
public const string Complete = "complete";
public const string Failed = "failed";
public static string Determine(int totalSendCount, int successCount)
{
if (totalSendCount == 0) return Pending;
return successCount > 0 ? Complete : Failed;
}
}

View File

@ -104,12 +104,12 @@ public class MessageRepository : Repository<Message>, IMessageRepository
SuccessCount = _context.PushSendLogs.Count(l => l.MessageId == m.Id && l.Status == PushResult.Success)
});
// 발송 상태 필터
if (sendStatus == "complete")
// 발송 상태 필터 (SendStatus 상수 사용 — PRD FR-MSG-006)
if (sendStatus == SendStatus.Complete)
projected = projected.Where(p => p.SuccessCount > 0);
else if (sendStatus == "failed")
else if (sendStatus == SendStatus.Failed)
projected = projected.Where(p => p.TotalSendCount > 0 && p.SuccessCount == 0);
else if (sendStatus == "pending")
else if (sendStatus == SendStatus.Pending)
projected = projected.Where(p => p.TotalSendCount == 0);
var totalCount = await projected.CountAsync();