diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/controller/query/NoticeQueryController.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/controller/query/NoticeQueryController.java index ff7c0df..3cae7be 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/controller/query/NoticeQueryController.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/controller/query/NoticeQueryController.java @@ -16,6 +16,7 @@ import org.withtime.be.withtimebe.domain.notice.dto.request.NoticeRequestDTO; import org.withtime.be.withtimebe.domain.notice.dto.response.NoticeResponseDTO; import org.withtime.be.withtimebe.domain.notice.entity.Notice; +import org.withtime.be.withtimebe.domain.notice.entity.enums.NoticeCategory; import org.withtime.be.withtimebe.domain.notice.service.query.NoticeQueryService; import org.withtime.be.withtimebe.global.annotation.SwaggerPageable; import org.withtime.be.withtimebe.global.security.annotation.AuthenticatedMember; @@ -47,10 +48,9 @@ public class NoticeQueryController { @GetMapping public DefaultResponse findNoticeList( @PageableDefault(page = 0, size = 10) Pageable pageable, - @RequestParam String noticeCategory + @RequestParam NoticeCategory noticeCategory ) { - NoticeRequestDTO.FindNoticeList request = NoticeConverter.toFindNoticeList(pageable, noticeCategory); - Page result = noticeQueryService.findNoticeList(request); + Page result = noticeQueryService.findNoticeList(pageable, noticeCategory); NoticeResponseDTO.NoticeList response = NoticeConverter.toNoticeList(result); return DefaultResponse.ok(response); } @@ -70,10 +70,9 @@ public DefaultResponse findNoticeList( public DefaultResponse findNoticeListByKeyword( @PageableDefault(page = 0, size = 10) Pageable pageable, @RequestParam String keyword, - @RequestParam String noticeCategory + @RequestParam NoticeCategory noticeCategory ) { - NoticeRequestDTO.FindNoticeListByKeyword request = NoticeConverter.toFindNoticeListByKeyword(pageable, keyword, noticeCategory); - Page result = noticeQueryService.findNoticeListByKeyword(request); + Page result = noticeQueryService.findNoticeListByKeyword(pageable, keyword, noticeCategory); NoticeResponseDTO.NoticeList response = NoticeConverter.toNoticeList(result); return DefaultResponse.ok(response); } @@ -97,9 +96,8 @@ public DefaultResponse findNoticeDetail( @PathVariable("noticeId") Long noticeId, @AuthenticatedMember Member member ) { - NoticeRequestDTO.FindNoticeDetail request = NoticeConverter.toFindNoticeDetail(noticeId, member); - Notice result = noticeQueryService.findNoticeDetail(request); - NoticeResponseDTO.NoticeDetail response = NoticeConverter.toNoticeDetail(result, member); + Notice result = noticeQueryService.findNoticeDetail(noticeId, member); + NoticeResponseDTO.NoticeDetail response = NoticeConverter.toNoticeDetail(result); return DefaultResponse.ok(response); } @@ -121,10 +119,9 @@ public DefaultResponse findNoticeDetail( @GetMapping("/trash") public DefaultResponse findTrashNoticeList( @PageableDefault(page = 0, size = 10) Pageable pageable, - @RequestParam String noticeCategory + @RequestParam NoticeCategory noticeCategory ) { - NoticeRequestDTO.FindNoticeList request = NoticeConverter.toFindNoticeList(pageable, noticeCategory); - Page result = noticeQueryService.findTrashNoticeList(request); + Page result = noticeQueryService.findTrashNoticeList(pageable, noticeCategory); NoticeResponseDTO.NoticeList response = NoticeConverter.toNoticeList(result); return DefaultResponse.ok(response); } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeCategoryConverter.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeCategoryConverter.java new file mode 100644 index 0000000..5d083ca --- /dev/null +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeCategoryConverter.java @@ -0,0 +1,17 @@ +package org.withtime.be.withtimebe.domain.notice.converter; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.util.StringUtils; +import org.withtime.be.withtimebe.domain.notice.entity.enums.NoticeCategory; +import org.withtime.be.withtimebe.global.error.code.NoticeErrorCode; +import org.withtime.be.withtimebe.global.error.exception.NoticeException; + +public class NoticeCategoryConverter implements Converter { + + @Override + public NoticeCategory convert(String source) { + if(!StringUtils.hasText(source)) throw new NoticeException(NoticeErrorCode.NOTICE_CATEGORY_EMPTY); + return NoticeCategory.findNoticeCategory(source); + } +} + diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeConverter.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeConverter.java index 5d7276c..54a5d23 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeConverter.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeConverter.java @@ -15,50 +15,6 @@ public class NoticeConverter { - // Request DTO : 전체 조회 (Controller -> Service) - public static NoticeRequestDTO.FindNoticeList toFindNoticeList(Pageable pageable, String type) { - - NoticeCategory noticeCategory; - - try { - noticeCategory = NoticeCategory.valueOf(type); - } catch (IllegalArgumentException e) { - throw new NoticeException(NoticeErrorCode.NOTICE_CATEGORY_NOT_FOUND); - } - - return NoticeRequestDTO.FindNoticeList.builder() - .pageable(pageable) - .noticeCategory(noticeCategory) - .build(); - } - - // Request DTO : 검색어 전체 조회 (Controller -> Service) - public static NoticeRequestDTO.FindNoticeListByKeyword toFindNoticeListByKeyword(Pageable pageable, String keyword, String type) { - - NoticeCategory noticeCategory; - - try { - noticeCategory = NoticeCategory.valueOf(type); - } catch (IllegalArgumentException e) { - throw new NoticeException(NoticeErrorCode.NOTICE_CATEGORY_NOT_FOUND); - } - - return NoticeRequestDTO.FindNoticeListByKeyword.builder() - .pageable(pageable) - .keyword(keyword) - .noticeCategory(noticeCategory) - .build(); - } - - // Request : 상세 조회 요청 (Controller -> Service) DTO - public static NoticeRequestDTO.FindNoticeDetail toFindNoticeDetail(Long noticeId, Member member) { - - return NoticeRequestDTO.FindNoticeDetail.builder() - .noticeId(noticeId) - .member(member) - .build(); - } - // Response DTO : NoticeResponseDTO.NoticeList public static NoticeResponseDTO.NoticeList toNoticeList(Page noticePage) { @@ -87,16 +43,13 @@ public static NoticeResponseDTO.Notice toNotice(Notice notice) { } // Response : NoticeDetail(DTO)로 변환 - public static NoticeResponseDTO.NoticeDetail toNoticeDetail(Notice notice, Member member) { - - boolean hasAdminAuth = member != null && member.getRole().equals(Role.ADMIN); + public static NoticeResponseDTO.NoticeDetail toNoticeDetail(Notice notice) { return NoticeResponseDTO.NoticeDetail.builder() .noticeId(notice.getId()) .title(notice.getTitle()) .content(notice.getContent()) .isPinned(notice.getIsPinned()) - .hasAdminAuth(hasAdminAuth) .createdAt(notice.getCreatedAt()) .build(); } @@ -108,6 +61,7 @@ public static Notice toNoticeEntity(NoticeRequestDTO.CreateNotice request, Membe .title(request.title()) .content(request.content()) .isPinned(request.isPinned()) + .noticeCategory(request.noticeCategory()) .build(); } } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/request/NoticeRequestDTO.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/request/NoticeRequestDTO.java index b6e28b5..f3aceaa 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/request/NoticeRequestDTO.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/request/NoticeRequestDTO.java @@ -10,32 +10,15 @@ public record NoticeRequestDTO() { - @Builder - public record FindNoticeList( - Pageable pageable, // 게시글 식별자 값 - NoticeCategory noticeCategory // 게시글 유형 - ) {} - - @Builder - public record FindNoticeListByKeyword( - Pageable pageable, // 게시글 식별자 값 - String keyword, // 검색 키워드 - NoticeCategory noticeCategory // 게시글 유형 - ) {} - - @Builder - public record FindNoticeDetail( - Long noticeId, - Member member - ) {} - public record CreateNotice( @NotBlank(message = "제목을 입력해주세요") String title, @NotBlank(message = "내용을 입력해주세요") String content, @NotNull(message = "상단 고정 여부를 결정해주세요") - Boolean isPinned + Boolean isPinned, + @NotNull(message = "공지사항 유형을 입력해주세요") + NoticeCategory noticeCategory ) {} public record UpdateNotice ( diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/response/NoticeResponseDTO.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/response/NoticeResponseDTO.java index e4fc557..1c8de43 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/response/NoticeResponseDTO.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/response/NoticeResponseDTO.java @@ -30,7 +30,6 @@ public record NoticeDetail( String title, // 게시글 제목 String content, // 게시글 내용 Boolean isPinned, // 고정 여부 - Boolean hasAdminAuth, // 어드민 여부 LocalDateTime createdAt // 생성 날짜 ) {} } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java index a05920f..c12f003 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java @@ -1,6 +1,24 @@ package org.withtime.be.withtimebe.domain.notice.entity.enums; +import java.util.Arrays; + +import org.withtime.be.withtimebe.global.error.code.NoticeErrorCode; +import org.withtime.be.withtimebe.global.error.exception.NoticeException; + +import com.fasterxml.jackson.annotation.JsonCreator; + public enum NoticeCategory { SERVICE, - SYSTEM + SYSTEM; + + // @RequestBody + @JsonCreator + public static NoticeCategory findNoticeCategory(String name) { + return Arrays.stream(values()) + .filter(type -> type.name().equalsIgnoreCase(name)) + .findAny() + .orElseThrow( + () -> new NoticeException(NoticeErrorCode.NOTICE_CATEGORY_NOT_FOUND) + ); + } } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryService.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryService.java index bc6bd86..3b0a933 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryService.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryService.java @@ -1,12 +1,15 @@ package org.withtime.be.withtimebe.domain.notice.service.query; import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.withtime.be.withtimebe.domain.member.entity.Member; import org.withtime.be.withtimebe.domain.notice.dto.request.NoticeRequestDTO; import org.withtime.be.withtimebe.domain.notice.entity.Notice; +import org.withtime.be.withtimebe.domain.notice.entity.enums.NoticeCategory; public interface NoticeQueryService { - Page findNoticeList(NoticeRequestDTO.FindNoticeList request); - Page findNoticeListByKeyword(NoticeRequestDTO.FindNoticeListByKeyword request); - Page findTrashNoticeList(NoticeRequestDTO.FindNoticeList request); - Notice findNoticeDetail(NoticeRequestDTO.FindNoticeDetail request); + Page findNoticeList(Pageable pageable, NoticeCategory noticeCategory); + Page findNoticeListByKeyword(Pageable pageable, String keyword, NoticeCategory noticeCategory); + Page findTrashNoticeList(Pageable pageable, NoticeCategory noticeCategory); + Notice findNoticeDetail(Long noticeId, Member member); } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryServiceImpl.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryServiceImpl.java index 4846417..0baac4a 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryServiceImpl.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryServiceImpl.java @@ -1,12 +1,15 @@ package org.withtime.be.withtimebe.domain.notice.service.query; import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.withtime.be.withtimebe.domain.member.entity.Member; import org.withtime.be.withtimebe.domain.member.entity.enums.Role; +import org.withtime.be.withtimebe.domain.member.repository.MemberRepository; import org.withtime.be.withtimebe.domain.notice.dto.request.NoticeRequestDTO; import org.withtime.be.withtimebe.domain.notice.entity.Notice; +import org.withtime.be.withtimebe.domain.notice.entity.enums.NoticeCategory; import org.withtime.be.withtimebe.domain.notice.repository.NoticeRepository; import org.withtime.be.withtimebe.global.error.code.AuthErrorCode; import org.withtime.be.withtimebe.global.error.code.NoticeErrorCode; @@ -23,32 +26,31 @@ public class NoticeQueryServiceImpl implements NoticeQueryService { private final NoticeRepository noticeRepository; @Override - public Page findNoticeList(NoticeRequestDTO.FindNoticeList request) { + public Page findNoticeList(Pageable pageable, NoticeCategory noticeCategory) { return noticeRepository.findNoticeListByNoticeCategory( - request.noticeCategory(), request.pageable()); + noticeCategory, pageable); } @Override - public Page findNoticeListByKeyword(NoticeRequestDTO.FindNoticeListByKeyword request) { + public Page findNoticeListByKeyword(Pageable pageable, String keyword, NoticeCategory noticeCategory) { return noticeRepository.findNoticeListByNoticeCategoryAndKeyword( - request.noticeCategory(), request.keyword(), request.pageable()); + noticeCategory, keyword, pageable); } @Override - public Page findTrashNoticeList(NoticeRequestDTO.FindNoticeList request) { + public Page findTrashNoticeList(Pageable pageable, NoticeCategory noticeCategory) { return noticeRepository.findTrashNoticeListByNoticeCategory( - request.noticeCategory(), request.pageable() + noticeCategory, pageable ); } @Override - public Notice findNoticeDetail(NoticeRequestDTO.FindNoticeDetail request) { + public Notice findNoticeDetail(Long noticeId, Member member) { - Notice notice = noticeRepository.findNoticeById(request.noticeId()) + Notice notice = noticeRepository.findNoticeById(noticeId) .orElseThrow(() -> new NoticeException(NoticeErrorCode.NOTICE_NOT_FOUND)); - Member member = request.member(); - // 삭제된 게시글을 USER가 보려는 경우 처리 + // 삭제된 게시글을 'USER'가 보려는 경우 처리 if(notice.getDeletedAt() != null) { if(member == null || !member.getRole().equals(Role.ADMIN)) throw new AuthException(NoticeErrorCode.DELETED_NOTICE_FORBIDDEN_ACCESS); diff --git a/src/main/java/org/withtime/be/withtimebe/global/config/WebConfig.java b/src/main/java/org/withtime/be/withtimebe/global/config/WebConfig.java index 89b594a..70b377d 100644 --- a/src/main/java/org/withtime/be/withtimebe/global/config/WebConfig.java +++ b/src/main/java/org/withtime/be/withtimebe/global/config/WebConfig.java @@ -5,6 +5,7 @@ import org.springframework.format.FormatterRegistry; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.withtime.be.withtimebe.domain.notice.converter.NoticeCategoryConverter; import org.withtime.be.withtimebe.domain.faq.converter.FaqCategoryConverter; import org.withtime.be.withtimebe.global.security.annotation.resolver.AuthenticatedMemberResolver; @@ -23,6 +24,7 @@ public void addArgumentResolvers(List resolvers) @Override public void addFormatters(FormatterRegistry registry) { + registry.addConverter(new NoticeCategoryConverter()); registry.addConverter(new FaqCategoryConverter()); } } diff --git a/src/main/java/org/withtime/be/withtimebe/global/error/code/NoticeErrorCode.java b/src/main/java/org/withtime/be/withtimebe/global/error/code/NoticeErrorCode.java index 6c6389f..32d18ba 100644 --- a/src/main/java/org/withtime/be/withtimebe/global/error/code/NoticeErrorCode.java +++ b/src/main/java/org/withtime/be/withtimebe/global/error/code/NoticeErrorCode.java @@ -10,6 +10,8 @@ @AllArgsConstructor public enum NoticeErrorCode implements BaseErrorCode { + NOTICE_CATEGORY_EMPTY(HttpStatus.BAD_REQUEST, "NOTICE400_1", "공지사항 유형을 입력해주세요."), + DELETED_NOTICE_FORBIDDEN_ACCESS(HttpStatus.FORBIDDEN, "NOTICE403_1", "삭제된 공지사항을 열람할 Admin 권한이 없습니다."), NOTICE_CATEGORY_NOT_FOUND(HttpStatus.NOT_FOUND, "NOTICE404_1", "해당하는 공지사항 유형을 찾을 수 없습니다."),