improvement: 통계 서비스 범위 정책 고정 (#229)
- Stats 도메인 에러코드 추가 (171: DateRangeInvalid, 172: ServiceScopeInvalid) - StatsService ParseDateRange에서 generic BadRequest → StatsDateRangeInvalid로 교체 - StatsController 전 엔드포인트 Swagger Description에 스코프 정책 안내 추가 - SpmsHeaderOperationFilter에서 message/list를 Optional로 반영 (미들웨어 정합) Closes #229
This commit is contained in:
parent
15a2dd66e5
commit
a3b2da5ffb
|
|
@ -19,7 +19,7 @@ public class StatsController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("daily")]
|
||||
[SwaggerOperation(Summary = "일별 통계 조회", Description = "기간별 일별 발송/성공/실패/열람 통계를 조회합니다.")]
|
||||
[SwaggerOperation(Summary = "일별 통계 조회", Description = "기간별 일별 발송/성공/실패/열람 통계를 조회합니다. X-Service-Code 헤더 미지정 시 전체 서비스 통계를 조회합니다.")]
|
||||
public async Task<IActionResult> GetDailyAsync([FromBody] DailyStatRequestDto request)
|
||||
{
|
||||
var serviceId = GetOptionalServiceId();
|
||||
|
|
@ -28,7 +28,7 @@ public class StatsController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("summary")]
|
||||
[SwaggerOperation(Summary = "요약 통계 조회", Description = "대시보드 요약 통계를 조회합니다.")]
|
||||
[SwaggerOperation(Summary = "요약 통계 조회", Description = "대시보드 요약 통계를 조회합니다. X-Service-Code 헤더 미지정 시 전체 서비스 통계를 조회합니다.")]
|
||||
public async Task<IActionResult> GetSummaryAsync()
|
||||
{
|
||||
var serviceId = GetOptionalServiceId();
|
||||
|
|
@ -37,7 +37,7 @@ public class StatsController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("message")]
|
||||
[SwaggerOperation(Summary = "메시지별 통계 조회", Description = "특정 메시지의 발송 통계를 조회합니다.")]
|
||||
[SwaggerOperation(Summary = "메시지별 통계 조회", Description = "특정 메시지의 발송 통계를 조회합니다. X-Service-Code 헤더 미지정 시 전체 서비스 통계를 조회합니다.")]
|
||||
public async Task<IActionResult> GetMessageStatAsync([FromBody] MessageStatRequestDto request)
|
||||
{
|
||||
var serviceId = GetOptionalServiceId();
|
||||
|
|
@ -46,7 +46,7 @@ public class StatsController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("hourly")]
|
||||
[SwaggerOperation(Summary = "시간대별 통계 조회", Description = "시간대별 발송 추이를 조회합니다.")]
|
||||
[SwaggerOperation(Summary = "시간대별 통계 조회", Description = "시간대별 발송 추이를 조회합니다. X-Service-Code 헤더 미지정 시 전체 서비스 통계를 조회합니다.")]
|
||||
public async Task<IActionResult> GetHourlyAsync([FromBody] HourlyStatRequestDto request)
|
||||
{
|
||||
var serviceId = GetOptionalServiceId();
|
||||
|
|
@ -55,7 +55,7 @@ public class StatsController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("device")]
|
||||
[SwaggerOperation(Summary = "디바이스 통계 조회", Description = "플랫폼/모델별 디바이스 분포를 조회합니다.")]
|
||||
[SwaggerOperation(Summary = "디바이스 통계 조회", Description = "플랫폼/모델별 디바이스 분포를 조회합니다. X-Service-Code 헤더 미지정 시 전체 서비스 통계를 조회합니다.")]
|
||||
public async Task<IActionResult> GetDeviceStatAsync()
|
||||
{
|
||||
var serviceId = GetOptionalServiceId();
|
||||
|
|
@ -64,7 +64,7 @@ public class StatsController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("export")]
|
||||
[SwaggerOperation(Summary = "통계 리포트 다운로드", Description = "일별/시간대별/플랫폼별 통계를 엑셀(.xlsx) 파일로 다운로드합니다.")]
|
||||
[SwaggerOperation(Summary = "통계 리포트 다운로드", Description = "일별/시간대별/플랫폼별 통계를 엑셀(.xlsx) 파일로 다운로드합니다. X-Service-Code 헤더 미지정 시 전체 서비스 통계를 조회합니다.")]
|
||||
public async Task<IActionResult> ExportReportAsync([FromBody] StatsExportRequestDto request)
|
||||
{
|
||||
var serviceId = GetOptionalServiceId();
|
||||
|
|
@ -74,7 +74,7 @@ public class StatsController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("failure")]
|
||||
[SwaggerOperation(Summary = "실패원인 통계 조회", Description = "실패 원인별 집계를 상위 N개로 조회합니다.")]
|
||||
[SwaggerOperation(Summary = "실패원인 통계 조회", Description = "실패 원인별 집계를 상위 N개로 조회합니다. X-Service-Code 헤더 미지정 시 전체 서비스 통계를 조회합니다.")]
|
||||
public async Task<IActionResult> GetFailureStatAsync([FromBody] FailureStatRequestDto request)
|
||||
{
|
||||
var serviceId = GetOptionalServiceId();
|
||||
|
|
@ -83,7 +83,7 @@ public class StatsController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("send-log")]
|
||||
[SwaggerOperation(Summary = "발송 상세 로그 조회", Description = "특정 메시지의 개별 디바이스별 발송 상세 로그를 조회합니다.")]
|
||||
[SwaggerOperation(Summary = "발송 상세 로그 조회", Description = "특정 메시지의 개별 디바이스별 발송 상세 로그를 조회합니다. X-Service-Code 헤더 미지정 시 전체 서비스 통계를 조회합니다.")]
|
||||
public async Task<IActionResult> GetSendLogDetailAsync([FromBody] SendLogDetailRequestDto request)
|
||||
{
|
||||
var serviceId = GetOptionalServiceId();
|
||||
|
|
|
|||
|
|
@ -16,14 +16,15 @@ public class SpmsHeaderOperationFilter : IOperationFilter
|
|||
operation.Parameters ??= new List<OpenApiParameter>();
|
||||
|
||||
// v1/in/* 중 X-Service-Code 대상 경로 판별
|
||||
var isStatsOrDeviceList = relativePath.StartsWith("v1/in/stats") ||
|
||||
relativePath == "v1/in/device/list";
|
||||
var isRequired = relativePath.StartsWith("v1/in/message") ||
|
||||
var isOptional = relativePath.StartsWith("v1/in/stats") ||
|
||||
relativePath == "v1/in/device/list" ||
|
||||
relativePath == "v1/in/message/list";
|
||||
var isRequired = (relativePath.StartsWith("v1/in/message") && !isOptional) ||
|
||||
relativePath.StartsWith("v1/in/push") ||
|
||||
relativePath.StartsWith("v1/in/file");
|
||||
var isDeviceNonList = relativePath.StartsWith("v1/in/device") && !isStatsOrDeviceList;
|
||||
var isDeviceNonList = relativePath.StartsWith("v1/in/device") && !isOptional;
|
||||
|
||||
if (isStatsOrDeviceList)
|
||||
if (isOptional)
|
||||
{
|
||||
operation.Parameters.Add(new OpenApiParameter
|
||||
{
|
||||
|
|
|
|||
|
|
@ -443,13 +443,13 @@ public class StatsService : IStatsService
|
|||
private static (DateOnly Start, DateOnly End) ParseDateRange(string startStr, string endStr)
|
||||
{
|
||||
if (!DateOnly.TryParseExact(startStr, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var start))
|
||||
throw new SpmsException(ErrorCodes.BadRequest, "start_date 형식이 올바르지 않습니다. (yyyy-MM-dd)", 400);
|
||||
throw new SpmsException(ErrorCodes.StatsDateRangeInvalid, "start_date 형식이 올바르지 않습니다. (yyyy-MM-dd)", 400);
|
||||
|
||||
if (!DateOnly.TryParseExact(endStr, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var end))
|
||||
throw new SpmsException(ErrorCodes.BadRequest, "end_date 형식이 올바르지 않습니다. (yyyy-MM-dd)", 400);
|
||||
throw new SpmsException(ErrorCodes.StatsDateRangeInvalid, "end_date 형식이 올바르지 않습니다. (yyyy-MM-dd)", 400);
|
||||
|
||||
if (start > end)
|
||||
throw new SpmsException(ErrorCodes.BadRequest, "start_date가 end_date보다 클 수 없습니다.", 400);
|
||||
throw new SpmsException(ErrorCodes.StatsDateRangeInvalid, "start_date가 end_date보다 클 수 없습니다.", 400);
|
||||
|
||||
return (start, end);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ public static class ErrorCodes
|
|||
public const string JobNotFound = "163";
|
||||
public const string JobAlreadyCompleted = "164";
|
||||
|
||||
// === Stats (7) ===
|
||||
public const string StatsDateRangeInvalid = "171";
|
||||
public const string StatsServiceScopeInvalid = "172";
|
||||
|
||||
// === File (8) ===
|
||||
public const string FileNotFound = "181";
|
||||
public const string FileTypeNotAllowed = "182";
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user