diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index 69b0039..f3874f2 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -599,6 +599,12 @@ operation::notification/settings-get-success[snippets='http-request,request-head operation::notification/settings-update-success[snippets='http-request,request-headers,request-fields,http-response'] +== *5. 알림 읽기 API* + +=== *1-1* 성공 + +operation::notification/notification-read-success[snippets='http-request,request-headers,request-fields,http-response,response-fields'] + [[푸시-API]] == *1. 푸시 토큰 전송 API* diff --git a/src/main/java/com/polzzak/domain/notification/controller/NotificationController.java b/src/main/java/com/polzzak/domain/notification/controller/NotificationController.java index 17ccaba..dba2b33 100644 --- a/src/main/java/com/polzzak/domain/notification/controller/NotificationController.java +++ b/src/main/java/com/polzzak/domain/notification/controller/NotificationController.java @@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -14,7 +15,9 @@ import com.polzzak.domain.notification.dto.NotificationResponseWithCount; import com.polzzak.domain.notification.dto.NotificationSettingDto; +import com.polzzak.domain.notification.dto.ReadNotificationId; import com.polzzak.domain.notification.dto.UpdateNotificationSetting; +import com.polzzak.domain.notification.entity.Notification; import com.polzzak.domain.notification.service.NotificationService; import com.polzzak.global.common.ApiResponse; import com.polzzak.global.security.LoginId; @@ -47,6 +50,14 @@ public ResponseEntity> deleteNotifications( return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); } + @PostMapping("/read") + public ResponseEntity> readNotification( + final @LoginId Long memberId, + final @RequestBody ReadNotificationId readNotificationId) { + notificationService.changeNotificationStatus(readNotificationId.notificationId(), Notification.Status.READ); + return ResponseEntity.ok(ApiResponse.ok(notificationService.getUnreadNotificationCount(memberId))); + } + @GetMapping("/settings") public ResponseEntity> getNotificationSettings(final @LoginId Long memberId) { return ResponseEntity.ok(ApiResponse.ok(notificationService.getNotificationSetting(memberId))); diff --git a/src/main/java/com/polzzak/domain/notification/dto/ReadNotificationId.java b/src/main/java/com/polzzak/domain/notification/dto/ReadNotificationId.java new file mode 100644 index 0000000..da3b4f6 --- /dev/null +++ b/src/main/java/com/polzzak/domain/notification/dto/ReadNotificationId.java @@ -0,0 +1,4 @@ +package com.polzzak.domain.notification.dto; + +public record ReadNotificationId(long notificationId) { +} diff --git a/src/main/java/com/polzzak/domain/notification/repository/NotificationRepository.java b/src/main/java/com/polzzak/domain/notification/repository/NotificationRepository.java index 95188eb..6c8c1f6 100644 --- a/src/main/java/com/polzzak/domain/notification/repository/NotificationRepository.java +++ b/src/main/java/com/polzzak/domain/notification/repository/NotificationRepository.java @@ -21,6 +21,10 @@ Slice findNotificationsByReceiverIdAndIdLessThan(final long member @Query("UPDATE Notification n SET n.status = :status WHERE n.id IN :ids") void updateStatusByIds(@Param("ids") List ids, @Param("status") Notification.Status status); + @Modifying + @Query("UPDATE Notification n SET n.status = :status WHERE n.id = :id") + void updateStatusById(@Param("id") long id, @Param("status") Notification.Status status); + @Query(nativeQuery = true, value = """ SELECT n.id FROM notification n diff --git a/src/main/java/com/polzzak/domain/notification/service/NotificationService.java b/src/main/java/com/polzzak/domain/notification/service/NotificationService.java index c4db70e..119e0a6 100644 --- a/src/main/java/com/polzzak/domain/notification/service/NotificationService.java +++ b/src/main/java/com/polzzak/domain/notification/service/NotificationService.java @@ -71,6 +71,10 @@ public NotificationResponseWithCount getNotificationsAndChangeStatus(final Long return NotificationResponseWithCount.from(notificationResponse, count); } + public int getUnreadNotificationCount(final long memberId) { + return notificationRepository.countByStatusIsUnRead(memberId); + } + @Transactional public void changeRequestNotificationStatus(final Long senderId, final Long receiverId, final Notification.Status status) { @@ -78,6 +82,11 @@ public void changeRequestNotificationStatus(final Long senderId, final Long rece notificationRepository.updateStatusByIds(List.of(notificationId), status); } + @Transactional + public void changeNotificationStatus(final long notificationId, final Notification.Status status) { + notificationRepository.updateStatusById(notificationId, status); + } + @Transactional public void deleteNotifications(final List notificationIds) { List notifications = notificationRepository.findByIdIn(notificationIds); diff --git a/src/test/java/com/polzzak/domain/notification/controller/NotificationControllerTest.java b/src/test/java/com/polzzak/domain/notification/controller/NotificationControllerTest.java index 28aad3e..f46ace7 100644 --- a/src/test/java/com/polzzak/domain/notification/controller/NotificationControllerTest.java +++ b/src/test/java/com/polzzak/domain/notification/controller/NotificationControllerTest.java @@ -21,6 +21,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; +import com.polzzak.domain.notification.dto.ReadNotificationId; import com.polzzak.domain.notification.service.NotificationService; import com.polzzak.domain.user.service.UserService; import com.polzzak.support.NotificationFixtures; @@ -109,6 +110,33 @@ void deleteNotificationTest() throws Exception { ))); } + @Test + @DisplayName("알림 읽기 테스트") + void readNotificationTest() throws Exception { + doNothing().when(notificationService).changeNotificationStatus(anyLong(), any()); + when(notificationService.getUnreadNotificationCount(anyLong())).thenReturn(12); + + mockMvc.perform( + post(BASE_URL + "/read") + .header(HttpHeaders.AUTHORIZATION, TOKEN_TYPE + USER_ACCESS_TOKEN) + .contentType(MediaType.APPLICATION_JSON) + .content(objectToString(new ReadNotificationId(45)))) + .andDo(print()) + .andExpect(status().isOk()) + .andDo(document("notification/notification-read-success", + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("엑세스 토큰") + ), + requestFields( + fieldWithPath("notificationId").description("읽을 알림 id") + ), + responseFields( + fieldWithPath("code").description("응답 코드"), + fieldWithPath("messages").description("응답 메시지"), + fieldWithPath("data").description("남은 안 읽은 알림 수") + ))); + } + @Test @DisplayName("알림 설정 조회 테스트") void getNotificationSettings() throws Exception {