diff --git a/src/main/java/clap/server/adapter/inbound/web/notification/ManagementNotificationController.java b/src/main/java/clap/server/adapter/inbound/web/notification/ManagementNotificationController.java new file mode 100644 index 00000000..d4d37dc1 --- /dev/null +++ b/src/main/java/clap/server/adapter/inbound/web/notification/ManagementNotificationController.java @@ -0,0 +1,30 @@ +package clap.server.adapter.inbound.web.notification; + +import clap.server.application.port.inbound.notification.UpdateNotificationUsecase; +import clap.server.common.annotation.architecture.WebAdapter; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "알림 읽음 처리") +@WebAdapter +@RestController +@RequestMapping("/api/notification") +@RequiredArgsConstructor +public class ManagementNotificationController { + + private final UpdateNotificationUsecase updateNotificationUsecase; + + @Operation(summary = "알림 목록에서 한 개 눌렀을 때 읽음 처리") + @Parameter(name = "notificationId", description = "알림 고유 ID", required = true, in = ParameterIn.PATH) + @PatchMapping("/{notificationId}") + public void updateNotificationIsRead(@PathVariable Long notificationId) { + updateNotificationUsecase.updateNotification(notificationId); + } +} diff --git a/src/main/java/clap/server/adapter/outbound/persistense/NotificationPersistenceAdapter.java b/src/main/java/clap/server/adapter/outbound/persistense/NotificationPersistenceAdapter.java index 8aad00a0..5e94aa6c 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/NotificationPersistenceAdapter.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/NotificationPersistenceAdapter.java @@ -12,6 +12,9 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import java.util.List; +import java.util.Optional; + @PersistenceAdapter @RequiredArgsConstructor public class NotificationPersistenceAdapter implements LoadNotificationPort, CommandNotificationPort { @@ -20,6 +23,12 @@ public class NotificationPersistenceAdapter implements LoadNotificationPort, Com private final NotificationPersistenceMapper notificationPersistenceMapper; + @Override + public Optional findById(Long notificationId) { + return notificationRepository.findById(notificationId) + .map(notificationPersistenceMapper::toDomain); + } + @Override public Page findAllByReceiverId(Long receiverId, Pageable pageable) { Page notificationList = notificationRepository.findAllByReceiver_MemberId(receiverId, pageable) diff --git a/src/main/java/clap/server/application/port/inbound/notification/UpdateNotificationUsecase.java b/src/main/java/clap/server/application/port/inbound/notification/UpdateNotificationUsecase.java new file mode 100644 index 00000000..91c124fe --- /dev/null +++ b/src/main/java/clap/server/application/port/inbound/notification/UpdateNotificationUsecase.java @@ -0,0 +1,5 @@ +package clap.server.application.port.inbound.notification; + +public interface UpdateNotificationUsecase { + void updateNotification(Long notificationId); +} diff --git a/src/main/java/clap/server/application/port/outbound/notification/LoadNotificationPort.java b/src/main/java/clap/server/application/port/outbound/notification/LoadNotificationPort.java index 46602d90..3704ee67 100644 --- a/src/main/java/clap/server/application/port/outbound/notification/LoadNotificationPort.java +++ b/src/main/java/clap/server/application/port/outbound/notification/LoadNotificationPort.java @@ -1,10 +1,18 @@ package clap.server.application.port.outbound.notification; import clap.server.adapter.inbound.web.dto.notification.FindNotificationListResponse; +import clap.server.adapter.outbound.persistense.entity.notification.NotificationEntity; +import clap.server.domain.model.notification.Notification; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import java.util.List; +import java.util.Optional; + public interface LoadNotificationPort { + + Optional findById(Long notificationId); + Page findAllByReceiverId(Long receiverId, Pageable pageable); } \ No newline at end of file diff --git a/src/main/java/clap/server/application/service/notification/ReadNotificationService.java b/src/main/java/clap/server/application/service/notification/ReadNotificationService.java new file mode 100644 index 00000000..ed4ff10b --- /dev/null +++ b/src/main/java/clap/server/application/service/notification/ReadNotificationService.java @@ -0,0 +1,29 @@ +package clap.server.application.service.notification; + +import clap.server.application.port.inbound.notification.UpdateNotificationUsecase; +import clap.server.application.port.outbound.notification.CommandNotificationPort; +import clap.server.application.port.outbound.notification.LoadNotificationPort; +import clap.server.common.annotation.architecture.ApplicationService; +import clap.server.domain.model.notification.Notification; +import clap.server.exception.ApplicationException; +import clap.server.exception.code.NotificationErrorCode; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@ApplicationService +@RequiredArgsConstructor +public class ReadNotificationService implements UpdateNotificationUsecase { + + private final LoadNotificationPort loadNotificationPort; + private final CommandNotificationPort commandNotificationPort; + + + @Transactional + @Override + public void updateNotification(Long notificationId) { + Notification notification = loadNotificationPort.findById(notificationId) + .orElseThrow(() -> new ApplicationException(NotificationErrorCode.NOTIFICATION_NOT_FOUND)); + notification.updateNotificationIsRead(); + commandNotificationPort.save(notification); + } +} diff --git a/src/main/java/clap/server/domain/model/notification/Notification.java b/src/main/java/clap/server/domain/model/notification/Notification.java index 91ae10f9..46bd4f26 100644 --- a/src/main/java/clap/server/domain/model/notification/Notification.java +++ b/src/main/java/clap/server/domain/model/notification/Notification.java @@ -34,4 +34,17 @@ public Notification(Task task, NotificationType type, Member receiver, String me this.message = message; this.isRead = false; } + + public void updateNotificationIsRead() { + this.isRead = true; + } + + public static Notification createTaskNotification(Task task, Member reviewer, NotificationType type) { + return Notification.builder() + .task(task) + .type(type) + .receiver(reviewer) + .message(null) + .build(); + } } diff --git a/src/main/java/clap/server/exception/code/NotificationErrorCode.java b/src/main/java/clap/server/exception/code/NotificationErrorCode.java new file mode 100644 index 00000000..f6805e61 --- /dev/null +++ b/src/main/java/clap/server/exception/code/NotificationErrorCode.java @@ -0,0 +1,17 @@ +package clap.server.exception.code; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum NotificationErrorCode implements BaseErrorCode { + + NOTIFICATION_NOT_FOUND(HttpStatus.NOT_FOUND, "NOTIFICATION_001", "알림을 찾을 수 없습니다"), + ; + + private final HttpStatus httpStatus; + private final String customCode; + private final String message; +}