diff --git a/item-service/src/main/java/com/comatching/item/domain/notice/dto/AdminNoticeResponse.java b/item-service/src/main/java/com/comatching/item/domain/notice/dto/AdminNoticeResponse.java new file mode 100644 index 0000000..6b390ea --- /dev/null +++ b/item-service/src/main/java/com/comatching/item/domain/notice/dto/AdminNoticeResponse.java @@ -0,0 +1,29 @@ +package com.comatching.item.domain.notice.dto; + +import java.time.LocalDateTime; + +import com.comatching.item.domain.notice.entity.Notice; + +public record AdminNoticeResponse( + Long noticeId, + String title, + String content, + LocalDateTime startTime, + LocalDateTime endTime, + boolean active +) { + public static AdminNoticeResponse from(Notice notice, LocalDateTime currentTime) { + return new AdminNoticeResponse( + notice.getId(), + notice.getTitle(), + notice.getContent(), + notice.getStartTime(), + notice.getEndTime(), + isActive(notice, currentTime) + ); + } + + private static boolean isActive(Notice notice, LocalDateTime currentTime) { + return !notice.getStartTime().isAfter(currentTime) && !notice.getEndTime().isBefore(currentTime); + } +} diff --git a/item-service/src/main/java/com/comatching/item/domain/notice/repository/NoticeRepository.java b/item-service/src/main/java/com/comatching/item/domain/notice/repository/NoticeRepository.java index 99f1784..f5a7760 100644 --- a/item-service/src/main/java/com/comatching/item/domain/notice/repository/NoticeRepository.java +++ b/item-service/src/main/java/com/comatching/item/domain/notice/repository/NoticeRepository.java @@ -9,6 +9,8 @@ public interface NoticeRepository extends JpaRepository { + List findAllByOrderByStartTimeDescIdDesc(); + List findAllByStartTimeLessThanEqualAndEndTimeGreaterThanEqualOrderByStartTimeDescIdDesc( LocalDateTime currentTime, LocalDateTime currentTime2 diff --git a/item-service/src/main/java/com/comatching/item/domain/notice/service/NoticeService.java b/item-service/src/main/java/com/comatching/item/domain/notice/service/NoticeService.java index 492a3cf..e0505dc 100644 --- a/item-service/src/main/java/com/comatching/item/domain/notice/service/NoticeService.java +++ b/item-service/src/main/java/com/comatching/item/domain/notice/service/NoticeService.java @@ -2,6 +2,7 @@ import java.util.List; +import com.comatching.item.domain.notice.dto.AdminNoticeResponse; import com.comatching.item.domain.notice.dto.ActiveNoticeResponse; import com.comatching.item.domain.notice.dto.NoticeCreateRequest; import com.comatching.item.domain.notice.dto.NoticeUpdateRequest; @@ -15,4 +16,6 @@ public interface NoticeService { void deleteNotice(Long noticeId); List getActiveNotices(); + + List getAdminNotices(); } diff --git a/item-service/src/main/java/com/comatching/item/domain/notice/service/NoticeServiceImpl.java b/item-service/src/main/java/com/comatching/item/domain/notice/service/NoticeServiceImpl.java index fcd01b7..0797afc 100644 --- a/item-service/src/main/java/com/comatching/item/domain/notice/service/NoticeServiceImpl.java +++ b/item-service/src/main/java/com/comatching/item/domain/notice/service/NoticeServiceImpl.java @@ -8,6 +8,7 @@ import com.comatching.common.exception.BusinessException; import com.comatching.common.exception.code.GeneralErrorCode; +import com.comatching.item.domain.notice.dto.AdminNoticeResponse; import com.comatching.item.domain.notice.dto.ActiveNoticeResponse; import com.comatching.item.domain.notice.dto.NoticeCreateRequest; import com.comatching.item.domain.notice.dto.NoticeUpdateRequest; @@ -62,6 +63,16 @@ public List getActiveNotices() { .toList(); } + @Override + @Transactional(readOnly = true) + public List getAdminNotices() { + LocalDateTime currentTime = LocalDateTime.now(); + return noticeRepository.findAllByOrderByStartTimeDescIdDesc() + .stream() + .map(notice -> AdminNoticeResponse.from(notice, currentTime)) + .toList(); + } + private Notice findNoticeOrThrow(Long noticeId) { return noticeRepository.findById(noticeId) .orElseThrow(() -> new BusinessException(GeneralErrorCode.NOT_FOUND, "공지사항을 찾을 수 없습니다.")); diff --git a/item-service/src/main/java/com/comatching/item/infra/controller/NoticeController.java b/item-service/src/main/java/com/comatching/item/infra/controller/NoticeController.java index 844b586..4251032 100644 --- a/item-service/src/main/java/com/comatching/item/infra/controller/NoticeController.java +++ b/item-service/src/main/java/com/comatching/item/infra/controller/NoticeController.java @@ -17,6 +17,7 @@ import com.comatching.common.domain.enums.MemberRole; import com.comatching.common.dto.member.MemberInfo; import com.comatching.common.dto.response.ApiResponse; +import com.comatching.item.domain.notice.dto.AdminNoticeResponse; import com.comatching.item.domain.notice.dto.ActiveNoticeResponse; import com.comatching.item.domain.notice.dto.NoticeCreateRequest; import com.comatching.item.domain.notice.dto.NoticeUpdateRequest; @@ -35,6 +36,15 @@ public class NoticeController { private final NoticeService noticeService; + @RequireRole(MemberRole.ROLE_ADMIN) + @Operation(summary = "관리자 공지사항 목록 조회", description = "관리자가 등록된 전체 공지사항을 노출 시작시간 내림차순으로 조회합니다.") + @GetMapping("/admin/notices") + public ResponseEntity>> getAdminNotices( + @CurrentMember MemberInfo memberInfo + ) { + return ResponseEntity.ok(ApiResponse.ok(noticeService.getAdminNotices())); + } + @RequireRole(MemberRole.ROLE_ADMIN) @Operation(summary = "공지사항 등록", description = "관리자가 제목, 내용, 시작시간, 종료시간으로 공지사항을 등록합니다.") @PostMapping("/admin/notices") diff --git a/item-service/src/test/java/com/comatching/item/domain/notice/service/NoticeServiceImplTest.java b/item-service/src/test/java/com/comatching/item/domain/notice/service/NoticeServiceImplTest.java index 1b53ae3..3666840 100644 --- a/item-service/src/test/java/com/comatching/item/domain/notice/service/NoticeServiceImplTest.java +++ b/item-service/src/test/java/com/comatching/item/domain/notice/service/NoticeServiceImplTest.java @@ -21,6 +21,7 @@ import com.comatching.common.exception.BusinessException; import com.comatching.common.exception.code.GeneralErrorCode; +import com.comatching.item.domain.notice.dto.AdminNoticeResponse; import com.comatching.item.domain.notice.dto.ActiveNoticeResponse; import com.comatching.item.domain.notice.dto.NoticeCreateRequest; import com.comatching.item.domain.notice.dto.NoticeUpdateRequest; @@ -122,6 +123,40 @@ void shouldReturnActiveNotices() { assertThat(responses.get(0).content()).isEqualTo("한 줄\n두 줄"); } + @Test + @DisplayName("관리자 공지사항 목록 조회 시 전체 공지사항과 활성 여부를 반환한다") + void shouldReturnAdminNotices() { + // given + LocalDateTime now = LocalDateTime.now(); + Notice activeNotice = Notice.builder() + .title("활성 공지") + .content("활성 내용") + .startTime(now.minusDays(1)) + .endTime(now.plusDays(1)) + .build(); + ReflectionTestUtils.setField(activeNotice, "id", 11L); + + Notice expiredNotice = Notice.builder() + .title("종료 공지") + .content("종료 내용") + .startTime(now.minusDays(3)) + .endTime(now.minusDays(2)) + .build(); + ReflectionTestUtils.setField(expiredNotice, "id", 12L); + + given(noticeRepository.findAllByOrderByStartTimeDescIdDesc()) + .willReturn(List.of(activeNotice, expiredNotice)); + + // when + List responses = noticeService.getAdminNotices(); + + // then + assertThat(responses).hasSize(2); + assertThat(responses).extracting(AdminNoticeResponse::noticeId).containsExactly(11L, 12L); + assertThat(responses).extracting(AdminNoticeResponse::title).containsExactly("활성 공지", "종료 공지"); + assertThat(responses).extracting(AdminNoticeResponse::active).containsExactly(true, false); + } + @Test @DisplayName("관리자 공지사항 수정 시 제목, 내용, 노출 기간을 변경한다") void shouldUpdateNotice() {