- Domain: NotificationCategory enum, Notification entity, INotificationRepository - Infrastructure: NotificationConfiguration, NotificationRepository, AppDbContext/DI 등록 - Migration: AddNotificationTable 생성 및 적용 - Application: DTO 7개, INotificationService, NotificationService, DI 등록 - API: NotificationController (summary, list, read, read-all) Closes #247
69 lines
2.8 KiB
C#
69 lines
2.8 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Swashbuckle.AspNetCore.Annotations;
|
|
using SPMS.Application.DTOs.Notification;
|
|
using SPMS.Application.Interfaces;
|
|
using SPMS.Domain.Common;
|
|
using SPMS.Domain.Exceptions;
|
|
|
|
namespace SPMS.API.Controllers;
|
|
|
|
[ApiController]
|
|
[Route("v1/in/notification")]
|
|
[Authorize]
|
|
[ApiExplorerSettings(GroupName = "notification")]
|
|
public class NotificationController : ControllerBase
|
|
{
|
|
private readonly INotificationService _notificationService;
|
|
|
|
public NotificationController(INotificationService notificationService)
|
|
{
|
|
_notificationService = notificationService;
|
|
}
|
|
|
|
[HttpPost("summary")]
|
|
[SwaggerOperation(Summary = "알림 요약 조회", Description = "최근 N건의 알림과 미읽 건수를 반환합니다. 헤더 뱃지용.")]
|
|
public async Task<IActionResult> GetSummaryAsync([FromBody] NotificationSummaryRequestDto request)
|
|
{
|
|
var adminId = GetAdminId();
|
|
var result = await _notificationService.GetSummaryAsync(adminId, request);
|
|
return Ok(ApiResponse<NotificationSummaryResponseDto>.Success(result));
|
|
}
|
|
|
|
[HttpPost("list")]
|
|
[SwaggerOperation(Summary = "알림 목록 조회", Description = "알림 목록을 페이지 단위로 조회합니다. 카테고리/기간/읽음 필터를 지원합니다.")]
|
|
public async Task<IActionResult> GetListAsync([FromBody] NotificationListRequestDto request)
|
|
{
|
|
var adminId = GetAdminId();
|
|
var result = await _notificationService.GetListAsync(adminId, request);
|
|
return Ok(ApiResponse<NotificationListResponseDto>.Success(result));
|
|
}
|
|
|
|
[HttpPost("read")]
|
|
[SwaggerOperation(Summary = "알림 읽음 처리", Description = "단건 알림을 읽음 처리합니다. 이미 읽은 알림은 무시(멱등).")]
|
|
public async Task<IActionResult> MarkAsReadAsync([FromBody] NotificationReadRequestDto request)
|
|
{
|
|
var adminId = GetAdminId();
|
|
var result = await _notificationService.MarkAsReadAsync(adminId, request);
|
|
return Ok(ApiResponse<NotificationReadResponseDto>.Success(result));
|
|
}
|
|
|
|
[HttpPost("read-all")]
|
|
[SwaggerOperation(Summary = "알림 전체 읽음", Description = "해당 관리자의 모든 미읽 알림을 일괄 읽음 처리합니다.")]
|
|
public async Task<IActionResult> MarkAllAsReadAsync()
|
|
{
|
|
var adminId = GetAdminId();
|
|
var result = await _notificationService.MarkAllAsReadAsync(adminId);
|
|
return Ok(ApiResponse<NotificationReadResponseDto>.Success(result));
|
|
}
|
|
|
|
private long GetAdminId()
|
|
{
|
|
var adminIdClaim = User.FindFirst("adminId")?.Value;
|
|
if (string.IsNullOrEmpty(adminIdClaim) || !long.TryParse(adminIdClaim, out var adminId))
|
|
throw new SpmsException(ErrorCodes.Unauthorized, "인증 정보가 올바르지 않습니다.", 401);
|
|
|
|
return adminId;
|
|
}
|
|
}
|