From 6500c9156ca5ded80653c196913bf3d20d894a00 Mon Sep 17 00:00:00 2001 From: whitemark Date: Fri, 9 Feb 2024 23:49:25 +0900 Subject: [PATCH 01/19] =?UTF-8?q?[feature/#233]=20NormalBoard=20entity,=20?= =?UTF-8?q?dto=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/domain/board/domain/AlbumBoard.java | 1 + .../api/domain/board/domain/NormalBoard.java | 69 ++++++++----------- .../domain/board/domain/NormalBoardType.java | 19 +++++ .../api/domain/board/dto/BoardDto.java | 25 ------- .../api/domain/board/dto/NormalBoardDto.java | 47 +++++++++++++ .../NormalBoardRepositoryCustom.java | 7 +- ...ResponseDto.java => PagedResponseDto.java} | 4 +- .../api/web/ClubActivityController.java | 8 +-- .../com/inhabas/api/web/MemberController.java | 20 +++--- .../inhabas/api/web/MyProfileController.java | 10 +-- 10 files changed, 120 insertions(+), 90 deletions(-) create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardDto.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDto.java rename resource-server/src/main/java/com/inhabas/api/global/dto/{PagedMemberResponseDto.java => PagedResponseDto.java} (76%) diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java index e39d42d9..52421c01 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java @@ -21,6 +21,7 @@ @Table(name = "ALBUM_BOARD") @NoArgsConstructor(access = AccessLevel.PROTECTED) @EntityListeners(AuditingEntityListener.class) + @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorValue("ALBUM") public class AlbumBoard extends BaseBoard { diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java index a64a6d9a..6d5fae2f 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java @@ -1,41 +1,40 @@ package com.inhabas.api.domain.board.domain; -import java.util.*; - -import javax.persistence.*; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.board.domain.valueObject.Content; import com.inhabas.api.domain.board.domain.valueObject.Title; -import com.inhabas.api.domain.board.exception.OnlyWriterModifiableException; import com.inhabas.api.domain.comment.domain.Comment; import com.inhabas.api.domain.file.domain.BoardFile; +import com.inhabas.api.domain.menu.domain.Menu; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; @Entity -@Table(name = "normal_board") -@Getter +@Table(name = "NORMAL_BOARD") @NoArgsConstructor(access = AccessLevel.PROTECTED) @EntityListeners(AuditingEntityListener.class) @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorValue("NORMAL") public class NormalBoard extends BaseBoard { - @Embedded protected Content content; + @Embedded private Content content; + + @Column + private Boolean isPinned = false; @OneToMany(mappedBy = "parentBoard", cascade = CascadeType.ALL, orphanRemoval = true) - protected List comments = new ArrayList<>(); + private List comments = new ArrayList<>(); /* constructor */ - public NormalBoard(String title, String contents) { - this.title = new Title(title); - this.content = new Content(contents); + public NormalBoard(String title, Menu menu, String content) { + super(title, menu); + this.content = new Content(content); } /* getter */ @@ -50,32 +49,22 @@ public List getFiles() { /* relation method */ - public NormalBoard addFiles(Set UploadFiles) { - if (Objects.nonNull(UploadFiles)) UploadFiles.forEach(this::addFile); - - return this; - } - - public void addFile(BoardFile uploadFile) { - files.add(uploadFile); - uploadFile.toBoard(this); - } - - public void addComment(Comment newComment) { - comments.add(newComment); + public void updateText(String title, String content) { + this.title = new Title(title); + this.content = new Content(content); } - public void modify(String title, String contents, Member writer) { + public void updateFiles(List files) { - if (cannotModifiableBy(writer)) { - throw new OnlyWriterModifiableException(); + if (this.files != null) { + this.files.clear(); + } else { + this.files = new ArrayList<>(); } - this.title = new Title(title); - this.content = new Content(contents); + for (BoardFile file : files) { + addFile(file); + } } - public boolean cannotModifiableBy(Member writer) { - return !this.writer.equals(writer); - } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java new file mode 100644 index 00000000..a9c6f2c5 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java @@ -0,0 +1,19 @@ + package com.inhabas.api.domain.board.domain; + +public enum NormalBoardType { + NOTICE("notice", 4), + FREE("free", 5), + QUESTION("question", 6), + SUGGEST("suggest", 7), + STORAGE("storage", 8), + EXECUTIVE("executive", 9); + + private String boardType; + private int menuId; + + NormalBoardType(String boardType, int menuId) { + this.boardType = boardType; + this.menuId = menuId; + } + +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardDto.java deleted file mode 100644 index a06da371..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardDto.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.inhabas.api.domain.board.dto; - -import java.time.LocalDateTime; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonUnwrapped; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; - -@Getter -@AllArgsConstructor -public class BoardDto { - private Integer id; - private String title; - private String contents; - private String writerName; - @JsonUnwrapped private MenuId menuId; - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime created; - - private LocalDateTime updated; -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDto.java new file mode 100644 index 00000000..1161fffc --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDto.java @@ -0,0 +1,47 @@ +package com.inhabas.api.domain.board.dto; + +import java.time.LocalDateTime; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import com.inhabas.api.domain.menu.domain.valueObject.MenuId; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Getter +@NoArgsConstructor +public class NormalBoardDto { + private Long id; + private String title; + private String writerName; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateCreated; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateUpdated; + + @NotNull + private Boolean isPinned; + + @Builder + public NormalBoardDto(Long id, String title, String writerName, LocalDateTime dateCreated, LocalDateTime dateUpdated, Boolean isPinned) { + this.id = id; + this.title = title; + this.writerName = writerName; + this.dateCreated = dateCreated; + this.dateUpdated = dateUpdated; + this.isPinned = isPinned; + } + +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java index 90c5fedb..2abf17bc 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java @@ -2,14 +2,13 @@ import java.util.Optional; +import com.inhabas.api.domain.board.dto.NormalBoardDto; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import com.inhabas.api.domain.board.dto.BoardDto; - public interface NormalBoardRepositoryCustom { - Page findAllByMenuId(Integer menuId, Pageable pageable); + Page findAllByMenuId(Integer menuId); - Optional findDtoById(Long id); + Optional findDtoById(Long id); } diff --git a/resource-server/src/main/java/com/inhabas/api/global/dto/PagedMemberResponseDto.java b/resource-server/src/main/java/com/inhabas/api/global/dto/PagedResponseDto.java similarity index 76% rename from resource-server/src/main/java/com/inhabas/api/global/dto/PagedMemberResponseDto.java rename to resource-server/src/main/java/com/inhabas/api/global/dto/PagedResponseDto.java index 1b051df0..cf74a59d 100644 --- a/resource-server/src/main/java/com/inhabas/api/global/dto/PagedMemberResponseDto.java +++ b/resource-server/src/main/java/com/inhabas/api/global/dto/PagedResponseDto.java @@ -10,14 +10,14 @@ @Data @NoArgsConstructor -public class PagedMemberResponseDto { +public class PagedResponseDto { @NotNull private PageInfoDto pageInfo; @NotNull private List data; @Builder - public PagedMemberResponseDto(PageInfoDto pageInfo, List data) { + public PagedResponseDto(PageInfoDto pageInfo, List data) { this.pageInfo = pageInfo; this.data = data; } diff --git a/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java b/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java index d28ee61b..95c1521c 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java @@ -21,7 +21,7 @@ import com.inhabas.api.domain.club.dto.SaveClubActivityDto; import com.inhabas.api.domain.club.usecase.ClubActivityService; import com.inhabas.api.global.dto.PageInfoDto; -import com.inhabas.api.global.dto.PagedMemberResponseDto; + import com.inhabas.api.global.dto.PagedResponseDto; import com.inhabas.api.global.util.PageUtil; import com.inhabas.api.web.argumentResolver.Authenticated; import io.swagger.v3.oas.annotations.Operation; @@ -46,13 +46,13 @@ public class ClubActivityController { value = { @ApiResponse( responseCode = "200", - content = {@Content(schema = @Schema(implementation = PagedMemberResponseDto.class))}), + content = {@Content(schema = @Schema(implementation = PagedResponseDto.class))}), }) @SecurityRequirements(value = {}) @GetMapping("/club/activities") @PreAuthorize( "@boardSecurityChecker.checkMenuAccess(2, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD_LIST)") - public ResponseEntity> getClubActivities( + public ResponseEntity> getClubActivities( @Parameter(description = "페이지", example = "0") @RequestParam(name = "page", defaultValue = "0") int page, @@ -68,7 +68,7 @@ public ResponseEntity> getClubActivities new PageImpl<>(pagedDtos, pageable, allDtos.size()); PageInfoDto pageInfoDto = new PageInfoDto(ClubActivityDtoPage); - return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); + return ResponseEntity.ok(new PagedResponseDto<>(pageInfoDto, pagedDtos)); } @Operation(summary = "동아리 활동 글 생성", description = "동아리 활동 글 생성 (운영진 이상)") diff --git a/resource-server/src/main/java/com/inhabas/api/web/MemberController.java b/resource-server/src/main/java/com/inhabas/api/web/MemberController.java index 981e25ba..2b6d3b29 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/MemberController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/MemberController.java @@ -17,7 +17,7 @@ import com.inhabas.api.domain.signUp.dto.ApplicationDetailDto; import com.inhabas.api.domain.signUp.usecase.AnswerService; import com.inhabas.api.global.dto.PageInfoDto; -import com.inhabas.api.global.dto.PagedMemberResponseDto; +import com.inhabas.api.global.dto.PagedResponseDto; import com.inhabas.api.global.util.PageUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -43,10 +43,10 @@ public class MemberController { value = { @ApiResponse( responseCode = "200", - content = {@Content(schema = @Schema(implementation = PagedMemberResponseDto.class))}), + content = {@Content(schema = @Schema(implementation = PagedResponseDto.class))}), }) @GetMapping("/members/unapproved") - public ResponseEntity> + public ResponseEntity> getUnapprovedMembers( @Parameter(description = "페이지", example = "0") @RequestParam(name = "page", defaultValue = "0") @@ -67,7 +67,7 @@ public class MemberController { new PageImpl<>(pagedDtos, pageable, allDtos.size()); PageInfoDto pageInfoDto = new PageInfoDto(newMemberManagementDtoPage); - return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); + return ResponseEntity.ok(new PagedResponseDto<>(pageInfoDto, pagedDtos)); } @Operation( @@ -124,10 +124,10 @@ public ResponseEntity getUnapprovedMemberApplication( value = { @ApiResponse( responseCode = "200", - content = {@Content(schema = @Schema(implementation = PagedMemberResponseDto.class))}), + content = {@Content(schema = @Schema(implementation = PagedResponseDto.class))}), }) @GetMapping("/members/graduated") - public ResponseEntity> getGraduatedMembers( + public ResponseEntity> getGraduatedMembers( @Parameter(description = "페이지", example = "0") @RequestParam(name = "page", defaultValue = "0") int page, @@ -147,7 +147,7 @@ public ResponseEntity> getGr new PageImpl<>(pagedDtos, pageable, allDtos.size()); PageInfoDto pageInfoDto = new PageInfoDto(graduatedMemberManagementDtoPage); - return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); + return ResponseEntity.ok(new PagedResponseDto<>(pageInfoDto, pagedDtos)); } @Operation(summary = "비활동 이상 졸업자 아닌 멤버 목록 조회", description = "이름, 학번 검색 가능") @@ -155,10 +155,10 @@ public ResponseEntity> getGr value = { @ApiResponse( responseCode = "200", - content = {@Content(schema = @Schema(implementation = PagedMemberResponseDto.class))}), + content = {@Content(schema = @Schema(implementation = PagedResponseDto.class))}), }) @GetMapping("/members/notGraduated") - public ResponseEntity> getNotGraduatedMembers( + public ResponseEntity> getNotGraduatedMembers( @Parameter(description = "페이지", example = "0") @RequestParam(name = "page", defaultValue = "0") int page, @@ -178,7 +178,7 @@ public ResponseEntity> getNo new PageImpl<>(pagedDtos, pageable, allDtos.size()); PageInfoDto pageInfoDto = new PageInfoDto(oldMemberManagementDtoPage); - return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); + return ResponseEntity.ok(new PagedResponseDto<>(pageInfoDto, pagedDtos)); } @Operation( diff --git a/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java b/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java index 59f9765f..c34ad092 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java @@ -19,7 +19,7 @@ import com.inhabas.api.auth.domain.oauth2.member.dto.*; import com.inhabas.api.domain.member.usecase.MemberProfileService; import com.inhabas.api.global.dto.PageInfoDto; -import com.inhabas.api.global.dto.PagedMemberResponseDto; +import com.inhabas.api.global.dto.PagedResponseDto; import com.inhabas.api.global.util.PageUtil; import com.inhabas.api.web.argumentResolver.Authenticated; import io.swagger.v3.oas.annotations.Operation; @@ -147,7 +147,7 @@ public ResponseEntity requestMyProfileName( content = {@Content(schema = @Schema(implementation = UpdateNameRequestDto.class))}), }) @GetMapping("/myInfo/myRequests") - public ResponseEntity> getMyInfoMyRequests( + public ResponseEntity> getMyInfoMyRequests( @Parameter(description = "페이지", example = "0") @RequestParam(name = "page", defaultValue = "0") int page, @@ -163,7 +163,7 @@ public ResponseEntity> getMyInfoMyR new PageImpl<>(pagedDtos, pageable, allDtos.size()); PageInfoDto pageInfoDto = new PageInfoDto(updateNameRequestDtoPage); - return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); + return ResponseEntity.ok(new PagedResponseDto<>(pageInfoDto, pagedDtos)); } @Operation(summary = "이름 수정 요청 조회", description = "이름 수정 요청 조회") @@ -174,7 +174,7 @@ public ResponseEntity> getMyInfoMyR content = {@Content(schema = @Schema(implementation = UpdateNameRequestDto.class))}), }) @GetMapping("/myInfo/requests") - public ResponseEntity> getMyInfoRequests( + public ResponseEntity> getMyInfoRequests( @Parameter(description = "페이지", example = "0") @RequestParam(name = "page", defaultValue = "0") int page, @@ -190,7 +190,7 @@ public ResponseEntity> getMyInfoReq new PageImpl<>(pagedDtos, pageable, allDtos.size()); PageInfoDto pageInfoDto = new PageInfoDto(updateNameRequestDtoPage); - return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); + return ResponseEntity.ok(new PagedResponseDto<>(pageInfoDto, pagedDtos)); } @Operation(summary = "이름 수정 요청 처리", description = "이름 수정 요청 처리") From 9868a36e0abd83369379a3727b2866f6ee5e0c2d Mon Sep 17 00:00:00 2001 From: whitemark Date: Sat, 10 Feb 2024 23:58:59 +0900 Subject: [PATCH 02/19] =?UTF-8?q?[feature/#233]=20NormalBoard=20controller?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/web/NormalBoardController.java | 228 ++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java diff --git a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java new file mode 100644 index 00000000..c359f80f --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java @@ -0,0 +1,228 @@ +package com.inhabas.api.web; + +import com.inhabas.api.auth.domain.error.ErrorResponse; +import com.inhabas.api.domain.board.domain.NormalBoardType; +import com.inhabas.api.domain.board.dto.NormalBoardDto; +import com.inhabas.api.domain.board.dto.UpdateBoardDto; +import com.inhabas.api.domain.board.usecase.NormalBoardService; +import com.inhabas.api.global.dto.PageInfoDto; +import com.inhabas.api.global.dto.PagedResponseDto; +import com.inhabas.api.global.util.PageUtil; +import com.inhabas.api.web.argumentResolver.Authenticated; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirements; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import javax.validation.Valid; +import java.net.URI; +import java.util.List; + +@Slf4j +@Tag(name = "게시글 관리") +@RestController +@RequiredArgsConstructor +public class NormalBoardController { + + private final NormalBoardService normalBoardService; + + @Operation(summary = "게시판 종류 당 글 개수 조회") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = BoardCountDto.class))}), + }) + @GetMapping("/board/count") + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD_LIST)" + ) + @SecurityRequirements(value = {}) + public ResponseEntity> getBoardList() { + return ResponseEntity.ok(normalBoardService.getPostCount()); + } + + @Operation(summary = "게시글 목록 조회") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = PagedResponseDto.class))}), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @GetMapping("/board/{boardType}") + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD_LIST)" + ) + public ResponseEntity> getBoardList( + @Parameter(description = "페이지", example = "0") + @RequestParam(name = "page", defaultValue = "0") + int page, + @Parameter(description = "페이지당 개수", example = "10") + @RequestParam(name = "size", defaultValue = "10") + int size, + @Parameter(description = "검색어 (작성자 이름 or 제목 or 내용)", example = "") + @RequestParam(name = "search", defaultValue = "") + String search, + @PathVariable NormalBoardType boardType, + @Authenticated Long memberId) { + + Pageable pageable = PageRequest.of(page, size); + List allDtos = normalBoardService.getPosts(memberId, boardType, search); + List pagedDtos = PageUtil.getPagedDtoList(pageable, allDtos); + + PageImpl normalBoardDtoPage = + new PageImpl<>(pagedDtos, pageable, allDtos.size()); + PageInfoDto pageInfoDto = new PageInfoDto(normalBoardDtoPage); + + return ResponseEntity.ok(new PagedResponseDto<>(pageInfoDto, pagedDtos)); + } + + @Operation(summary = "게시글 단일 조회") + @GetMapping("/board/{boardType}/{boardId}") + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD)" + ) + @ApiResponses({ + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = NormalBoardDto.class))}), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + public ResponseEntity getBoard( + @PathVariable Long boardId, + @PathVariable NormalBoardType boardType, + @Authenticated Long memberId) { + + return ResponseEntity.ok(normalBoardService.getBoard(boardId)); + } + + @Operation(summary = "게시글 추가") + @PostMapping("/board/{boardType}") + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).CREATE_BOARD)" + ) + @ApiResponses({ + @ApiResponse(responseCode = "201", description = "'Location' 헤더에 생성된 리소스의 URI 가 포함됩니다."), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + public ResponseEntity addBoard( + @Authenticated Long memberId, + @PathVariable NormalBoardType boardType, + @Valid @RequestBody SaveNormalBoardDto saveNormalBoardDto) { + + Long newNormalBoardId = normalBoardService.write(memberId, boardType, saveNormalBoardDto); + URI location = + ServletUriComponentsBuilder.fromCurrentRequest() + .path("/board/{boardType}/{boardId}") + .buildAndExpand(boardType, newNormalBoardId) + .toUri(); + + return ResponseEntity.created(location).build(); + } + + @Operation(summary = "게시글 수정") + @PutMapping("/board/{boardType}/{boardId}") + @ApiResponses({ + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), + @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + }) + @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") + public ResponseEntity updateBoard( + @Authenticated Long memberId, + @PathVariable NormalBoardType boardType, + @Valid @RequestBody UpdateBoardDto updateBoardDto) { + + normalBoardService.update(memberId, boardType, updateBoardDto); + return ResponseEntity.noContent().build(); + } + + @Operation(description = "게시글 삭제") + @DeleteMapping("/board/{boardType}/{boardId}") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 게시글 삭제 요청"), + @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + }) + @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") + public ResponseEntity deleteBoard( + @Authenticated Long memberId, + @PathVariable NormalBoardType boardType, + @PathVariable Long boardId) { + + normalBoardService.delete(memberId, boardType, boardId); + return ResponseEntity.noContent().build(); + } +} From 99ee0078ea53d9d83085abe1cfc701becdcff63d Mon Sep 17 00:00:00 2001 From: whitemark Date: Sun, 11 Feb 2024 23:59:46 +0900 Subject: [PATCH 03/19] =?UTF-8?q?[feature/#233]=20NormalBoard=20=EC=A0=84?= =?UTF-8?q?=EB=B0=98=EC=A0=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/domain/board/domain/NormalBoard.java | 9 +- .../domain/board/domain/NormalBoardType.java | 7 ++ .../com/inhabas/api/web/BoardController.java | 86 ------------------- .../api/web/NormalBoardController.java | 2 +- 4 files changed, 15 insertions(+), 89 deletions(-) delete mode 100644 resource-server/src/main/java/com/inhabas/api/web/BoardController.java diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java index 6d5fae2f..24eb0abd 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java @@ -32,13 +32,18 @@ public class NormalBoard extends BaseBoard { /* constructor */ - public NormalBoard(String title, Menu menu, String content) { + public NormalBoard(String title, Menu menu, Content content, Boolean isPinned) { super(title, menu); - this.content = new Content(content); + this.content = content; + this.isPinned = isPinned; } /* getter */ + public Boolean getPinned() { + return isPinned; + } + public String getContent() { return content.getValue(); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java index a9c6f2c5..142d09a3 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java @@ -16,4 +16,11 @@ public enum NormalBoardType { this.menuId = menuId; } + public String getBoardType() { + return boardType; + } + + public int getMenuId() { + return menuId; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/BoardController.java b/resource-server/src/main/java/com/inhabas/api/web/BoardController.java deleted file mode 100644 index 3b9e9b28..00000000 --- a/resource-server/src/main/java/com/inhabas/api/web/BoardController.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.inhabas.api.web; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import org.springframework.web.bind.annotation.*; - -import io.swagger.v3.oas.annotations.tags.Tag; - -@Slf4j -@Tag(name = "게시글 관리") -@RestController -@RequiredArgsConstructor -public class BoardController { - - // private final BoardService boardService; - - // @Operation(summary = "게시글 단일 조회") - // @GetMapping("/board/{id}") - // @ApiResponses({ - // @ApiResponse(responseCode = "200"), - // @ApiResponse(responseCode = "400", description = "잘못된 게시글 조회 URL 요청"), - // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") - // }) - // public ResponseEntity getBoard(@PathVariable Integer id) { - // - // return new ResponseEntity<>(boardService.getBoard(id), HttpStatus.OK); - // } - - // @Operation(summary = "게시글 목록 조회") - // @GetMapping("/boards") - // @ApiResponses({ - // @ApiResponse(responseCode = "200"), - // @ApiResponse(responseCode = "400", description = "잘못된 게시글 목록 조회 URL 요청"), - // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") - // }) - // public ResponseEntity> getBoardList( - // @PageableDefault(size = 15, direction = Direction.DESC, sort = "created") Pageable - // pageable, - // @RequestParam("menu_id") MenuId menuId) { - // - // return new ResponseEntity<>(boardService.getBoardList(menuId, pageable), HttpStatus.OK); - // } - - // @Operation(summary = "게시글 추가") - // @PostMapping("/board") - // @ApiResponses({ - // @ApiResponse(responseCode = "201"), - // @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), - // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") - // }) - // public ResponseEntity addBoard( - // @Authenticated Long memberId, @Valid @RequestBody SaveBoardDto saveBoardDto) { - // - // return new ResponseEntity<>(boardService.write(memberId, saveBoardDto), - // HttpStatus.CREATED); - // } - // - // @Operation(summary = "게시글 수정") - // @PutMapping("/board") - // @ApiResponses({ - // @ApiResponse(responseCode = "200"), - // @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), - // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") - // }) - // public ResponseEntity updateBoard( - // @Authenticated Long memberId, @Valid @RequestBody UpdateBoardDto updateBoardDto) { - // - // return new ResponseEntity<>(boardService.update(memberId, updateBoardDto), - // HttpStatus.OK); - // } - // - // @Operation(description = "게시글 삭제") - // @DeleteMapping("/board/{id}") - // @ApiResponses({ - // @ApiResponse(responseCode = "204"), - // @ApiResponse(responseCode = "400", description = "잘못된 게시글 삭제 요청"), - // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") - // }) - // public ResponseEntity deleteBoard( - // @Authenticated Long memberId, @PathVariable Long id) { - // - // boardService.delete(memberId, id); - // return new ResponseEntity<>(HttpStatus.NO_CONTENT); - // } -} diff --git a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java index c359f80f..fb66c23b 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java @@ -146,7 +146,7 @@ public ResponseEntity getBoard( @PathVariable NormalBoardType boardType, @Authenticated Long memberId) { - return ResponseEntity.ok(normalBoardService.getBoard(boardId)); + return ResponseEntity.ok(normalBoardService.getPost(boardId)); } @Operation(summary = "게시글 추가") From 178479563d2502cd4fc61bd1191ce4438e76f07c Mon Sep 17 00:00:00 2001 From: whitemark Date: Mon, 12 Feb 2024 23:12:56 +0900 Subject: [PATCH 04/19] =?UTF-8?q?[feature/#233]=20NormalBoard=20Service=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/domain/board/domain/NormalBoard.java | 4 +- .../api/domain/board/dto/BoardCountDto.java | 26 +++ .../board/dto/NormalBoardDetailDto.java | 65 +++++++ .../api/domain/board/dto/SaveBoardDto.java | 30 ---- .../domain/board/dto/SaveNormalBoardDto.java | 34 ++++ .../domain/board/usecase/BoardService.java | 20 --- .../board/usecase/BoardServiceImpl.java | 82 --------- .../board/usecase/NormalBoardService.java | 25 +++ .../usecase/NormalNormalBoardServiceImpl.java | 162 ++++++++++++++++++ .../api/web/NormalBoardController.java | 14 +- 10 files changed, 321 insertions(+), 141 deletions(-) create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDetailDto.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveBoardDto.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveNormalBoardDto.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardService.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardServiceImpl.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java index 24eb0abd..5ee87cb5 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java @@ -32,9 +32,9 @@ public class NormalBoard extends BaseBoard { /* constructor */ - public NormalBoard(String title, Menu menu, Content content, Boolean isPinned) { + public NormalBoard(String title, Menu menu, String content, Boolean isPinned) { super(title, menu); - this.content = content; + this.content = new Content(content); this.isPinned = isPinned; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java new file mode 100644 index 00000000..1e7baf56 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java @@ -0,0 +1,26 @@ +package com.inhabas.api.domain.board.dto; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.PositiveOrZero; + +@Getter +@NoArgsConstructor +public class BoardCountDto { + + @NotNull + private String menuName; + + @NotNull + @PositiveOrZero + private Integer count; + + @Builder + public BoardCountDto(String menuName, Integer count) { + this.menuName = menuName; + this.count = count; + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDetailDto.java new file mode 100644 index 00000000..234d87e7 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDetailDto.java @@ -0,0 +1,65 @@ +package com.inhabas.api.domain.board.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.domain.file.dto.FileDownloadDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import java.time.LocalDateTime; +import java.util.List; + +@Getter +@NoArgsConstructor +public class NormalBoardDetailDto { + + @NotNull + @Positive + private Long id; + + @NotBlank + private String title; + + @NotBlank private String content; + + @NotBlank private String writerName; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateCreated; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateUpdated; + + @NotNull private List files; + + @NotNull + private Boolean isPinned; + + @Builder + public NormalBoardDetailDto( + Long id, + String title, + String content, + String writerName, + LocalDateTime dateCreated, + LocalDateTime dateUpdated, + List files, + Boolean isPinned) { + this.id = id; + this.title = title; + this.content = content; + this.writerName = writerName; + this.dateCreated = dateCreated; + this.dateUpdated = dateUpdated; + this.files = files; + this.isPinned = isPinned; + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveBoardDto.java deleted file mode 100644 index 84afb64d..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveBoardDto.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.inhabas.api.domain.board.dto; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; -import org.hibernate.validator.constraints.Length; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class SaveBoardDto { - @NotBlank(message = "제목을 입력하세요.") - @Length(max = 100, message = "제목은 최대 100자입니다.") - private String title; - - @NotBlank(message = "본문을 입력하세요.") - private String contents; - - @NotNull private MenuId menuId; - - public SaveBoardDto(String title, String contents, MenuId menuId) { - this.title = title; - this.contents = contents; - this.menuId = menuId; - } -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveNormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveNormalBoardDto.java new file mode 100644 index 00000000..c3634a0d --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveNormalBoardDto.java @@ -0,0 +1,34 @@ +package com.inhabas.api.domain.board.dto; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +import org.springframework.web.multipart.MultipartFile; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@NoArgsConstructor +public class SaveNormalBoardDto { + @NotBlank + private String title; + + @NotBlank + private String content; + + private List files; + + @NotNull + private Boolean isPinned; + + public SaveNormalBoardDto(String title, String content, List files, Boolean isPinned) { + this.title = title; + this.content = content; + this.files = (files != null) ? files : new ArrayList<>(); + this.isPinned = isPinned; + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardService.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardService.java deleted file mode 100644 index ff870c68..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardService.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.inhabas.api.domain.board.usecase; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -import com.inhabas.api.domain.board.dto.BoardDto; -import com.inhabas.api.domain.board.dto.SaveBoardDto; -import com.inhabas.api.domain.board.dto.UpdateBoardDto; - -public interface BoardService { - Long write(Long memberId, SaveBoardDto saveBoardDto); - - Long update(Long memberId, UpdateBoardDto updateBoardDto); - - void delete(Long memberId, Long boardId); - - BoardDto getBoard(Long boardId); - - Page getBoardList(Integer menuId, Pageable pageable); -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardServiceImpl.java deleted file mode 100644 index 53bb6fed..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardServiceImpl.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.inhabas.api.domain.board.usecase; - -import javax.transaction.Transactional; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; - -import com.inhabas.api.auth.domain.error.businessException.NotFoundException; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.auth.domain.oauth2.member.domain.exception.MemberNotFoundException; -import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; -import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.board.dto.BoardDto; -import com.inhabas.api.domain.board.dto.SaveBoardDto; -import com.inhabas.api.domain.board.dto.UpdateBoardDto; -import com.inhabas.api.domain.board.exception.OnlyWriterModifiableException; -import com.inhabas.api.domain.board.repository.NormalBoardRepository; -import com.inhabas.api.domain.menu.repository.MenuRepository; - -@Service -@Slf4j -@Transactional -@RequiredArgsConstructor -public class BoardServiceImpl implements BoardService { - - private final NormalBoardRepository boardRepository; - private final MenuRepository menuRepository; - private final MemberRepository memberRepository; - - @Override - public Long write(Long memberId, SaveBoardDto saveBoardDto) { - - Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - - NormalBoard normalBoard = - new NormalBoard(saveBoardDto.getTitle(), saveBoardDto.getContents()) - .writtenBy(writer, NormalBoard.class); - - return boardRepository.save(normalBoard).getId(); - } - - @Override - public Long update(Long memberId, UpdateBoardDto updateBoardDto) { - - NormalBoard savedBoard = - boardRepository.findById(updateBoardDto.getId()).orElseThrow(NotFoundException::new); - Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - - savedBoard.modify(updateBoardDto.getTitle(), updateBoardDto.getContents(), writer); - - return boardRepository.save(savedBoard).getId(); - } - - @Override - public void delete(Long memberId, Long boardId) { - - NormalBoard board = boardRepository.findById(boardId).orElseThrow(NotFoundException::new); - Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - - if (board.cannotModifiableBy(writer)) { - throw new OnlyWriterModifiableException(); - } - - boardRepository.deleteById(boardId); - } - - @Override - public BoardDto getBoard(Long id) { - - return boardRepository.findDtoById(id).orElseThrow(NotFoundException::new); - } - - @Override - public Page getBoardList(Integer menuId, Pageable pageable) { - - return boardRepository.findAllByMenuId(menuId, pageable); - } -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java new file mode 100644 index 00000000..fb00d389 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java @@ -0,0 +1,25 @@ +package com.inhabas.api.domain.board.usecase; + +import com.inhabas.api.domain.board.domain.NormalBoardType; + +import com.inhabas.api.domain.board.dto.BoardCountDto; +import com.inhabas.api.domain.board.dto.NormalBoardDetailDto; +import com.inhabas.api.domain.board.dto.NormalBoardDto; +import com.inhabas.api.domain.board.dto.SaveNormalBoardDto; + +import java.util.List; + +public interface NormalBoardService { + + List getPostCount(); + + List getPosts(Long memberId, NormalBoardType boardType, String search); + + NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Long boardId); + + Long write(Long memberId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto); + + void update(Long boardId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto); + + void delete(Long boardId); +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java new file mode 100644 index 00000000..91a512e6 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java @@ -0,0 +1,162 @@ +package com.inhabas.api.domain.board.usecase; + +import javax.transaction.Transactional; + +import com.inhabas.api.domain.board.domain.NormalBoardType; +import com.inhabas.api.domain.board.dto.BoardCountDto; +import com.inhabas.api.domain.board.dto.NormalBoardDetailDto; +import com.inhabas.api.domain.board.dto.SaveNormalBoardDto; +import com.inhabas.api.domain.board.exception.S3UploadFailedException; +import com.inhabas.api.domain.board.repository.BaseBoardRepository; +import com.inhabas.api.domain.file.domain.BoardFile; +import com.inhabas.api.domain.file.dto.FileDownloadDto; +import com.inhabas.api.domain.file.usecase.S3Service; +import com.inhabas.api.domain.menu.domain.Menu; +import com.inhabas.api.global.util.FileUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.stereotype.Service; + +import com.inhabas.api.auth.domain.error.businessException.NotFoundException; +import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; +import com.inhabas.api.domain.board.domain.NormalBoard; +import com.inhabas.api.domain.board.dto.NormalBoardDto; +import com.inhabas.api.domain.board.repository.NormalBoardRepository; +import com.inhabas.api.domain.menu.repository.MenuRepository; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@Slf4j +@Transactional +@RequiredArgsConstructor +public class NormalNormalBoardServiceImpl implements NormalBoardService { + + private final NormalBoardRepository normalBoardRepository; + private final BaseBoardRepository baseBoardRepository; + private final MenuRepository menuRepository; + private final MemberRepository memberRepository; + private final S3Service s3Service; + + + @Override + public List getPostCount() { + return baseBoardRepository.countRowsGroupByMenuId(); + } + + + @Override + public List getPosts(Long memberId, NormalBoardType boardType, String search) { + List normalBoardList; + if (boardType.equals(NormalBoardType.SUGGEST)) { + normalBoardList = normalBoardRepository.findAllByMemberIdAndTypeAndSearch(memberId, boardType, search); + } else { + normalBoardList = normalBoardRepository.findAllByTypeAndSearch(boardType, search); + } + + return normalBoardList.stream().map(board -> NormalBoardDto.builder() + .id(board.getId()) + .title(board.getTitle()) + .isPinned(board.getPinned()) + .writerName(board.getWriter().getName()) + .dateCreated(board.getDateCreated()) + .dateUpdated(board.getDateUpdated()) + .build()) + .collect(Collectors.toList()); + } + + @Override + public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Long boardId) { + NormalBoard normalBoard; + List fileDownloadDtoList = null; + if (boardType.equals(NormalBoardType.SUGGEST)) { + normalBoard = normalBoardRepository.findMyByMemberIdAndTypeAndId(memberId, boardType, boardId); + } else { + normalBoard = normalBoardRepository.findByTypeAndId(boardType, boardId); + } + if (!normalBoard.getFiles().isEmpty()) { + fileDownloadDtoList = + normalBoard.getFiles().stream() + .map(obj -> FileDownloadDto.builder().name(obj.getName()).url(obj.getUrl()).build()) + .collect(Collectors.toList()); + } + + + return NormalBoardDetailDto.builder() + .id(normalBoard.getId()) + .title(normalBoard.getTitle()) + .content(normalBoard.getContent()) + .writerName(normalBoard.getWriter().getName()) + .dateCreated(normalBoard.getDateCreated()) + .dateUpdated(normalBoard.getDateUpdated()) + .files(fileDownloadDtoList) + .isPinned(normalBoard.getPinned()) + .build(); + } + + @Override + public Long write(Long memberId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto) { + + Menu menu = menuRepository.findById(normalBoardType.getMenuId()).orElseThrow(NotFoundException::new); + + NormalBoard normalBoard = + new NormalBoard(saveNormalBoardDto.getTitle(), menu, saveNormalBoardDto.getContent(), saveNormalBoardDto.getIsPinned()); + + return normalBoardRepository.save(normalBoard).getId(); + } + + @Override + public void update(Long boardId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto) { + + NormalBoard normalBoard = + normalBoardRepository.findById(boardId).orElseThrow(NotFoundException::new); + + updateNormalBoardFiles(saveNormalBoardDto, normalBoardType, normalBoard); + } + + @Override + public void delete(Long boardId) { + normalBoardRepository.deleteById(boardId); + } + + + private Long updateNormalBoardFiles( + SaveNormalBoardDto saveNormalBoardDto, NormalBoardType normalBoardType, NormalBoard normalBoard) { + final String DIR_NAME = "/" + normalBoardType.getBoardType(); + List updateFiles = new ArrayList<>(); + List urlListForDelete = new ArrayList<>(); + + if (saveNormalBoardDto.getFiles() != null) { + normalBoard.updateText(saveNormalBoardDto.getTitle(), saveNormalBoardDto.getContent()); + try { + updateFiles = + saveNormalBoardDto.getFiles().stream() + .map( + file -> { + String path = FileUtil.generateFileName(file, DIR_NAME); + String url = s3Service.uploadS3File(file, path); + urlListForDelete.add(url); + return BoardFile.builder() + .name(file.getOriginalFilename()) + .url(url) + .board(normalBoard) + .build(); + }) + .collect(Collectors.toList()); + + } catch (RuntimeException e) { + for (String url : urlListForDelete) { + s3Service.deleteS3File(url); + } + throw new S3UploadFailedException(); + } + } + + normalBoard.updateFiles(updateFiles); + return normalBoardRepository.save(normalBoard).getId(); + } + +} diff --git a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java index fb66c23b..4f88ffe4 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java @@ -2,8 +2,7 @@ import com.inhabas.api.auth.domain.error.ErrorResponse; import com.inhabas.api.domain.board.domain.NormalBoardType; -import com.inhabas.api.domain.board.dto.NormalBoardDto; -import com.inhabas.api.domain.board.dto.UpdateBoardDto; +import com.inhabas.api.domain.board.dto.*; import com.inhabas.api.domain.board.usecase.NormalBoardService; import com.inhabas.api.global.dto.PageInfoDto; import com.inhabas.api.global.dto.PagedResponseDto; @@ -141,12 +140,12 @@ public ResponseEntity> getBoardList( value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) }) - public ResponseEntity getBoard( + public ResponseEntity getBoard( @PathVariable Long boardId, @PathVariable NormalBoardType boardType, @Authenticated Long memberId) { - return ResponseEntity.ok(normalBoardService.getPost(boardId)); + return ResponseEntity.ok(normalBoardService.getPost(memberId, boardType, boardId)); } @Operation(summary = "게시글 추가") @@ -203,9 +202,10 @@ public ResponseEntity addBoard( public ResponseEntity updateBoard( @Authenticated Long memberId, @PathVariable NormalBoardType boardType, - @Valid @RequestBody UpdateBoardDto updateBoardDto) { + @PathVariable Long boardId, + @Valid @RequestBody SaveNormalBoardDto saveNormalBoardDto) { - normalBoardService.update(memberId, boardType, updateBoardDto); + normalBoardService.update(boardId, boardType, saveNormalBoardDto); return ResponseEntity.noContent().build(); } @@ -222,7 +222,7 @@ public ResponseEntity deleteBoard( @PathVariable NormalBoardType boardType, @PathVariable Long boardId) { - normalBoardService.delete(memberId, boardType, boardId); + normalBoardService.delete(boardId); return ResponseEntity.noContent().build(); } } From 65e4232ed5942692d4c00f0e4e0b892e024fbd6a Mon Sep 17 00:00:00 2001 From: whitemark Date: Tue, 13 Feb 2024 10:56:34 +0900 Subject: [PATCH 05/19] =?UTF-8?q?[feature/#233]=20NormalBoard=20repository?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/repository/BaseBoardRepository.java | 2 +- .../repository/BaseBoardRepositoryCustom.java | 11 ++ .../repository/BaseBoardRepositoryImpl.java | 29 ++++ .../NormalBoardRepositoryCustom.java | 16 ++- .../repository/NormalBoardRepositoryImpl.java | 127 ++++++++++-------- .../board/usecase/NormalBoardService.java | 3 - .../usecase/NormalNormalBoardServiceImpl.java | 47 ++----- .../domain/contest/domain/ContestBoard.java | 2 +- .../api/web/NormalBoardController.java | 6 +- 9 files changed, 136 insertions(+), 107 deletions(-) create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java index 8fae3619..e4685ac2 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java @@ -4,4 +4,4 @@ import com.inhabas.api.domain.board.domain.BaseBoard; -public interface BaseBoardRepository extends JpaRepository {} +public interface BaseBoardRepository extends JpaRepository, BaseBoardRepositoryCustom {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java new file mode 100644 index 00000000..073af9ab --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java @@ -0,0 +1,11 @@ +package com.inhabas.api.domain.board.repository; + +import com.inhabas.api.domain.board.dto.BoardCountDto; + +import java.util.List; + +public interface BaseBoardRepositoryCustom { + + List countRowsGroupByMenuId(); + +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java new file mode 100644 index 00000000..eb375686 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java @@ -0,0 +1,29 @@ +package com.inhabas.api.domain.board.repository; + +import com.inhabas.api.domain.board.dto.BoardCountDto; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; + +import static com.inhabas.api.domain.board.domain.QBaseBoard.baseBoard; +import java.util.List; + +@RequiredArgsConstructor +public class BaseBoardRepositoryImpl implements BaseBoardRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + @Override + public List countRowsGroupByMenuId() { + return queryFactory + .select( + Projections.constructor( + BoardCountDto.class, + baseBoard.menu.id, + baseBoard.id.count() + )) + .from(baseBoard) + .groupBy(baseBoard.menu.id) + .fetch(); + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java index 2abf17bc..72ae7f18 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java @@ -1,14 +1,16 @@ package com.inhabas.api.domain.board.repository; -import java.util.Optional; - +import com.inhabas.api.domain.board.domain.NormalBoard; +import com.inhabas.api.domain.board.domain.NormalBoardType; import com.inhabas.api.domain.board.dto.NormalBoardDto; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -public interface NormalBoardRepositoryCustom { +import java.util.List; +import java.util.Optional; - Page findAllByMenuId(Integer menuId); +public interface NormalBoardRepositoryCustom { - Optional findDtoById(Long id); + List findAllByMemberIdAndTypeAndSearch(Long memberId, NormalBoardType boardType, String search); + List findAllByTypeAndSearch(NormalBoardType boardType, String search); + Optional findByMemberIdAndTypeAndId(Long memberId, NormalBoardType boardType, Long boardId); + Optional findByTypeAndId(NormalBoardType boardType, Long boardId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java index 59d9df4a..05d89ded 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java @@ -1,22 +1,17 @@ package com.inhabas.api.domain.board.repository; -import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember.member; -import static com.inhabas.api.domain.board.domain.QNormalBoard.normalBoard; +import com.inhabas.api.domain.board.domain.NormalBoard; +import com.inhabas.api.domain.board.domain.NormalBoardType; +import com.inhabas.api.domain.board.dto.NormalBoardDto; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; import java.util.List; import java.util.Optional; -import lombok.RequiredArgsConstructor; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; - -import com.inhabas.api.domain.board.dto.BoardDto; -import com.querydsl.core.types.Projections; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.core.types.dsl.Expressions; -import com.querydsl.jpa.impl.JPAQueryFactory; +import static com.inhabas.api.domain.board.domain.QNormalBoard.normalBoard; @RequiredArgsConstructor public class NormalBoardRepositoryImpl implements NormalBoardRepositoryCustom { @@ -24,65 +19,81 @@ public class NormalBoardRepositoryImpl implements NormalBoardRepositoryCustom { private final JPAQueryFactory queryFactory; @Override - public Page findAllByMenuId(Integer menuId, Pageable pageable) { - List results = - queryFactory + public List findAllByMemberIdAndTypeAndSearch(Long memberId, NormalBoardType boardType, String search) { + return queryFactory .select( - Projections.constructor( - BoardDto.class, - normalBoard.id, - normalBoard.title.value, - Expressions.asString("").as("content"), - member.name.value, - normalBoard.menu.id, - normalBoard.dateCreated, - normalBoard.dateUpdated)) + Projections.constructor( + NormalBoardDto.class, + normalBoard.id, + normalBoard.title.value, + normalBoard.writer.name.value, + normalBoard.dateCreated, + normalBoard.dateUpdated, + normalBoard.isPinned)) .from(normalBoard) - .innerJoin(member) - .on(eqMemberId()) - .where(eqMenuId(menuId)) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) + .where(eqMemberId(memberId) + .and(eqNormalBoardType(boardType)) + .and(likeTitle(search)) + .or(likeContent(search))) .orderBy(normalBoard.dateCreated.desc()) .fetch(); - - return new PageImpl<>(results, pageable, this.getCount(menuId)); } - private BooleanExpression eqMenuId(Integer menuId) { - return normalBoard.menu.id.eq(menuId); + @Override + public List findAllByTypeAndSearch(NormalBoardType boardType, String search) { + return queryFactory + .select( + Projections.constructor( + NormalBoardDto.class, + normalBoard.id, + normalBoard.title.value, + normalBoard.writer.name.value, + normalBoard.dateCreated, + normalBoard.dateUpdated, + normalBoard.isPinned)) + .from(normalBoard) + .where(eqNormalBoardType(boardType) + .and(likeTitle(search)) + .or(likeContent(search))) + .orderBy(normalBoard.dateCreated.desc()) + .fetch(); } - // 캐시 필요함. - private Integer getCount(Integer menuId) { - return queryFactory.selectFrom(normalBoard).where(eqMenuId(menuId)).fetch().size(); + @Override + public Optional findByMemberIdAndTypeAndId(Long memberId, NormalBoardType boardType, Long boardId) { + return Optional.ofNullable(queryFactory + .selectFrom(normalBoard) + .where(eqMemberId(memberId) + .and(eqNormalBoardType(boardType)) + .and(normalBoard.id.eq(boardId))) + .orderBy(normalBoard.dateCreated.desc()) + .fetchOne()); } @Override - public Optional findDtoById(Long id) { + public Optional findByTypeAndId(NormalBoardType boardType, Long boardId) { + return Optional.ofNullable(queryFactory + .selectFrom(normalBoard) + .where((eqNormalBoardType(boardType)) + .and(normalBoard.id.eq(boardId))) + .orderBy(normalBoard.dateCreated.desc()) + .fetchOne()); + } - BoardDto target = - queryFactory - .select( - Projections.constructor( - BoardDto.class, - Expressions.asNumber(id).as("id"), - normalBoard.title.value, - normalBoard.content.value, - member.name.value, - normalBoard.menu.id, - normalBoard.dateCreated, - normalBoard.dateUpdated)) - .from(normalBoard) - .innerJoin(member) - .on(eqMemberId()) - .where(normalBoard.id.eq(id)) - .fetchOne(); + private BooleanExpression eqMemberId(Long memberId) { + return normalBoard.writer.id.eq(memberId); + } - return Optional.ofNullable(target); + private BooleanExpression eqNormalBoardType(NormalBoardType normalBoardType) { + return normalBoard.menu.id.eq(normalBoardType.getMenuId()); } - private BooleanExpression eqMemberId() { - return normalBoard.writer.id.eq(member.id); + private BooleanExpression likeTitle(String search) { + return normalBoard.title.value.like(search); } + + private BooleanExpression likeContent(String search) { + return normalBoard.content.value.like(search); + } + } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java index fb00d389..c4767a46 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java @@ -2,7 +2,6 @@ import com.inhabas.api.domain.board.domain.NormalBoardType; -import com.inhabas.api.domain.board.dto.BoardCountDto; import com.inhabas.api.domain.board.dto.NormalBoardDetailDto; import com.inhabas.api.domain.board.dto.NormalBoardDto; import com.inhabas.api.domain.board.dto.SaveNormalBoardDto; @@ -11,8 +10,6 @@ public interface NormalBoardService { - List getPostCount(); - List getPosts(Long memberId, NormalBoardType boardType, String search); NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Long boardId); diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java index 91a512e6..e8a994c8 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java @@ -1,30 +1,24 @@ package com.inhabas.api.domain.board.usecase; -import javax.transaction.Transactional; - +import com.inhabas.api.auth.domain.error.businessException.NotFoundException; +import com.inhabas.api.domain.board.domain.NormalBoard; import com.inhabas.api.domain.board.domain.NormalBoardType; -import com.inhabas.api.domain.board.dto.BoardCountDto; import com.inhabas.api.domain.board.dto.NormalBoardDetailDto; +import com.inhabas.api.domain.board.dto.NormalBoardDto; import com.inhabas.api.domain.board.dto.SaveNormalBoardDto; import com.inhabas.api.domain.board.exception.S3UploadFailedException; -import com.inhabas.api.domain.board.repository.BaseBoardRepository; +import com.inhabas.api.domain.board.repository.NormalBoardRepository; import com.inhabas.api.domain.file.domain.BoardFile; import com.inhabas.api.domain.file.dto.FileDownloadDto; import com.inhabas.api.domain.file.usecase.S3Service; import com.inhabas.api.domain.menu.domain.Menu; +import com.inhabas.api.domain.menu.repository.MenuRepository; import com.inhabas.api.global.util.FileUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; - import org.springframework.stereotype.Service; -import com.inhabas.api.auth.domain.error.businessException.NotFoundException; -import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; -import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.board.dto.NormalBoardDto; -import com.inhabas.api.domain.board.repository.NormalBoardRepository; -import com.inhabas.api.domain.menu.repository.MenuRepository; - +import javax.transaction.Transactional; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -36,36 +30,19 @@ public class NormalNormalBoardServiceImpl implements NormalBoardService { private final NormalBoardRepository normalBoardRepository; - private final BaseBoardRepository baseBoardRepository; private final MenuRepository menuRepository; - private final MemberRepository memberRepository; private final S3Service s3Service; - @Override - public List getPostCount() { - return baseBoardRepository.countRowsGroupByMenuId(); - } - - @Override public List getPosts(Long memberId, NormalBoardType boardType, String search) { - List normalBoardList; + List normalBoardList; if (boardType.equals(NormalBoardType.SUGGEST)) { normalBoardList = normalBoardRepository.findAllByMemberIdAndTypeAndSearch(memberId, boardType, search); } else { normalBoardList = normalBoardRepository.findAllByTypeAndSearch(boardType, search); } - - return normalBoardList.stream().map(board -> NormalBoardDto.builder() - .id(board.getId()) - .title(board.getTitle()) - .isPinned(board.getPinned()) - .writerName(board.getWriter().getName()) - .dateCreated(board.getDateCreated()) - .dateUpdated(board.getDateUpdated()) - .build()) - .collect(Collectors.toList()); + return normalBoardList; } @Override @@ -73,9 +50,9 @@ public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Lo NormalBoard normalBoard; List fileDownloadDtoList = null; if (boardType.equals(NormalBoardType.SUGGEST)) { - normalBoard = normalBoardRepository.findMyByMemberIdAndTypeAndId(memberId, boardType, boardId); + normalBoard = normalBoardRepository.findByMemberIdAndTypeAndId(memberId, boardType, boardId).orElseThrow(NotFoundException::new); } else { - normalBoard = normalBoardRepository.findByTypeAndId(boardType, boardId); + normalBoard = normalBoardRepository.findByTypeAndId(boardType, boardId).orElseThrow(NotFoundException::new); } if (!normalBoard.getFiles().isEmpty()) { fileDownloadDtoList = @@ -123,7 +100,7 @@ public void delete(Long boardId) { } - private Long updateNormalBoardFiles( + private void updateNormalBoardFiles( SaveNormalBoardDto saveNormalBoardDto, NormalBoardType normalBoardType, NormalBoard normalBoard) { final String DIR_NAME = "/" + normalBoardType.getBoardType(); List updateFiles = new ArrayList<>(); @@ -156,7 +133,7 @@ private Long updateNormalBoardFiles( } normalBoard.updateFiles(updateFiles); - return normalBoardRepository.save(normalBoard).getId(); + normalBoardRepository.save(normalBoard); } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java index cae468c0..511434d8 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java @@ -53,7 +53,7 @@ public ContestBoard( LocalDate deadline) { this.title = new Title(title); - this.content = new Content(contents); +// this.content = new Content(contents); this.association = new Association(association); this.topic = new Topic(topic); this.start = start; diff --git a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java index 4f88ffe4..34a4d925 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java @@ -3,6 +3,7 @@ import com.inhabas.api.auth.domain.error.ErrorResponse; import com.inhabas.api.domain.board.domain.NormalBoardType; import com.inhabas.api.domain.board.dto.*; +import com.inhabas.api.domain.board.repository.BaseBoardRepository; import com.inhabas.api.domain.board.usecase.NormalBoardService; import com.inhabas.api.global.dto.PageInfoDto; import com.inhabas.api.global.dto.PagedResponseDto; @@ -37,7 +38,8 @@ @RequiredArgsConstructor public class NormalBoardController { - private final NormalBoardService normalBoardService; + private final NormalBoardService normalBoardService; + private final BaseBoardRepository baseBoardRepository; @Operation(summary = "게시판 종류 당 글 개수 조회") @ApiResponses( @@ -52,7 +54,7 @@ public class NormalBoardController { ) @SecurityRequirements(value = {}) public ResponseEntity> getBoardList() { - return ResponseEntity.ok(normalBoardService.getPostCount()); + return ResponseEntity.ok(baseBoardRepository.countRowsGroupByMenuId()); } @Operation(summary = "게시글 목록 조회") From e2225152ba2f8f8a123f82e0ab912122d45a4e35 Mon Sep 17 00:00:00 2001 From: whitemark Date: Tue, 13 Feb 2024 11:07:24 +0900 Subject: [PATCH 06/19] =?UTF-8?q?[feature/#233]=20NormalBoard,=20Board=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/domain/board/domain/NormalBoard.java | 75 ---------- .../domain/board/domain/NormalBoardType.java | 26 ---- .../board/dto/NormalBoardDetailDto.java | 65 -------- .../api/domain/board/dto/NormalBoardDto.java | 47 ------ .../domain/board/dto/SaveNormalBoardDto.java | 34 ----- .../api/domain/board/dto/UpdateBoardDto.java | 29 ---- .../repository/NormalBoardRepository.java | 8 - .../NormalBoardRepositoryCustom.java | 16 -- .../repository/NormalBoardRepositoryImpl.java | 99 ------------- .../board/usecase/NormalBoardService.java | 22 --- .../usecase/NormalNormalBoardServiceImpl.java | 139 ------------------ .../domain/contest/domain/ContestBoard.java | 3 +- .../api/web/NormalBoardController.java | 10 +- 13 files changed, 6 insertions(+), 567 deletions(-) delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDetailDto.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDto.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveNormalBoardDto.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/dto/UpdateBoardDto.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepository.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java delete mode 100644 resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java deleted file mode 100644 index 5ee87cb5..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.inhabas.api.domain.board.domain; - -import com.inhabas.api.domain.board.domain.valueObject.Content; -import com.inhabas.api.domain.board.domain.valueObject.Title; -import com.inhabas.api.domain.comment.domain.Comment; -import com.inhabas.api.domain.file.domain.BoardFile; -import com.inhabas.api.domain.menu.domain.Menu; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import javax.persistence.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -@Entity -@Table(name = "NORMAL_BOARD") -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@EntityListeners(AuditingEntityListener.class) -@Inheritance(strategy = InheritanceType.JOINED) -@DiscriminatorValue("NORMAL") -public class NormalBoard extends BaseBoard { - - @Embedded private Content content; - - @Column - private Boolean isPinned = false; - - @OneToMany(mappedBy = "parentBoard", cascade = CascadeType.ALL, orphanRemoval = true) - private List comments = new ArrayList<>(); - - /* constructor */ - - public NormalBoard(String title, Menu menu, String content, Boolean isPinned) { - super(title, menu); - this.content = new Content(content); - this.isPinned = isPinned; - } - - /* getter */ - - public Boolean getPinned() { - return isPinned; - } - - public String getContent() { - return content.getValue(); - } - - public List getFiles() { - return Collections.unmodifiableList(files); - } - - /* relation method */ - - public void updateText(String title, String content) { - this.title = new Title(title); - this.content = new Content(content); - } - - public void updateFiles(List files) { - - if (this.files != null) { - this.files.clear(); - } else { - this.files = new ArrayList<>(); - } - - for (BoardFile file : files) { - addFile(file); - } - } - -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java deleted file mode 100644 index 142d09a3..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoardType.java +++ /dev/null @@ -1,26 +0,0 @@ - package com.inhabas.api.domain.board.domain; - -public enum NormalBoardType { - NOTICE("notice", 4), - FREE("free", 5), - QUESTION("question", 6), - SUGGEST("suggest", 7), - STORAGE("storage", 8), - EXECUTIVE("executive", 9); - - private String boardType; - private int menuId; - - NormalBoardType(String boardType, int menuId) { - this.boardType = boardType; - this.menuId = menuId; - } - - public String getBoardType() { - return boardType; - } - - public int getMenuId() { - return menuId; - } -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDetailDto.java deleted file mode 100644 index 234d87e7..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDetailDto.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.inhabas.api.domain.board.dto; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.file.dto.FileDownloadDto; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import java.time.LocalDateTime; -import java.util.List; - -@Getter -@NoArgsConstructor -public class NormalBoardDetailDto { - - @NotNull - @Positive - private Long id; - - @NotBlank - private String title; - - @NotBlank private String content; - - @NotBlank private String writerName; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") - @Schema(type = "string", example = "2024-11-01T00:00:00") - private LocalDateTime dateCreated; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") - @Schema(type = "string", example = "2024-11-01T00:00:00") - private LocalDateTime dateUpdated; - - @NotNull private List files; - - @NotNull - private Boolean isPinned; - - @Builder - public NormalBoardDetailDto( - Long id, - String title, - String content, - String writerName, - LocalDateTime dateCreated, - LocalDateTime dateUpdated, - List files, - Boolean isPinned) { - this.id = id; - this.title = title; - this.content = content; - this.writerName = writerName; - this.dateCreated = dateCreated; - this.dateUpdated = dateUpdated; - this.files = files; - this.isPinned = isPinned; - } -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDto.java deleted file mode 100644 index 1161fffc..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/NormalBoardDto.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.inhabas.api.domain.board.dto; - -import java.time.LocalDateTime; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonUnwrapped; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -@Getter -@NoArgsConstructor -public class NormalBoardDto { - private Long id; - private String title; - private String writerName; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") - @Schema(type = "string", example = "2024-11-01T00:00:00") - private LocalDateTime dateCreated; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") - @Schema(type = "string", example = "2024-11-01T00:00:00") - private LocalDateTime dateUpdated; - - @NotNull - private Boolean isPinned; - - @Builder - public NormalBoardDto(Long id, String title, String writerName, LocalDateTime dateCreated, LocalDateTime dateUpdated, Boolean isPinned) { - this.id = id; - this.title = title; - this.writerName = writerName; - this.dateCreated = dateCreated; - this.dateUpdated = dateUpdated; - this.isPinned = isPinned; - } - -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveNormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveNormalBoardDto.java deleted file mode 100644 index c3634a0d..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveNormalBoardDto.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.inhabas.api.domain.board.dto; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -import org.springframework.web.multipart.MultipartFile; - -import java.util.ArrayList; -import java.util.List; - -@Getter -@NoArgsConstructor -public class SaveNormalBoardDto { - @NotBlank - private String title; - - @NotBlank - private String content; - - private List files; - - @NotNull - private Boolean isPinned; - - public SaveNormalBoardDto(String title, String content, List files, Boolean isPinned) { - this.title = title; - this.content = content; - this.files = (files != null) ? files : new ArrayList<>(); - this.isPinned = isPinned; - } -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/UpdateBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/UpdateBoardDto.java deleted file mode 100644 index 8f5aaec8..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/UpdateBoardDto.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.inhabas.api.domain.board.dto; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Getter -@Setter -@NoArgsConstructor -public class UpdateBoardDto { - @NotNull private Long id; - - @NotBlank(message = "제목을 입력하세요.") - @Size(max = 100, message = "제목은 최대 100자입니다.") - private String title; - - @NotBlank(message = "본문을 입력하세요") - private String contents; - - public UpdateBoardDto(Long id, String title, String contents) { - this.id = id; - this.title = title; - this.contents = contents; - } -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepository.java deleted file mode 100644 index 49122501..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.inhabas.api.domain.board.repository; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.inhabas.api.domain.board.domain.NormalBoard; - -public interface NormalBoardRepository - extends JpaRepository, NormalBoardRepositoryCustom {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java deleted file mode 100644 index 72ae7f18..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.inhabas.api.domain.board.repository; - -import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.board.domain.NormalBoardType; -import com.inhabas.api.domain.board.dto.NormalBoardDto; - -import java.util.List; -import java.util.Optional; - -public interface NormalBoardRepositoryCustom { - - List findAllByMemberIdAndTypeAndSearch(Long memberId, NormalBoardType boardType, String search); - List findAllByTypeAndSearch(NormalBoardType boardType, String search); - Optional findByMemberIdAndTypeAndId(Long memberId, NormalBoardType boardType, Long boardId); - Optional findByTypeAndId(NormalBoardType boardType, Long boardId); -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java deleted file mode 100644 index 05d89ded..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.inhabas.api.domain.board.repository; - -import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.board.domain.NormalBoardType; -import com.inhabas.api.domain.board.dto.NormalBoardDto; -import com.querydsl.core.types.Projections; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.jpa.impl.JPAQueryFactory; -import lombok.RequiredArgsConstructor; - -import java.util.List; -import java.util.Optional; - -import static com.inhabas.api.domain.board.domain.QNormalBoard.normalBoard; - -@RequiredArgsConstructor -public class NormalBoardRepositoryImpl implements NormalBoardRepositoryCustom { - - private final JPAQueryFactory queryFactory; - - @Override - public List findAllByMemberIdAndTypeAndSearch(Long memberId, NormalBoardType boardType, String search) { - return queryFactory - .select( - Projections.constructor( - NormalBoardDto.class, - normalBoard.id, - normalBoard.title.value, - normalBoard.writer.name.value, - normalBoard.dateCreated, - normalBoard.dateUpdated, - normalBoard.isPinned)) - .from(normalBoard) - .where(eqMemberId(memberId) - .and(eqNormalBoardType(boardType)) - .and(likeTitle(search)) - .or(likeContent(search))) - .orderBy(normalBoard.dateCreated.desc()) - .fetch(); - } - - @Override - public List findAllByTypeAndSearch(NormalBoardType boardType, String search) { - return queryFactory - .select( - Projections.constructor( - NormalBoardDto.class, - normalBoard.id, - normalBoard.title.value, - normalBoard.writer.name.value, - normalBoard.dateCreated, - normalBoard.dateUpdated, - normalBoard.isPinned)) - .from(normalBoard) - .where(eqNormalBoardType(boardType) - .and(likeTitle(search)) - .or(likeContent(search))) - .orderBy(normalBoard.dateCreated.desc()) - .fetch(); - } - - @Override - public Optional findByMemberIdAndTypeAndId(Long memberId, NormalBoardType boardType, Long boardId) { - return Optional.ofNullable(queryFactory - .selectFrom(normalBoard) - .where(eqMemberId(memberId) - .and(eqNormalBoardType(boardType)) - .and(normalBoard.id.eq(boardId))) - .orderBy(normalBoard.dateCreated.desc()) - .fetchOne()); - } - - @Override - public Optional findByTypeAndId(NormalBoardType boardType, Long boardId) { - return Optional.ofNullable(queryFactory - .selectFrom(normalBoard) - .where((eqNormalBoardType(boardType)) - .and(normalBoard.id.eq(boardId))) - .orderBy(normalBoard.dateCreated.desc()) - .fetchOne()); - } - - private BooleanExpression eqMemberId(Long memberId) { - return normalBoard.writer.id.eq(memberId); - } - - private BooleanExpression eqNormalBoardType(NormalBoardType normalBoardType) { - return normalBoard.menu.id.eq(normalBoardType.getMenuId()); - } - - private BooleanExpression likeTitle(String search) { - return normalBoard.title.value.like(search); - } - - private BooleanExpression likeContent(String search) { - return normalBoard.content.value.like(search); - } - -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java deleted file mode 100644 index c4767a46..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalBoardService.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.inhabas.api.domain.board.usecase; - -import com.inhabas.api.domain.board.domain.NormalBoardType; - -import com.inhabas.api.domain.board.dto.NormalBoardDetailDto; -import com.inhabas.api.domain.board.dto.NormalBoardDto; -import com.inhabas.api.domain.board.dto.SaveNormalBoardDto; - -import java.util.List; - -public interface NormalBoardService { - - List getPosts(Long memberId, NormalBoardType boardType, String search); - - NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Long boardId); - - Long write(Long memberId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto); - - void update(Long boardId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto); - - void delete(Long boardId); -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java deleted file mode 100644 index e8a994c8..00000000 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/NormalNormalBoardServiceImpl.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.inhabas.api.domain.board.usecase; - -import com.inhabas.api.auth.domain.error.businessException.NotFoundException; -import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.board.domain.NormalBoardType; -import com.inhabas.api.domain.board.dto.NormalBoardDetailDto; -import com.inhabas.api.domain.board.dto.NormalBoardDto; -import com.inhabas.api.domain.board.dto.SaveNormalBoardDto; -import com.inhabas.api.domain.board.exception.S3UploadFailedException; -import com.inhabas.api.domain.board.repository.NormalBoardRepository; -import com.inhabas.api.domain.file.domain.BoardFile; -import com.inhabas.api.domain.file.dto.FileDownloadDto; -import com.inhabas.api.domain.file.usecase.S3Service; -import com.inhabas.api.domain.menu.domain.Menu; -import com.inhabas.api.domain.menu.repository.MenuRepository; -import com.inhabas.api.global.util.FileUtil; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import javax.transaction.Transactional; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -@Service -@Slf4j -@Transactional -@RequiredArgsConstructor -public class NormalNormalBoardServiceImpl implements NormalBoardService { - - private final NormalBoardRepository normalBoardRepository; - private final MenuRepository menuRepository; - private final S3Service s3Service; - - - @Override - public List getPosts(Long memberId, NormalBoardType boardType, String search) { - List normalBoardList; - if (boardType.equals(NormalBoardType.SUGGEST)) { - normalBoardList = normalBoardRepository.findAllByMemberIdAndTypeAndSearch(memberId, boardType, search); - } else { - normalBoardList = normalBoardRepository.findAllByTypeAndSearch(boardType, search); - } - return normalBoardList; - } - - @Override - public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Long boardId) { - NormalBoard normalBoard; - List fileDownloadDtoList = null; - if (boardType.equals(NormalBoardType.SUGGEST)) { - normalBoard = normalBoardRepository.findByMemberIdAndTypeAndId(memberId, boardType, boardId).orElseThrow(NotFoundException::new); - } else { - normalBoard = normalBoardRepository.findByTypeAndId(boardType, boardId).orElseThrow(NotFoundException::new); - } - if (!normalBoard.getFiles().isEmpty()) { - fileDownloadDtoList = - normalBoard.getFiles().stream() - .map(obj -> FileDownloadDto.builder().name(obj.getName()).url(obj.getUrl()).build()) - .collect(Collectors.toList()); - } - - - return NormalBoardDetailDto.builder() - .id(normalBoard.getId()) - .title(normalBoard.getTitle()) - .content(normalBoard.getContent()) - .writerName(normalBoard.getWriter().getName()) - .dateCreated(normalBoard.getDateCreated()) - .dateUpdated(normalBoard.getDateUpdated()) - .files(fileDownloadDtoList) - .isPinned(normalBoard.getPinned()) - .build(); - } - - @Override - public Long write(Long memberId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto) { - - Menu menu = menuRepository.findById(normalBoardType.getMenuId()).orElseThrow(NotFoundException::new); - - NormalBoard normalBoard = - new NormalBoard(saveNormalBoardDto.getTitle(), menu, saveNormalBoardDto.getContent(), saveNormalBoardDto.getIsPinned()); - - return normalBoardRepository.save(normalBoard).getId(); - } - - @Override - public void update(Long boardId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto) { - - NormalBoard normalBoard = - normalBoardRepository.findById(boardId).orElseThrow(NotFoundException::new); - - updateNormalBoardFiles(saveNormalBoardDto, normalBoardType, normalBoard); - } - - @Override - public void delete(Long boardId) { - normalBoardRepository.deleteById(boardId); - } - - - private void updateNormalBoardFiles( - SaveNormalBoardDto saveNormalBoardDto, NormalBoardType normalBoardType, NormalBoard normalBoard) { - final String DIR_NAME = "/" + normalBoardType.getBoardType(); - List updateFiles = new ArrayList<>(); - List urlListForDelete = new ArrayList<>(); - - if (saveNormalBoardDto.getFiles() != null) { - normalBoard.updateText(saveNormalBoardDto.getTitle(), saveNormalBoardDto.getContent()); - try { - updateFiles = - saveNormalBoardDto.getFiles().stream() - .map( - file -> { - String path = FileUtil.generateFileName(file, DIR_NAME); - String url = s3Service.uploadS3File(file, path); - urlListForDelete.add(url); - return BoardFile.builder() - .name(file.getOriginalFilename()) - .url(url) - .board(normalBoard) - .build(); - }) - .collect(Collectors.toList()); - - } catch (RuntimeException e) { - for (String url : urlListForDelete) { - s3Service.deleteS3File(url); - } - throw new S3UploadFailedException(); - } - } - - normalBoard.updateFiles(updateFiles); - normalBoardRepository.save(normalBoard); - } - -} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java index 511434d8..975dd368 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java @@ -7,13 +7,12 @@ import javax.persistence.Entity; import javax.persistence.Table; +import com.inhabas.api.domain.normalBoard.domain.NormalBoard; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.board.domain.valueObject.Content; import com.inhabas.api.domain.board.domain.valueObject.Title; import com.inhabas.api.domain.contest.domain.valueObject.Association; import com.inhabas.api.domain.contest.domain.valueObject.Topic; diff --git a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java index 34a4d925..9ea41b51 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java @@ -1,10 +1,13 @@ package com.inhabas.api.web; import com.inhabas.api.auth.domain.error.ErrorResponse; -import com.inhabas.api.domain.board.domain.NormalBoardType; import com.inhabas.api.domain.board.dto.*; import com.inhabas.api.domain.board.repository.BaseBoardRepository; -import com.inhabas.api.domain.board.usecase.NormalBoardService; +import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDetailDto; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; +import com.inhabas.api.domain.normalBoard.dto.SaveNormalBoardDto; +import com.inhabas.api.domain.normalBoard.usecase.NormalBoardService; import com.inhabas.api.global.dto.PageInfoDto; import com.inhabas.api.global.dto.PagedResponseDto; import com.inhabas.api.global.util.PageUtil; @@ -49,9 +52,6 @@ public class NormalBoardController { content = {@Content(schema = @Schema(implementation = BoardCountDto.class))}), }) @GetMapping("/board/count") - @PreAuthorize( - "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD_LIST)" - ) @SecurityRequirements(value = {}) public ResponseEntity> getBoardList() { return ResponseEntity.ok(baseBoardRepository.countRowsGroupByMenuId()); From b3457849a3573ed067e87cd0951d7c53e7787fdc Mon Sep 17 00:00:00 2001 From: whitemark Date: Thu, 15 Feb 2024 00:00:10 +0900 Subject: [PATCH 07/19] =?UTF-8?q?[feature/#233]=20NormalBoard,=20Board=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../normalBoard/domain/NormalBoard.java | 76 ++++++++++ .../normalBoard/domain/NormalBoardType.java | 26 ++++ .../normalBoard/dto/NormalBoardDetailDto.java | 65 ++++++++ .../normalBoard/dto/NormalBoardDto.java | 51 +++++++ .../normalBoard/dto/SaveNormalBoardDto.java | 32 ++++ .../repository/NormalBoardRepository.java | 7 + .../NormalBoardRepositoryCustom.java | 16 ++ .../repository/NormalBoardRepositoryImpl.java | 100 +++++++++++++ .../usecase/NormalBoardService.java | 21 +++ .../usecase/NormalNormalBoardServiceImpl.java | 139 ++++++++++++++++++ 10 files changed, 533 insertions(+) create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardType.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepository.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalNormalBoardServiceImpl.java diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java new file mode 100644 index 00000000..57a51542 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java @@ -0,0 +1,76 @@ +package com.inhabas.api.domain.normalBoard.domain; + +import com.inhabas.api.domain.board.domain.BaseBoard; +import com.inhabas.api.domain.board.domain.valueObject.Content; +import com.inhabas.api.domain.board.domain.valueObject.Title; +import com.inhabas.api.domain.comment.domain.Comment; +import com.inhabas.api.domain.file.domain.BoardFile; +import com.inhabas.api.domain.menu.domain.Menu; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Entity +@Table(name = "NORMAL_BOARD") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@EntityListeners(AuditingEntityListener.class) +@Inheritance(strategy = InheritanceType.JOINED) +@DiscriminatorValue("NORMAL") +public class NormalBoard extends BaseBoard { + + @Embedded private Content content; + + @Column + private Boolean isPinned = false; + + @OneToMany(mappedBy = "parentBoard", cascade = CascadeType.ALL, orphanRemoval = true) + private List comments = new ArrayList<>(); + + /* constructor */ + + public NormalBoard(String title, Menu menu, String content, Boolean isPinned) { + super(title, menu); + this.content = new Content(content); + this.isPinned = isPinned; + } + + /* getter */ + + public Boolean getPinned() { + return isPinned; + } + + public String getContent() { + return content.getValue(); + } + + public List getFiles() { + return Collections.unmodifiableList(files); + } + + /* relation method */ + + public void updateText(String title, String content) { + this.title = new Title(title); + this.content = new Content(content); + } + + public void updateFiles(List files) { + + if (this.files != null) { + this.files.clear(); + } else { + this.files = new ArrayList<>(); + } + + for (BoardFile file : files) { + addFile(file); + } + } + +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardType.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardType.java new file mode 100644 index 00000000..a1cd26e2 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardType.java @@ -0,0 +1,26 @@ + package com.inhabas.api.domain.normalBoard.domain; + +public enum NormalBoardType { + NOTICE("notice", 4), + FREE("free", 5), + QUESTION("question", 6), + SUGGEST("suggest", 7), + STORAGE("storage", 8), + EXECUTIVE("executive", 9); + + private String boardType; + private int menuId; + + NormalBoardType(String boardType, int menuId) { + this.boardType = boardType; + this.menuId = menuId; + } + + public String getBoardType() { + return boardType; + } + + public int getMenuId() { + return menuId; + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java new file mode 100644 index 00000000..ff5af0a9 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java @@ -0,0 +1,65 @@ +package com.inhabas.api.domain.normalBoard.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.domain.file.dto.FileDownloadDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import java.time.LocalDateTime; +import java.util.List; + +@Getter +@NoArgsConstructor +public class NormalBoardDetailDto { + + @NotNull + @Positive + private Long id; + + @NotBlank + private String title; + + @NotBlank private String content; + + @NotBlank private String writerName; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateCreated; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateUpdated; + + @NotNull private List files; + + @NotNull + private Boolean isPinned; + + @Builder + public NormalBoardDetailDto( + Long id, + String title, + String content, + String writerName, + LocalDateTime dateCreated, + LocalDateTime dateUpdated, + List files, + Boolean isPinned) { + this.id = id; + this.title = title; + this.content = content; + this.writerName = writerName; + this.dateCreated = dateCreated; + this.dateUpdated = dateUpdated; + this.files = files; + this.isPinned = isPinned; + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java new file mode 100644 index 00000000..c6108ed2 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java @@ -0,0 +1,51 @@ +package com.inhabas.api.domain.normalBoard.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +public class NormalBoardDto { + + @NotNull + @Positive + private Long id; + + @NotBlank + private String title; + + @NotBlank + private String writerName; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateCreated; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateUpdated; + + @NotNull + private Boolean isPinned; + + @Builder + public NormalBoardDto(Long id, String title, String writerName, LocalDateTime dateCreated, LocalDateTime dateUpdated, Boolean isPinned) { + this.id = id; + this.title = title; + this.writerName = writerName; + this.dateCreated = dateCreated; + this.dateUpdated = dateUpdated; + this.isPinned = isPinned; + } + +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java new file mode 100644 index 00000000..3e7b4040 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java @@ -0,0 +1,32 @@ +package com.inhabas.api.domain.normalBoard.dto; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.List; + +@Getter +@NoArgsConstructor +public class SaveNormalBoardDto { + @NotBlank + private String title; + + @NotBlank + private String content; + + private List files; + + @NotNull + private Boolean isPinned; + + public SaveNormalBoardDto(String title, String content, List files, Boolean isPinned) { + this.title = title; + this.content = content; + this.files = (files != null) ? files : new ArrayList<>(); + this.isPinned = isPinned; + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepository.java new file mode 100644 index 00000000..676e8f73 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepository.java @@ -0,0 +1,7 @@ +package com.inhabas.api.domain.normalBoard.repository; + +import com.inhabas.api.domain.normalBoard.domain.NormalBoard; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface NormalBoardRepository + extends JpaRepository, NormalBoardRepositoryCustom {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java new file mode 100644 index 00000000..7b501db5 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java @@ -0,0 +1,16 @@ +package com.inhabas.api.domain.normalBoard.repository; + +import com.inhabas.api.domain.normalBoard.domain.NormalBoard; +import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; + +import java.util.List; +import java.util.Optional; + +public interface NormalBoardRepositoryCustom { + + List findAllByMemberIdAndTypeAndSearch(Long memberId, NormalBoardType boardType, String search); + List findAllByTypeAndSearch(NormalBoardType boardType, String search); + Optional findByMemberIdAndTypeAndId(Long memberId, NormalBoardType boardType, Long boardId); + Optional findByTypeAndId(NormalBoardType boardType, Long boardId); +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java new file mode 100644 index 00000000..5d998068 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java @@ -0,0 +1,100 @@ +package com.inhabas.api.domain.normalBoard.repository; + +import com.inhabas.api.domain.normalBoard.domain.NormalBoard; +import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; + +import java.util.List; +import java.util.Optional; + +import static com.inhabas.api.domain.normalBoard.domain.QNormalBoard.normalBoard; + + +@RequiredArgsConstructor +public class NormalBoardRepositoryImpl implements NormalBoardRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + @Override + public List findAllByMemberIdAndTypeAndSearch(Long memberId, NormalBoardType boardType, String search) { + return queryFactory + .select( + Projections.constructor( + NormalBoardDto.class, + normalBoard.id, + normalBoard.title.value, + normalBoard.writer.name.value, + normalBoard.dateCreated, + normalBoard.dateUpdated, + normalBoard.isPinned)) + .from(normalBoard) + .where(eqMemberId(memberId) + .and(eqNormalBoardType(boardType)) + .and(likeTitle(search)) + .or(likeContent(search))) + .orderBy(normalBoard.dateCreated.desc()) + .fetch(); + } + + @Override + public List findAllByTypeAndSearch(NormalBoardType boardType, String search) { + return queryFactory + .select( + Projections.constructor( + NormalBoardDto.class, + normalBoard.id, + normalBoard.title.value, + normalBoard.writer.name.value, + normalBoard.dateCreated, + normalBoard.dateUpdated, + normalBoard.isPinned)) + .from(normalBoard) + .where(eqNormalBoardType(boardType) + .and(likeTitle(search)) + .or(likeContent(search))) + .orderBy(normalBoard.dateCreated.desc()) + .fetch(); + } + + @Override + public Optional findByMemberIdAndTypeAndId(Long memberId, NormalBoardType boardType, Long boardId) { + return Optional.ofNullable(queryFactory + .selectFrom(normalBoard) + .where(eqMemberId(memberId) + .and(eqNormalBoardType(boardType)) + .and(normalBoard.id.eq(boardId))) + .orderBy(normalBoard.dateCreated.desc()) + .fetchOne()); + } + + @Override + public Optional findByTypeAndId(NormalBoardType boardType, Long boardId) { + return Optional.ofNullable(queryFactory + .selectFrom(normalBoard) + .where((eqNormalBoardType(boardType)) + .and(normalBoard.id.eq(boardId))) + .orderBy(normalBoard.dateCreated.desc()) + .fetchOne()); + } + + private BooleanExpression eqMemberId(Long memberId) { + return normalBoard.writer.id.eq(memberId); + } + + private BooleanExpression eqNormalBoardType(NormalBoardType normalBoardType) { + return normalBoard.menu.id.eq(normalBoardType.getMenuId()); + } + + private BooleanExpression likeTitle(String search) { + return normalBoard.title.value.like(search); + } + + private BooleanExpression likeContent(String search) { + return normalBoard.content.value.like(search); + } + +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java new file mode 100644 index 00000000..17fe6802 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java @@ -0,0 +1,21 @@ +package com.inhabas.api.domain.normalBoard.usecase; + +import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDetailDto; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; +import com.inhabas.api.domain.normalBoard.dto.SaveNormalBoardDto; + +import java.util.List; + +public interface NormalBoardService { + + List getPosts(Long memberId, NormalBoardType boardType, String search); + + NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Long boardId); + + Long write(Long memberId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto); + + void update(Long boardId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto); + + void delete(Long boardId); +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalNormalBoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalNormalBoardServiceImpl.java new file mode 100644 index 00000000..a27815ee --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalNormalBoardServiceImpl.java @@ -0,0 +1,139 @@ +package com.inhabas.api.domain.normalBoard.usecase; + +import com.inhabas.api.auth.domain.error.businessException.NotFoundException; +import com.inhabas.api.domain.board.exception.S3UploadFailedException; +import com.inhabas.api.domain.file.domain.BoardFile; +import com.inhabas.api.domain.file.dto.FileDownloadDto; +import com.inhabas.api.domain.file.usecase.S3Service; +import com.inhabas.api.domain.menu.domain.Menu; +import com.inhabas.api.domain.menu.repository.MenuRepository; +import com.inhabas.api.domain.normalBoard.domain.NormalBoard; +import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDetailDto; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; +import com.inhabas.api.domain.normalBoard.dto.SaveNormalBoardDto; +import com.inhabas.api.domain.normalBoard.repository.NormalBoardRepository; +import com.inhabas.api.global.util.FileUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@Slf4j +@Transactional +@RequiredArgsConstructor +public class NormalNormalBoardServiceImpl implements NormalBoardService { + + private final NormalBoardRepository normalBoardRepository; + private final MenuRepository menuRepository; + private final S3Service s3Service; + + + @Override + public List getPosts(Long memberId, NormalBoardType boardType, String search) { + List normalBoardList; + if (boardType.equals(NormalBoardType.SUGGEST)) { + normalBoardList = normalBoardRepository.findAllByMemberIdAndTypeAndSearch(memberId, boardType, search); + } else { + normalBoardList = normalBoardRepository.findAllByTypeAndSearch(boardType, search); + } + return normalBoardList; + } + + @Override + public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Long boardId) { + NormalBoard normalBoard; + List fileDownloadDtoList = null; + if (boardType.equals(NormalBoardType.SUGGEST)) { + normalBoard = normalBoardRepository.findByMemberIdAndTypeAndId(memberId, boardType, boardId).orElseThrow(NotFoundException::new); + } else { + normalBoard = normalBoardRepository.findByTypeAndId(boardType, boardId).orElseThrow(NotFoundException::new); + } + if (!normalBoard.getFiles().isEmpty()) { + fileDownloadDtoList = + normalBoard.getFiles().stream() + .map(obj -> FileDownloadDto.builder().name(obj.getName()).url(obj.getUrl()).build()) + .collect(Collectors.toList()); + } + + + return NormalBoardDetailDto.builder() + .id(normalBoard.getId()) + .title(normalBoard.getTitle()) + .content(normalBoard.getContent()) + .writerName(normalBoard.getWriter().getName()) + .dateCreated(normalBoard.getDateCreated()) + .dateUpdated(normalBoard.getDateUpdated()) + .files(fileDownloadDtoList) + .isPinned(normalBoard.getPinned()) + .build(); + } + + @Override + public Long write(Long memberId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto) { + + Menu menu = menuRepository.findById(normalBoardType.getMenuId()).orElseThrow(NotFoundException::new); + + NormalBoard normalBoard = + new NormalBoard(saveNormalBoardDto.getTitle(), menu, saveNormalBoardDto.getContent(), saveNormalBoardDto.getIsPinned()); + + return normalBoardRepository.save(normalBoard).getId(); + } + + @Override + public void update(Long boardId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto) { + + NormalBoard normalBoard = + normalBoardRepository.findById(boardId).orElseThrow(NotFoundException::new); + + updateNormalBoardFiles(saveNormalBoardDto, normalBoardType, normalBoard); + } + + @Override + public void delete(Long boardId) { + normalBoardRepository.deleteById(boardId); + } + + + private void updateNormalBoardFiles( + SaveNormalBoardDto saveNormalBoardDto, NormalBoardType normalBoardType, NormalBoard normalBoard) { + final String DIR_NAME = "/" + normalBoardType.getBoardType(); + List updateFiles = new ArrayList<>(); + List urlListForDelete = new ArrayList<>(); + + if (saveNormalBoardDto.getFiles() != null) { + normalBoard.updateText(saveNormalBoardDto.getTitle(), saveNormalBoardDto.getContent()); + try { + updateFiles = + saveNormalBoardDto.getFiles().stream() + .map( + file -> { + String path = FileUtil.generateFileName(file, DIR_NAME); + String url = s3Service.uploadS3File(file, path); + urlListForDelete.add(url); + return BoardFile.builder() + .name(file.getOriginalFilename()) + .url(url) + .board(normalBoard) + .build(); + }) + .collect(Collectors.toList()); + + } catch (RuntimeException e) { + for (String url : urlListForDelete) { + s3Service.deleteS3File(url); + } + throw new S3UploadFailedException(); + } + } + + normalBoard.updateFiles(updateFiles); + normalBoardRepository.save(normalBoard); + } + +} From 47dd50c9ed7548078331152abafacff10c99ec58 Mon Sep 17 00:00:00 2001 From: whitemark Date: Thu, 15 Feb 2024 00:01:45 +0900 Subject: [PATCH 08/19] [feature/#233] NormalBoard entity, dto TEST code --- .../domain/board/domain/NormalBoardTest.java | 24 ------ .../domain/board/dto/SaveBoardDtoTest.java | 79 ------------------- .../domain/board/dto/UpdateBoardDtoTest.java | 59 -------------- .../domain/NormalBoardExampleTest.java | 29 +++++++ .../normalBoard/domain/NormalBoardTest.java | 72 +++++++++++++++++ .../dto/NormalBoardDetailDtoTest.java | 67 ++++++++++++++++ .../normalBoard/dto/NormalBoardDtoTest.java | 66 ++++++++++++++++ 7 files changed, 234 insertions(+), 162 deletions(-) delete mode 100644 resource-server/src/test/java/com/inhabas/api/domain/board/domain/NormalBoardTest.java delete mode 100644 resource-server/src/test/java/com/inhabas/api/domain/board/dto/SaveBoardDtoTest.java delete mode 100644 resource-server/src/test/java/com/inhabas/api/domain/board/dto/UpdateBoardDtoTest.java create mode 100644 resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java create mode 100644 resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java create mode 100644 resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java create mode 100644 resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/NormalBoardTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/NormalBoardTest.java deleted file mode 100644 index d112c4b6..00000000 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/NormalBoardTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.inhabas.api.domain.board.domain; - -import org.springframework.test.util.ReflectionTestUtils; - -public class NormalBoardTest { - - public static NormalBoard getBoard1() { - return new NormalBoard("이건 제목", "이건 내용입니다."); - } - - public static NormalBoard getBoard2() { - return new NormalBoard("이건 공지", "이건 공지입니다."); - } - - public static NormalBoard getBoard3() { - return new NormalBoard("이건 공지2", "이건 공지2입니다."); - } - - public static NormalBoard getTestBoard(Integer id) { - NormalBoard board = new NormalBoard("이건 공지2", "이건 공지2입니다."); - ReflectionTestUtils.setField(board, "id", id); - return board; - } -} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/dto/SaveBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/dto/SaveBoardDtoTest.java deleted file mode 100644 index 51d93cda..00000000 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/dto/SaveBoardDtoTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.inhabas.api.domain.board.dto; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Set; - -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; - -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; - -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -public class SaveBoardDtoTest { - - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - @DisplayName("SaveBoardDto 객체를 정상적으로 생성한다.") - @Test - public void SaveBoardDto_is_OK() { - // given - SaveBoardDto saveBoardDto = new SaveBoardDto("title", "content", new MenuId(1)); - - // when - Set> violations = validator.validate(saveBoardDto); - - // then - assertTrue(violations.isEmpty()); - } - - @DisplayName("SaveBoardDto의 content 필드가 null 이면 validation 실패") - @Test - public void Contents_is_null() { - // given - SaveBoardDto saveBoardDto = new SaveBoardDto("title", null, new MenuId(1)); - - // when - Set> violations = validator.validate(saveBoardDto); - - // then - assertEquals(1, violations.size()); - assertEquals("본문을 입력하세요.", violations.iterator().next().getMessage()); - } - - @DisplayName("게시글의 제목이 100자 이상을 넘긴 경우 validation 통과하지 못함.") - @Test - public void Title_is_too_long() { - // given - String title = "title".repeat(20) + "."; - String contents = "그냥 본문 내용입니다."; - - SaveBoardDto saveBoardDto = new SaveBoardDto(title, contents, new MenuId(1)); - - // when - Set> violations = validator.validate(saveBoardDto); - - // then - assertEquals(1, violations.size()); - assertEquals("제목은 최대 100자입니다.", violations.iterator().next().getMessage()); - } -} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/dto/UpdateBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/dto/UpdateBoardDtoTest.java deleted file mode 100644 index e128a266..00000000 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/dto/UpdateBoardDtoTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.inhabas.api.domain.board.dto; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.Set; - -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; - -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -public class UpdateBoardDtoTest { - - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - @DisplayName("UpdateBoardDto를 정상적으로 생성한다. ") - @Test - public void UpdateBoardDto_is_OK() { - // given - UpdateBoardDto updateBoardDto = new UpdateBoardDto(1L, "title", "content"); - - // when - Set> violations = validator.validate(updateBoardDto); - - // then - assertEquals(0, violations.size()); - } - - @DisplayName("본문에 공백이 입력되었을 경우 테스트를 통과하지 못함.") - @Test - public void Contents_is_empty() { - // given - UpdateBoardDto updateBoardDto = new UpdateBoardDto(2L, "title", " "); - - // when - Set> violations = validator.validate(updateBoardDto); - - // then - assertEquals(1, violations.size()); - assertEquals("본문을 입력하세요", violations.iterator().next().getMessage()); - } -} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java new file mode 100644 index 00000000..ce185d14 --- /dev/null +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java @@ -0,0 +1,29 @@ +package com.inhabas.api.domain.normalBoard.domain; + +import com.inhabas.api.domain.menu.domain.Menu; +import com.inhabas.api.domain.menu.domain.MenuGroup; +import com.inhabas.api.domain.menu.domain.valueObject.MenuType; +import org.springframework.test.util.ReflectionTestUtils; + +public class NormalBoardExampleTest { + + public static NormalBoard getBoard1(Menu menu) { + return new NormalBoard("이건 공지1", menu, "이건 공지1입니다.", false); + } + + public static NormalBoard getBoard2(Menu menu) { + return new NormalBoard("이건 공지2", menu, "이건 공지2입니다.", false); + } + + public static NormalBoard getBoard3(Menu menu) { + return new NormalBoard("이건 공지3", menu, "이건 공지3입니다.", false); + } + + public static NormalBoard getTestBoard(Integer id, Menu menu) { + + NormalBoard board = new NormalBoard("이건 공지", menu, "이건 공지입니다.", false); + ReflectionTestUtils.setField(board, "id", id); + return board; + } + +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java new file mode 100644 index 00000000..eada2b73 --- /dev/null +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java @@ -0,0 +1,72 @@ +package com.inhabas.api.domain.normalBoard.domain; + +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.domain.board.domain.AlbumBoard; +import com.inhabas.api.domain.file.domain.BoardFile; +import com.inhabas.api.domain.menu.domain.Menu; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.ArrayList; +import java.util.List; + +public class NormalBoardTest { + + @Mock + private Menu menu; + + private NormalBoard normalBoard; + + @BeforeEach + public void setUp() { + + MockitoAnnotations.openMocks(this); + + String title = "title1"; + String content = "content1"; + normalBoard = new NormalBoard(title, menu, content, false); + } + + @DisplayName("올바른 NormalBoard 를 생성한다.") + @Test + public void ConstructorTest() { + // then + Assertions.assertThat(normalBoard.getTitle()).isEqualTo("title1"); + Assertions.assertThat(normalBoard.getContent()).isEqualTo("content1"); + } + + @DisplayName("NormalBoard text 부분을 수정한다.") + @Test + public void updateTextTest() { + // given + String newTitle = "newTitle"; + String newContent = "newContent"; + + // when + normalBoard.updateText(newTitle, newContent); + + // then + Assertions.assertThat(normalBoard.getTitle()).isEqualTo(newTitle); + Assertions.assertThat(normalBoard.getContent()).isEqualTo(newContent); + } + + @DisplayName("NormalBoard file 부분을 수정한다.") + @Test + public void updateFilesTest() { + // given + List files = new ArrayList<>(); + BoardFile file = new BoardFile("fileName", "/hello", normalBoard); + files.add(file); + + // when + normalBoard.updateFiles(files); + + // then + Assertions.assertThat(normalBoard.getFiles().get(0)).isEqualTo(file); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java new file mode 100644 index 00000000..937fb758 --- /dev/null +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java @@ -0,0 +1,67 @@ +package com.inhabas.api.domain.normalBoard.dto; + +import com.inhabas.api.domain.file.dto.FileDownloadDto; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.*; + +class NormalBoardDetailDtoTest { + + private static ValidatorFactory validatorFactory; + private static Validator validator; + private final List emptyList = new ArrayList<>(); + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("NormalBoardDetailDto 객체를 정상적으로 생성한다.") + @Test + public void NormalBoardDetailDto_is_OK() { + // given + NormalBoardDetailDto normalBoardDetailDto = + new NormalBoardDetailDto(1L, "title", "content", "writer", + LocalDateTime.now(), LocalDateTime.now(), emptyList, false); + + // when + Set> violations = validator.validate(normalBoardDetailDto); + + // then + assertTrue(violations.isEmpty()); + } + + @DisplayName("normalBoardDetailDto title 필드가 null 이면 validation 실패") + @Test + public void Title_is_null() { + // given + NormalBoardDetailDto normalBoardDetailDto = + new NormalBoardDetailDto(1L, null, "content", "writer", + LocalDateTime.now(), LocalDateTime.now(), emptyList, false); + + // when + Set> violations = validator.validate(normalBoardDetailDto); + + // then + assertEquals(1, violations.size()); + } +} \ No newline at end of file diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java new file mode 100644 index 00000000..82e3207f --- /dev/null +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java @@ -0,0 +1,66 @@ +package com.inhabas.api.domain.normalBoard.dto; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.*; + +class NormalBoardDtoTest { + + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("NormalBoardDto 객체를 정상적으로 생성한다.") + @Test + public void NormalBoardDto_is_OK() { + // given + NormalBoardDto normalBoardDto = + new NormalBoardDto(1L, "title", "writer", + LocalDateTime.now(), LocalDateTime.now(), false); + + // when + Set> violations = validator.validate(normalBoardDto); + + // then + assertTrue(violations.isEmpty()); + } + + @DisplayName("NormalBoardDto title 필드가 null 이면 validation 실패") + @Test + public void Title_is_null() { + // given + NormalBoardDto normalBoardDto = + new NormalBoardDto(1L, null, "writer", + LocalDateTime.now(), LocalDateTime.now(), false); + + // when + Set> violations = validator.validate(normalBoardDto); + + // then + assertEquals(1, violations.size()); + } + +} \ No newline at end of file From 4cf9e5ad20311664a59b97f89bc1d8e511c40f94 Mon Sep 17 00:00:00 2001 From: whitemark Date: Thu, 15 Feb 2024 23:52:35 +0900 Subject: [PATCH 09/19] [feature/#233] NormalBoard repository TEST code --- .../oauth2/member/domain/entity/Member.java | 2 +- .../repository/NormalBoardRepositoryImpl.java | 4 +- .../repository/NormalBoardRepositoryTest.java | 185 ------------------ .../dto/SaveNormalBoardDtoTest.java | 64 ++++++ .../repository/NormalBoardRepositoryTest.java | 133 +++++++++++++ 5 files changed, 200 insertions(+), 188 deletions(-) delete mode 100644 resource-server/src/test/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryTest.java create mode 100644 resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java create mode 100644 resource-server/src/test/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryTest.java diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java index a35aa7ca..b8c15a49 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java @@ -22,7 +22,7 @@ @Entity @Table( - name = "user", + name = "USER", uniqueConstraints = { @UniqueConstraint( name = "UNIQUE_PROVIDER_UID", diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java index 5d998068..d4b63206 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java @@ -90,11 +90,11 @@ private BooleanExpression eqNormalBoardType(NormalBoardType normalBoardType) { } private BooleanExpression likeTitle(String search) { - return normalBoard.title.value.like(search); + return normalBoard.title.value.like("%" + search + "%"); } private BooleanExpression likeContent(String search) { - return normalBoard.content.value.like(search); + return normalBoard.content.value.like("%" + search + "%"); } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryTest.java deleted file mode 100644 index f5b264cf..00000000 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryTest.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.inhabas.api.domain.board.repository; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; - -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.menu.domain.Menu; -import com.inhabas.testAnnotataion.DefaultDataJpaTest; - -@DefaultDataJpaTest -public class NormalBoardRepositoryTest { - - @Autowired NormalBoardRepository boardRepository; - @Autowired TestEntityManager em; - - NormalBoard FREE_BOARD; - NormalBoard NOTICE_BOARD; - NormalBoard NOTICE_BOARD_2; - Menu freeBoardMenu; - Member writer; - - // @BeforeEach - // public void setUp() { - // writer = em.persist(basicMember1()); - // MenuGroup boardMenuGroup = em.persist(new MenuGroup("게시판")); - // Menu noticeBoardMenu = em.persist( - // Menu.builder() - // .menuGroup(boardMenuGroup) - // .priority(1) - // .type(MenuType.LIST) - // .name("공지사항") - // .description("부원이 알아야 할 내용을 게시합니다.") - // .build()); - // freeBoardMenu = em.persist( - // Menu.builder() - // .menuGroup(boardMenuGroup) - // .priority(2) - // .type(MenuType.LIST) - // .name("자유게시판") - // .description("부원이 자유롭게 사용할 수 있는 게시판입니다.") - // .build()); - // - // FREE_BOARD = NormalBoardTest.getBoard1() - // .writtenBy(writer.getId()).inMenu(freeBoardMenu.getId()); - // NOTICE_BOARD = NormalBoardTest.getBoard2() - // .writtenBy(writer.getId()).inMenu(noticeBoardMenu.getId()); - // NOTICE_BOARD_2 = NormalBoardTest.getBoard3() - // .writtenBy(writer.getId()).inMenu(noticeBoardMenu.getId()); - // } - - // @DisplayName("저장 후 반환값이 처음과 같다.") - // @Test - // public void save() { - // Member saveMember = em.find(Member.class, basicMember1().getId()); - // - // //when - // NormalBoard saveBoard = boardRepository.save(FREE_BOARD); - // - // //then - // assertAll( - // () -> assertThat(saveBoard.getId()).isNotNull(), - // () -> assertThat(saveBoard.getDateCreated()).isNotNull(), - // () -> assertThat(saveBoard.getTitle()).isEqualTo(FREE_BOARD.getTitle()), - // () -> assertThat(saveBoard.getContent()).isEqualTo(FREE_BOARD.getContent()), - // () -> assertThat(saveBoard.getWriterId()).isEqualTo(saveMember.getId()) - // ); - // } - - // @DisplayName("id에 해당하는 게시글을 dto 로 반환한다.") - // @Test - // public void findDtoById() { - // //given - // boardRepository.save(FREE_BOARD); - // boardRepository.save(NOTICE_BOARD); - // - // //when - // BoardDto find = boardRepository.findDtoById(NOTICE_BOARD.getId()) - // .orElseThrow(EntityNotFoundException::new); - // - // //then - // assertAll( - // () -> assertThat(find.getId()).isEqualTo(NOTICE_BOARD.getId()), - // () -> assertThat(find.getTitle()).isEqualTo(NOTICE_BOARD.getTitle()), - // () -> assertThat(find.getContent()).isEqualTo(NOTICE_BOARD.getContent()), - // () -> assertThat(find.getMenuId()).isEqualTo(NOTICE_BOARD.getMenuId()), - // () -> assertThat(find.getWriterName()).isEqualTo(writer.getName()) - // ); - // } - - // @DisplayName("게시글을 수정한다.") - // @Test - // public void update() { - // //given - // Member saveMember = em.find(Member.class, basicMember1().getId()); - // boardRepository.save(FREE_BOARD); - // - // //when - // FREE_BOARD.modify("제목이 수정되었습니다.", "내용이 수정되었습니다.", saveMember.getId()); - // NormalBoard findBoard = boardRepository.findById(FREE_BOARD.getId()) - // .orElseThrow(EntityNotFoundException::new); - // - // //then - // assertThat(findBoard.getContent()).isEqualTo("내용이 수정되었습니다."); - // assertThat(findBoard.getTitle()).isEqualTo("제목이 수정되었습니다."); - // } - - // @DisplayName("id 로 게시글을 삭제한다.") - // @Test - // public void deleteById() { - // //given - // boardRepository.save(FREE_BOARD); - // - // //when - // boardRepository.deleteById(FREE_BOARD.getId()); - // - // //then - // assertTrue(boardRepository.findById(FREE_BOARD.getId()).isEmpty()); - // } - // - // @DisplayName("모든 게시글을 조회한다.") - // @Test - // public void findAll() { - // //given - // boardRepository.save(FREE_BOARD); - // boardRepository.save(NOTICE_BOARD); - - // //then - // assertThat(boards).contains(FREE_BOARD, NOTICE_BOARD); - // assertThat(boards.size()).isEqualTo(2); - // } - - // @DisplayName("메뉴 id 에 해당하는 게시글들을 갖고 온다.") - // @Test - // public void findAllByMenuId() { - // //given - // boardRepository.save(FREE_BOARD); - // boardRepository.save(NOTICE_BOARD); - // boardRepository.save(NOTICE_BOARD_2); - // MenuId freeBoardMenuId = FREE_BOARD.getMenuId(); - // MenuId noticeBoardMenuId = NOTICE_BOARD.getMenuId(); - // - // //when - // Page freeBoards = boardRepository.findAllByMenuId(freeBoardMenuId, - // Pageable.ofSize(5)); - // Page noticeBoards = boardRepository.findAllByMenuId(noticeBoardMenuId, - // Pageable.ofSize(5)); - // - // //then - // assertThat(freeBoards.getTotalElements()).isEqualTo(1); - // freeBoards.forEach( - // board->assertThat(board.getMenuId()).isEqualTo(freeBoardMenuId)); - // - // assertThat(noticeBoards.getTotalElements()).isEqualTo(2); - // noticeBoards.forEach( - // board->assertThat(board.getMenuId()).isEqualTo(noticeBoardMenuId)); - // } - - // @DisplayName("게시글 목록 페이지를 잘 불러온다.") - // @Test - // public void getBoardListPageTest() { - // //given - // ArrayList boards = new ArrayList<>(); - // for (int i = 0; i < 30; i++) { - // boards.add(new NormalBoard("이건 제목" + i, "이건 내용입니다.") - // .writtenBy(writer.getId()) - // .inMenu(freeBoardMenu.getId())); - // } - // boardRepository.saveAll(boards); - // - // //when - // Page page = - // boardRepository.findAllByMenuId( - // freeBoardMenu.getId(), - // PageRequest.of(2, 11, Direction.DESC, "created") - // ); - // - // //then - // assertThat(page.getTotalElements()).isEqualTo(30); - // assertThat(page.getTotalPages()).isEqualTo(3); - // assertThat(page.getNumber()).isEqualTo(2); - // assertThat(page.getNumberOfElements()).isEqualTo(8); - // } - -} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java new file mode 100644 index 00000000..d8607a8e --- /dev/null +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java @@ -0,0 +1,64 @@ +package com.inhabas.api.domain.normalBoard.dto; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class SaveNormalBoardDtoTest { + + private static ValidatorFactory validatorFactory; + private static Validator validator; + private final List emptyList = new ArrayList<>(); + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("SaveNormalBoardDto 객체를 정상적으로 생성한다.") + @Test + public void SaveNormalBoardDto_is_OK() { + // given + SaveNormalBoardDto saveNormalBoardDto = + new SaveNormalBoardDto("title", "content", emptyList, false); + + // when + Set> violations = validator.validate(saveNormalBoardDto); + + // then + assertTrue(violations.isEmpty()); + } + + @DisplayName("SaveNormalBoardDto content 필드가 null 이면 validation 실패") + @Test + public void Content_is_null() { + // given + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", null, emptyList,false); + + // when + Set> violations = validator.validate(saveNormalBoardDto); + + // then + assertEquals(1, violations.size()); + } + +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryTest.java new file mode 100644 index 00000000..2c64fd77 --- /dev/null +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryTest.java @@ -0,0 +1,133 @@ +package com.inhabas.api.domain.normalBoard.repository; + +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.domain.menu.domain.Menu; +import com.inhabas.api.domain.menu.domain.MenuGroup; +import com.inhabas.api.domain.menu.domain.valueObject.MenuType; +import com.inhabas.api.domain.normalBoard.domain.NormalBoard; +import com.inhabas.api.domain.normalBoard.domain.NormalBoardExampleTest; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; +import com.inhabas.testAnnotataion.DefaultDataJpaTest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.List; + +import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; +import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.NOTICE; +import static org.assertj.core.api.Assertions.assertThat; + +@DefaultDataJpaTest +public class NormalBoardRepositoryTest { + + @Autowired + NormalBoardRepository normalBoardRepository; + @Autowired TestEntityManager em; + + NormalBoard NOTICE_BOARD; + NormalBoard NOTICE_BOARD_2; + Member writer; + + @BeforeEach + public void setUp() { + em.getEntityManager().createNativeQuery("ALTER TABLE MENU ALTER COLUMN `id` RESTART WITH 4").executeUpdate(); + writer = em.persist(basicMember1()); + MenuGroup boardMenuGroup = em.persist(new MenuGroup("게시판")); + Menu noticeBoardMenu = em.persist( + Menu.builder() + .menuGroup(boardMenuGroup) + .priority(1) + .type(MenuType.NORMAL_NOTICE) + .name("공지사항") + .description("부원이 알아야 할 내용을 게시합니다.") + .build()); + ReflectionTestUtils.setField(noticeBoardMenu, "id", 4); + NOTICE_BOARD = NormalBoardExampleTest.getBoard1(noticeBoardMenu) + .writtenBy(writer, NormalBoard.class); + NOTICE_BOARD_2 = NormalBoardExampleTest.getBoard2(noticeBoardMenu) + .writtenBy(writer, NormalBoard.class); + } + + @AfterEach + public void deleteAll() { + + this.normalBoardRepository.deleteAll(); + this.em.clear(); + } + + @DisplayName("저장 후 반환값이 처음과 같다.") + @Test + public void save() { + //when + NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); + + //then + assertThat(saveBoard.getWriter()).isEqualTo(writer); + } + + @DisplayName("memberId, type, search 로 게시글 목록 조회한다.") + @Test + public void findAllByMemberIdAndTypeAndSearch() { + //given + NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); + NormalBoard saveBoard2 = normalBoardRepository.save(NOTICE_BOARD_2); + Long writerId = writer.getId(); + + //when + List dtoList = normalBoardRepository.findAllByMemberIdAndTypeAndSearch(writerId, NOTICE, ""); + + //then + assertThat(dtoList).hasSize(2); + assertThat(dtoList.get(0).getTitle()).isEqualTo(saveBoard.getTitle()); + } + + @DisplayName("type, search 로 게시글 목록 조회한다.") + @Test + public void findAllByTypeAndSearch() { + //given + NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); + NormalBoard saveBoard2 = normalBoardRepository.save(NOTICE_BOARD_2); + + //when + List dtoList = normalBoardRepository.findAllByTypeAndSearch(NOTICE, ""); + + //then + assertThat(dtoList).hasSize(2); + assertThat(dtoList.get(0).getTitle()).isEqualTo(saveBoard.getTitle()); + } + + @DisplayName("memberId, type, id 로 게시글 상세 조회한다.") + @Test + public void findByMemberIdAndTypeAndId() { + //given + NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); + Long writerId = writer.getId(); + + //when + NormalBoard normalBoard = normalBoardRepository.findByMemberIdAndTypeAndId(writerId, NOTICE, saveBoard.getId()).orElse(null); + + //then + assertThat(normalBoard).isNotNull(); + assertThat(normalBoard.getTitle()).isEqualTo(saveBoard.getTitle()); + } + + @DisplayName("type, id 로 게시글 상세 조회한다.") + @Test + public void findByTypeAndId() { + //given + NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); + + //when + NormalBoard normalBoard = normalBoardRepository.findByTypeAndId(NOTICE, saveBoard.getId()).orElse(null); + + //then + assertThat(normalBoard).isNotNull(); + assertThat(normalBoard.getTitle()).isEqualTo(saveBoard.getTitle()); + } + +} From 57338d9918c9ac14dd4bc4f52bdd78f64f4f6acf Mon Sep 17 00:00:00 2001 From: whitemark Date: Fri, 16 Feb 2024 23:51:03 +0900 Subject: [PATCH 10/19] [feature/#233] NormalBoard Service TEST code --- ...eImpl.java => NormalBoardServiceImpl.java} | 22 ++- .../board/usecase/BoardServiceTest.java | 154 ------------------ .../comment/usecase/CommentServiceTest.java | 4 +- .../domain/menu/domain/MenuExampleTest.java | 6 +- .../valueObject/MenuGroupExampleTest.java | 5 +- .../usecase/NormalBoardServiceImplTest.java | 147 +++++++++++++++++ 6 files changed, 174 insertions(+), 164 deletions(-) rename resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/{NormalNormalBoardServiceImpl.java => NormalBoardServiceImpl.java} (86%) delete mode 100644 resource-server/src/test/java/com/inhabas/api/domain/board/usecase/BoardServiceTest.java create mode 100644 resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalNormalBoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java similarity index 86% rename from resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalNormalBoardServiceImpl.java rename to resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java index a27815ee..de479723 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalNormalBoardServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java @@ -1,6 +1,9 @@ package com.inhabas.api.domain.normalBoard.usecase; import com.inhabas.api.auth.domain.error.businessException.NotFoundException; +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.auth.domain.oauth2.member.domain.exception.MemberNotFoundException; +import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; import com.inhabas.api.domain.board.exception.S3UploadFailedException; import com.inhabas.api.domain.file.domain.BoardFile; import com.inhabas.api.domain.file.dto.FileDownloadDto; @@ -27,10 +30,11 @@ @Slf4j @Transactional @RequiredArgsConstructor -public class NormalNormalBoardServiceImpl implements NormalBoardService { +public class NormalBoardServiceImpl implements NormalBoardService { private final NormalBoardRepository normalBoardRepository; private final MenuRepository menuRepository; + private final MemberRepository memberRepository; private final S3Service s3Service; @@ -77,12 +81,18 @@ public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Lo @Override public Long write(Long memberId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto) { + Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); Menu menu = menuRepository.findById(normalBoardType.getMenuId()).orElseThrow(NotFoundException::new); NormalBoard normalBoard = - new NormalBoard(saveNormalBoardDto.getTitle(), menu, saveNormalBoardDto.getContent(), saveNormalBoardDto.getIsPinned()); - - return normalBoardRepository.save(normalBoard).getId(); + new NormalBoard( + saveNormalBoardDto.getTitle(), + menu, + saveNormalBoardDto.getContent(), + saveNormalBoardDto.getIsPinned()) + .writtenBy(writer, NormalBoard.class); + + return updateNormalBoardFiles(saveNormalBoardDto, normalBoardType, normalBoard); } @Override @@ -100,7 +110,7 @@ public void delete(Long boardId) { } - private void updateNormalBoardFiles( + private Long updateNormalBoardFiles( SaveNormalBoardDto saveNormalBoardDto, NormalBoardType normalBoardType, NormalBoard normalBoard) { final String DIR_NAME = "/" + normalBoardType.getBoardType(); List updateFiles = new ArrayList<>(); @@ -133,7 +143,7 @@ private void updateNormalBoardFiles( } normalBoard.updateFiles(updateFiles); - normalBoardRepository.save(normalBoard); + return normalBoardRepository.save(normalBoard).getId(); } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/usecase/BoardServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/usecase/BoardServiceTest.java deleted file mode 100644 index 958072bb..00000000 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/usecase/BoardServiceTest.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.inhabas.api.domain.board.usecase; - -import static org.mockito.BDDMockito.*; - -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; - -import com.inhabas.api.domain.board.repository.NormalBoardRepository; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.extension.ExtendWith; - -@ExtendWith(MockitoExtension.class) -public class BoardServiceTest { - - @InjectMocks BoardServiceImpl boardService; - - @Mock NormalBoardRepository boardRepository; - - private MockMvc mockMvc; - - @BeforeEach - void setUp() { - mockMvc = MockMvcBuilders.standaloneSetup(boardService).build(); - } - - // @DisplayName("게시판을 성공적으로 생성한다.") - // @Test - // public void createBoard() { - // //given - // SaveBoardDto saveBoardDto = new SaveBoardDto("title", "content", new MenuId(1)); - // NormalBoard normalBoard = new NormalBoard("title", "content"); - // given(boardRepository.save(any())).willReturn(normalBoard); - // - // // when - // Integer returnedId = boardService.write(new StudentId("12201863"), saveBoardDto); - // - // // then - // then(boardRepository).should(times(1)).save(any()); - // } - // - // @DisplayName("게시판의 목록을 조회한다.") - // @Test - // public void getBoardList() { - // //given - // PageRequest pageable = PageRequest.of(0, 10, Sort.Direction.ASC, "created"); - // - // BoardDto boardDto1 = - // new BoardDto(1, "title", "content", "mingyeom", - // new MenuId(1), LocalDateTime.now(), LocalDateTime.now()); - // BoardDto boardDto2 = - // new BoardDto(2, "title", "content", "minji", - // new MenuId(1), LocalDateTime.now(), LocalDateTime.now()); - // - // List results = new ArrayList<>(); - // results.add(boardDto1); - // results.add(boardDto2); - // Page expectedBoardDto = new PageImpl<>(results, pageable, results.size()); - // - // given(boardRepository.findAllByMenuId(any(), any())).willReturn(expectedBoardDto); - // - // //when - // Page returnedBoardList = boardService.getBoardList(new MenuId(1), pageable); - // - // //then - // then(boardRepository).should(times(1)).findAllByMenuId(any(), any()); - // assertThat(returnedBoardList).isEqualTo(expectedBoardDto); - // } - // - // @DisplayName("게시글 단일 조회에 성공한다.") - // @Test - // public void getDetailBoard() { - // //given - // BoardDto boardDto = - // new BoardDto(1, "title", "content", "김민겸", - // new MenuId(1), LocalDateTime.now(), null); - // given(boardRepository.findDtoById(any())).willReturn(Optional.of(boardDto)); - // - // // when - // boardService.getBoard(1); - // - // // then - // then(boardRepository).should(times(1)).findDtoById(any()); - // } - // - // @DisplayName("게시글을 성공적으로 삭제한다.") - // @Test - // public void deleteBoard() { - // //given - // StudentId writer = new StudentId("12201863"); - // NormalBoard board = new NormalBoard("Title", "Content").writtenBy(writer); - // given(boardRepository.findById(anyInt())).willReturn(Optional.of(board)); - // doNothing().when(boardRepository).deleteById(any()); - // - // // when - // boardService.delete(writer, 1); - // - // // then - // then(boardRepository).should(times(1)).deleteById(any()); - // } - // - // @DisplayName("게시글을 수정한다.") - // @Test - // public void updateBoard() { - // //given - // StudentId memberId = new StudentId("12201863"); - // NormalBoard savedNormalBoard = new NormalBoard("Origin Title", - // "Origin Content").writtenBy(memberId); - // NormalBoard updatedNormalBoard = new NormalBoard("Title", "Content").writtenBy( - // memberId); - // - // given(boardRepository.findById(anyInt())).willReturn(Optional.of(savedNormalBoard)); - // given(boardRepository.save(any())).willReturn(updatedNormalBoard); - // - // UpdateBoardDto updateBoardDto = new UpdateBoardDto(1, "수정된 제목", "수정된 내용"); - // - // // when - // Integer returnedId = boardService.update(memberId, updateBoardDto); - // - // // then - // then(boardRepository).should(times(1)).save(any()); - // } - // - // @DisplayName("작성자가 아니면 게시글 수정에 실패한다.") - // @Test - // public void failToUpdateBoard() { - // //given - // StudentId badUser = new StudentId("44444444"); - // StudentId originWriter = new StudentId("12201863"); - // NormalBoard board = new NormalBoard("Title", "Content").writtenBy(originWriter); - // given(boardRepository.findById(anyInt())).willReturn(Optional.of(board)); - // - // // when - // Assertions.assertThrows(BoardCannotModifiableException.class, - // () -> boardService.update(badUser, new UpdateBoardDto(1, "수정된 제목", "수정된 내용"))); - // } - // - // @DisplayName("작성자가 아니면 게시글 삭제에 실패한다.") - // @Test - // public void failToDeleteBoard() { - // //given - // StudentId badUser = new StudentId("44444444"); - // StudentId originWriter = new StudentId("12201863"); - // NormalBoard board = new NormalBoard("Title", "Content").writtenBy(originWriter); - // given(boardRepository.findById(anyInt())).willReturn(Optional.of(board)); - // - // // when - // Assertions.assertThrows(BoardCannotModifiableException.class, - // () -> boardService.delete(badUser, 1)); - // } -} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/comment/usecase/CommentServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/comment/usecase/CommentServiceTest.java index 303a526f..be0b38d9 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/comment/usecase/CommentServiceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/comment/usecase/CommentServiceTest.java @@ -52,9 +52,9 @@ public class CommentServiceTest { public void setUpMocking() { proxyWriter = MemberTest.getTestBasicMember("12171652"); ReflectionTestUtils.setField(proxyWriter, "id", 1L); - proxyMenuGroup = MenuGroupExampleTest.getMenuGroup1(); + proxyMenuGroup = MenuGroupExampleTest.getIBASMenuGroup(); ReflectionTestUtils.setField(proxyMenuGroup, "id", 1); - proxyMenu = MenuExampleTest.getMenu1(proxyMenuGroup); + proxyMenu = MenuExampleTest.getAlbumMenu(proxyMenuGroup); ReflectionTestUtils.setField(proxyMenu, "id", 1); proxyBoard = AlbumExampleTest.getAlbumBoard1(proxyMenu); ReflectionTestUtils.setField(proxyBoard, "id", 1L); diff --git a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/MenuExampleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/MenuExampleTest.java index 53a88b0e..17a3daec 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/MenuExampleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/MenuExampleTest.java @@ -4,10 +4,14 @@ public class MenuExampleTest { - public static Menu getMenu1(MenuGroup menuGroup) { + public static Menu getAlbumMenu(MenuGroup menuGroup) { return new Menu(menuGroup, 1, MenuType.ALBUM, "동아리 활동", "동아리 활동 설명"); } + public static Menu getNormalNoticeMenu(MenuGroup menuGroup) { + return new Menu(menuGroup, 1, MenuType.NORMAL_NOTICE, "공지 사항", "공지 사항 설명"); + } + public static Menu getMenu2(MenuGroup menuGroup) { return new Menu(menuGroup, 1, MenuType.STUDY, "강의", "강의 설명"); } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java index 9211aa0c..746a6708 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java @@ -4,9 +4,12 @@ public class MenuGroupExampleTest { - public static MenuGroup getMenuGroup1() { + public static MenuGroup getIBASMenuGroup() { return new MenuGroup("IBAS"); } + public static MenuGroup getNormalMenuGroup() { + return new MenuGroup("게시판"); + } public static MenuGroup getMenuGroup2() { return new MenuGroup("STUDY"); diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java new file mode 100644 index 00000000..fedbf678 --- /dev/null +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java @@ -0,0 +1,147 @@ +package com.inhabas.api.domain.normalBoard.usecase; + +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; +import com.inhabas.api.domain.file.usecase.S3Service; +import com.inhabas.api.domain.member.domain.entity.MemberTest; +import com.inhabas.api.domain.menu.domain.Menu; +import com.inhabas.api.domain.menu.repository.MenuRepository; +import com.inhabas.api.domain.normalBoard.domain.NormalBoard; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDetailDto; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; +import com.inhabas.api.domain.normalBoard.dto.SaveNormalBoardDto; +import com.inhabas.api.domain.normalBoard.repository.NormalBoardRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.util.ReflectionTestUtils; + +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import static com.inhabas.api.domain.menu.domain.MenuExampleTest.getNormalNoticeMenu; +import static com.inhabas.api.domain.menu.domain.valueObject.MenuGroupExampleTest.getNormalMenuGroup; +import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.NOTICE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; + +@ExtendWith(MockitoExtension.class) +public class NormalBoardServiceImplTest { + + @InjectMocks + NormalBoardServiceImpl normalBoardService; + + @Mock + MemberRepository memberRepository; + @Mock + NormalBoardRepository normalBoardRepository; + @Mock + MenuRepository menuRepository; + @Mock + S3Service s3Service; + + @DisplayName("normal board 게시글 목록을 조회한다.") + @Test + void getPosts() { + // given + Member member = MemberTest.chiefMember(); + NormalBoardDto dto = new NormalBoardDto( + 1L, "title", member.getName(), LocalDateTime.now(), LocalDateTime.now(), false); + + given(normalBoardRepository.findAllByTypeAndSearch(any(), any())) + .willReturn(Arrays.asList(dto)); + + // when + List clubActivityDtoList = normalBoardService.getPosts(1L, NOTICE, ""); + + // then + assertThat(clubActivityDtoList).hasSize(1); + } + + @DisplayName("normal board 게시글 단일 조회한다.") + @Test + void getPost() { + // given + Member member = MemberTest.chiefMember(); + Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); + NormalBoard normalBoard = + new NormalBoard("title", menu, "content", false) + .writtenBy(member, NormalBoard.class); + + given(normalBoardRepository.findByTypeAndId(any(), any())).willReturn(Optional.of(normalBoard)); + + // when + NormalBoardDetailDto dto = normalBoardService.getPost(1L, NOTICE, 1L); + + // then + assertThat(dto.getTitle()).isEqualTo(normalBoard.getTitle()); + + } + + @DisplayName("normal board 게시글을 작성한다.") + @Test + void write() { + //given + Member member = MemberTest.chiefMember(); + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", "content", null, false); + Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); + NormalBoard normalBoard = + new NormalBoard("title", menu, "content", false) + .writtenBy(member, NormalBoard.class); + + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + given(normalBoardRepository.save(any())).willReturn(normalBoard); + given(menuRepository.findById(anyInt())).willReturn(Optional.of(menu)); + + // when + normalBoardService.write(1L, NOTICE, saveNormalBoardDto); + + // then + then(menuRepository).should(times(1)).findById(anyInt()); + then(normalBoardRepository).should(times(1)).save(any()); + } + + @DisplayName("normal board 게시글을 수정한다.") + @Test + void update() { + //given + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", "content", null, false); + Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); + NormalBoard normalBoard = new NormalBoard("title", menu, "content", false); + ReflectionTestUtils.setField(normalBoard, "id", 1L); + + given(normalBoardRepository.findById(any())).willReturn(Optional.of(normalBoard)); + given(normalBoardRepository.save(any())).willReturn(normalBoard); + + // when + normalBoardService.update(normalBoard.getId(), NOTICE, saveNormalBoardDto); + + // then + then(normalBoardRepository).should(times(1)).findById(any()); + then(normalBoardRepository).should(times(1)).save(any()); + } + + @DisplayName("normal board 게시글을 삭제한다.") + @Test + void delete() { + // given + Long boardId = 1L; + doNothing().when(normalBoardRepository).deleteById(boardId); + + // when + normalBoardService.delete(boardId); + + // then + then(normalBoardRepository).should(times(1)).deleteById(boardId); + } +} \ No newline at end of file From bcf2dbbe1b1b2180771e6a5473f9385d884575c9 Mon Sep 17 00:00:00 2001 From: whitemark Date: Sat, 17 Feb 2024 23:03:51 +0900 Subject: [PATCH 11/19] [feature/#233] NormalBoard controller TEST code --- .../api/web/NormalBoardController.java | 68 ++-- .../converter/NormalBoardTypeConverter.java | 35 ++ .../inhabas/api/web/BoardControllerTest.java | 171 --------- .../api/web/NormalBoardControllerTest.java | 333 ++++++++++++++++++ 4 files changed, 410 insertions(+), 197 deletions(-) create mode 100644 resource-server/src/main/java/com/inhabas/api/web/converter/NormalBoardTypeConverter.java delete mode 100644 resource-server/src/test/java/com/inhabas/api/web/BoardControllerTest.java create mode 100644 resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java diff --git a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java index 9ea41b51..5554fc4d 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java @@ -53,7 +53,7 @@ public class NormalBoardController { }) @GetMapping("/board/count") @SecurityRequirements(value = {}) - public ResponseEntity> getBoardList() { + public ResponseEntity> getBoardCount() { return ResponseEntity.ok(baseBoardRepository.countRowsGroupByMenuId()); } @@ -73,16 +73,6 @@ public ResponseEntity> getBoardList() { @ExampleObject( value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), - @ApiResponse( - responseCode = "404", - description = "데이터가 존재하지 않습니다.", - content = - @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = - @ExampleObject( - value = - "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) }) @GetMapping("/board/{boardType}") @PreAuthorize( @@ -167,16 +157,6 @@ public ResponseEntity getBoard( @ExampleObject( value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), - @ApiResponse( - responseCode = "404", - description = "데이터가 존재하지 않습니다.", - content = - @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = - @ExampleObject( - value = - "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) }) public ResponseEntity addBoard( @Authenticated Long memberId, @@ -187,7 +167,7 @@ public ResponseEntity addBoard( URI location = ServletUriComponentsBuilder.fromCurrentRequest() .path("/board/{boardType}/{boardId}") - .buildAndExpand(boardType, newNormalBoardId) + .buildAndExpand(boardType.getBoardType(), newNormalBoardId) .toUri(); return ResponseEntity.created(location).build(); @@ -197,8 +177,26 @@ public ResponseEntity addBoard( @PutMapping("/board/{boardType}/{boardId}") @ApiResponses({ @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), - @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) }) @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") public ResponseEntity updateBoard( @@ -215,8 +213,26 @@ public ResponseEntity updateBoard( @DeleteMapping("/board/{boardType}/{boardId}") @ApiResponses({ @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 게시글 삭제 요청"), - @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) }) @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") public ResponseEntity deleteBoard( diff --git a/resource-server/src/main/java/com/inhabas/api/web/converter/NormalBoardTypeConverter.java b/resource-server/src/main/java/com/inhabas/api/web/converter/NormalBoardTypeConverter.java new file mode 100644 index 00000000..1a7fed74 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/web/converter/NormalBoardTypeConverter.java @@ -0,0 +1,35 @@ +package com.inhabas.api.web.converter; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import com.inhabas.api.auth.domain.error.businessException.NotFoundException; +import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; +import org.springframework.core.convert.converter.Converter; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +public class NormalBoardTypeConverter { + + @Component + public static class StringToContestTypeConverter implements Converter { + + @Override + public NormalBoardType convert(String source) { + if (!StringUtils.hasText(source)) { + throw new InvalidInputException(); + } + try { + return NormalBoardType.valueOf(source.trim().toUpperCase()); + } catch (IllegalArgumentException e) { + throw new NotFoundException(); + } + } + } + + @Component + public static class ContestTypeToStringConverter implements Converter { + @Override + public String convert(NormalBoardType source) { + return source != null ? source.toString().toLowerCase() : null; + } + } +} \ No newline at end of file diff --git a/resource-server/src/test/java/com/inhabas/api/web/BoardControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/BoardControllerTest.java deleted file mode 100644 index f983f390..00000000 --- a/resource-server/src/test/java/com/inhabas/api/web/BoardControllerTest.java +++ /dev/null @@ -1,171 +0,0 @@ -package com.inhabas.api.web; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.web.servlet.MockMvc; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; -import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.board.usecase.BoardService; -import com.inhabas.testAnnotataion.NoSecureWebMvcTest; - -@NoSecureWebMvcTest(BoardController.class) -public class BoardControllerTest { - - @Autowired private MockMvc mvc; - - @Autowired private ObjectMapper objectMapper; - - @Autowired BoardController boardController; - - @MockBean BoardService boardService; - - @MockBean MemberService memberService; - - @MockBean NormalBoard normalBoard; - - // @DisplayName("게시글 저장을 요청한다.") - // @Test - // @WithMockJwtAuthenticationToken - // public void addNewBoard() throws Exception { - // //given - // SaveBoardDto saveBoardDto = new SaveBoardDto("This is title", "This is content", new - // MenuId(1)); - // given(boardService.write(any(), any(SaveBoardDto.class))).willReturn(1); - // - // // when - // mvc.perform(post("/board") - // .contentType(MediaType.APPLICATION_JSON) - // .content(objectMapper.writeValueAsString(saveBoardDto))) - // .andExpect(status().isCreated()) - // .andExpect(content().string("1")); - // } - - // @DisplayName("게시글 수정을 요청한다.") - // @Test - // @WithMockJwtAuthenticationToken - // public void updateBoard() throws Exception{ - // //given - // UpdateBoardDto updateBoardDto = new UpdateBoardDto(1, "제목을 수정하였습니다.", "내용을 수정하였습니다."); - // given(boardService.update(any(), any(UpdateBoardDto.class))).willReturn(1); - // - // // when - // mvc.perform(put("/board") - // .contentType(MediaType.APPLICATION_JSON) - // .content(objectMapper.writeValueAsString(updateBoardDto))) - // .andExpect(status().isOk()) - // .andExpect(content().string("1")); - // } - - // @DisplayName("게시글 삭제를 요청한다.") - // @Test - // public void deleteBoard() throws Exception{ - // //given - // doNothing().when(boardService).delete(any(), anyInt()); - // - // // when - // mvc.perform(delete("/board/1")) - // .andExpect(status().isNoContent()); - // } - - // @DisplayName("게시글 목록 조회를 요청한다.") - // @Test - // public void getBoardList() throws Exception { - // PageRequest pageable = PageRequest.of(2,1, Sort.Direction.ASC, "id"); - // - // List results = new ArrayList<>(); - // results.add(new BoardDto(1, "Shown Title1", null, "Mingyeom", - // new MenuId(2), LocalDateTime.now(), null)); - // results.add(new BoardDto(2, "Shown Title2", null, "Mingyeom", - // new MenuId(2), LocalDateTime.now(), null)); - // results.add(new BoardDto(3, "Shown Title3", null, "Mingyeom", - // new MenuId(2), LocalDateTime.now(), null)); - // - // Page expectedBoardDto = new PageImpl<>(results, pageable, results.size()); - // - // given(boardService.getBoardList(any(), any())).willReturn(expectedBoardDto); - // - // // when - // String responseBody = mvc.perform(get("/boards?menu_id=6") - // .contentType(MediaType.APPLICATION_JSON) - // .param("page", "2") - // .param("size", "1") - // .param("sort", "ASC") - // .param("properties", "id")) - // .andExpect(status().isOk()) - // .andDo(print()) - // .andReturn() - // .getResponse().getContentAsString(); - // - // // then - // assertThat(responseBody).isEqualTo(objectMapper.writeValueAsString(expectedBoardDto)); - // } - - // @DisplayName("게시글 단일 조회를 요청한다.") - // @Test - // public void getBoardDetail() throws Exception{ - // //given - // BoardDto boardDto = - // new BoardDto(1, "Shown Title", "Shown Content", "Mingyeom", - // new MenuId(1), LocalDateTime.now(), null); - // given(boardService.getBoard(anyLong())).willReturn(boardDto); - // - // // when - // String responseBody = mvc.perform(get("/board/1")) - // .andExpect(status().isOk()) - // .andReturn() - // .getResponse().getContentAsString(); - // - // // then - // assertThat(responseBody).isEqualTo(objectMapper.writeValueAsString(boardDto)); - // - // } - - // @DisplayName("게시글 작성 시 Title의 길이가 범위를 초과해 오류 발생") - // @Test - // @WithMockJwtAuthenticationToken - // public void TitleIsTooLongError() throws Exception { - // //given - // SaveBoardDto saveBoardDto = new SaveBoardDto("title".repeat(20) + ".", "content", new - // MenuId(1)); - // - // // when - // String errorMessage = Objects.requireNonNull( - // mvc.perform(post("/board") - // .contentType(MediaType.APPLICATION_JSON) - // .content(objectMapper.writeValueAsString(saveBoardDto))) - // .andExpect(status().isBadRequest()) - // .andReturn() - // .getResolvedException()) - // .getMessage(); - // - // // then - // assertThat(errorMessage).isNotBlank(); - // assertThat(errorMessage).contains("제목은 최대 100자입니다."); - // } - - // @DisplayName("게시글 작성 시 Contents가 null인 경우 오류 발생") - // @Test - // @WithMockJwtAuthenticationToken - // public void ContentIsNullError() throws Exception { - // //given - // SaveBoardDto saveBoardDto = new SaveBoardDto("title", " ", new MenuId(1)); - // - // // when - // String errorMessage = Objects.requireNonNull( - // mvc.perform(post("/board") - // .contentType(MediaType.APPLICATION_JSON) - // .content(objectMapper.writeValueAsString(saveBoardDto))) - // .andExpect(status().isBadRequest()) - // .andReturn() - // .getResolvedException()) - // .getMessage(); - // - // // then - // assertThat(errorMessage).isNotBlank(); - // assertThat(errorMessage).contains("본문을 입력하세요."); - // } -} diff --git a/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java new file mode 100644 index 00000000..e27519df --- /dev/null +++ b/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java @@ -0,0 +1,333 @@ +package com.inhabas.api.web; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import com.inhabas.api.auth.domain.error.businessException.NotFoundException; +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.domain.board.dto.BoardCountDto; +import com.inhabas.api.domain.board.repository.BaseBoardRepository; +import com.inhabas.api.domain.member.domain.entity.MemberTest; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDetailDto; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; +import com.inhabas.api.domain.normalBoard.dto.SaveNormalBoardDto; +import com.inhabas.api.domain.normalBoard.usecase.NormalBoardService; +import com.inhabas.testAnnotataion.NoSecureWebMvcTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.List; + +import static com.inhabas.api.auth.domain.error.ErrorCode.INVALID_INPUT_VALUE; +import static com.inhabas.api.auth.domain.error.ErrorCode.NOT_FOUND; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@NoSecureWebMvcTest(NormalBoardController.class) +public class NormalBoardControllerTest { + + @Autowired + private MockMvc mvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private NormalBoardService normalBoardService; + @MockBean + private BaseBoardRepository baseBoardRepository; + + private String jsonOf(Object response) throws JsonProcessingException { + return objectMapper.writeValueAsString(response); + } + + @DisplayName("게시판 종류 당 글 개수 조회 성공 200") + @Test + void getBoardCount_Success() throws Exception { + // given + BoardCountDto boardCountDto = new BoardCountDto("공지사항", 10); + List dtoList = List.of(boardCountDto); + given(baseBoardRepository.countRowsGroupByMenuId()).willReturn(dtoList); + + // when + String response = + mvc.perform(get("/board/count")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(jsonOf(dtoList)); + } + + @DisplayName("게시글 목록 조회 성공 200") + @Test + void getBoardList_Success() throws Exception { + // given + Member writer = MemberTest.chiefMember(); + NormalBoardDto normalBoardDto = + NormalBoardDto.builder() + .id(1L) + .title("title") + .writerName(writer.getName()) + .dateCreated(LocalDateTime.now()) + .dateUpdated(LocalDateTime.now()) + .isPinned(false) + .build(); + List dtoList = List.of(normalBoardDto); + given(normalBoardService.getPosts(any(),any(),any())).willReturn(dtoList); + + // when + String response = + mvc.perform(get("/board/notice")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(jsonOf(dtoList)); + } + + @DisplayName("게시글 목록 조회 데이터가 올바르지 않다면 400") + @Test + void getBoardList_Invalid_Input() throws Exception { + // when + String response = + mvc.perform(get("/board/invalid")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("게시글 단일 조회 성공 200") + @Test + void getBoard() throws Exception { + // given + Member writer = MemberTest.chiefMember(); + NormalBoardDetailDto normalBoardDetailDto = + NormalBoardDetailDto.builder() + .id(1L) + .title("title") + .content("content") + .writerName(writer.getName()) + .files(null) + .dateCreated(LocalDateTime.now()) + .dateUpdated(LocalDateTime.now()) + .isPinned(false) + .build(); + given(normalBoardService.getPost(any(),any(),any())).willReturn(normalBoardDetailDto); + + // when + String response = + mvc.perform(get("/board/notice/1")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(jsonOf(normalBoardDetailDto)); + } + + @DisplayName("게시글 단일 조회 데이터가 올바르지 않다면 400") + @Test + void getBoard_Invalid_Input() throws Exception { + // when + String response = + mvc.perform(get("/board/notice/invalid")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("게시글 단일 조회 데이터가 올바르지 않다면 404") + @Test + void getBoard_Not_Found() throws Exception { + // given + doThrow(NotFoundException.class).when(normalBoardService).getPost(any(), any(), any()); + + // when + String response = + mvc.perform(get("/board/notice/1")) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } + + @DisplayName("게시글 추가 성공 201") + @Test + void addBoard() throws Exception { + // given + SaveNormalBoardDto saveNormalBoardDto = + new SaveNormalBoardDto("title", "content", null, false); + given(normalBoardService.write(any(),any(),any())).willReturn(1L); + + // when + String header = + mvc.perform( + post("/board/notice") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(saveNormalBoardDto))) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader("Location"); + + // then + assertThat(header).contains("/board/notice/1"); + } + + @DisplayName("게시글 추가 데이터가 올바르지 않다면 400") + @Test + void addBoard_Invalid_Input() throws Exception { + //given + SaveNormalBoardDto saveNormalBoardDto = + new SaveNormalBoardDto("meaningless", "meaningless", null, false); + + // when + String response = + mvc.perform(post("/board/invalid") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(saveNormalBoardDto))) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("게시글 수정 성공 204") + @Test + void updateBoard() throws Exception { + // given + SaveNormalBoardDto saveNormalBoardDto = + new SaveNormalBoardDto("title", "content", null, false); + doNothing().when(normalBoardService).update(any(), any(), any()); + + // when then + mvc.perform( + put("/board/notice/1") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(saveNormalBoardDto))) + .andExpect(status().isNoContent()); + } + + @DisplayName("게시글 수정 데이터가 올바르지 않다면 400") + @Test + void updateBoard_Invalid_Input() throws Exception { + //given + SaveNormalBoardDto saveNormalBoardDto = + new SaveNormalBoardDto("title", "content", null, false); + doThrow(InvalidInputException.class).when(normalBoardService).update(any(), any(), any()); + + // when + String response = + mvc.perform(put("/board/notice/1") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(saveNormalBoardDto))) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("게시글 수정 데이터가 올바르지 않다면 404") + @Test + void updateBoard_Not_Found() throws Exception { + //given + SaveNormalBoardDto saveNormalBoardDto = + new SaveNormalBoardDto("title", "content", null, false); + doThrow(NotFoundException.class).when(normalBoardService).update(any(), any(), any()); + + // when + String response = + mvc.perform(put("/board/notice/1") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(saveNormalBoardDto))) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } + + @DisplayName("게시글 삭제 성공 204") + @Test + void deleteBoard() throws Exception { + // given + doNothing().when(normalBoardService).delete(any()); + + // when then + mvc.perform(delete("/board/notice/1")) + .andExpect(status().isNoContent()); + } + + @DisplayName("게시글 삭제 데이터가 올바르지 않다면 400") + @Test + void deleteBoard_Invalid_Input() throws Exception { + //given + doNothing().when(normalBoardService).delete(any()); + + // when + String response = + mvc.perform(delete("/board/invalid/invalid")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("게시글 삭제 데이터가 올바르지 않다면 404") + @Test + void deleteBoard_Not_Found() throws Exception { + //given + doThrow(NotFoundException.class).when(normalBoardService).delete(any()); + + // when + String response = + mvc.perform(delete("/board/notice/1")) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } + +} \ No newline at end of file From 3e9b83908b9adf7acae715587b41de18d1572535 Mon Sep 17 00:00:00 2001 From: whitemark Date: Sun, 18 Feb 2024 23:08:22 +0900 Subject: [PATCH 12/19] =?UTF-8?q?[feature/#233]=20NormalBoard=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/inhabas/api/config/SwaggerConfig.java | 9 +++++++++ .../com/inhabas/api/config/WebSecurityConfig.java | 12 ++++++++---- .../repository/BaseBoardRepositoryCustom.java | 3 +-- .../board/repository/BaseBoardRepositoryImpl.java | 14 +++++++++----- .../member/usecase/MemberProfileServiceImpl.java | 3 ++- .../com/inhabas/api/web/MyProfileController.java | 2 +- 6 files changed, 30 insertions(+), 13 deletions(-) diff --git a/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java b/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java index aeaf9386..d4883e92 100644 --- a/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java +++ b/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java @@ -98,6 +98,15 @@ public GroupedOpenApi getIBASApi() { .build(); } + @Bean + public GroupedOpenApi getBoardApi() { + + return GroupedOpenApi.builder() + .group("게시판 관련") + .pathsToMatch("/board/**", "/**/**/**/comment/**", "/**/**/**/comments") + .build(); + } + @Bean @Profile("local") public OpenAPI localOpenAPI() { diff --git a/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java b/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java index d62717ad..f2f01e87 100644 --- a/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java +++ b/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java @@ -59,6 +59,9 @@ public class WebSecurityConfig { private static final String[] AUTH_WHITELIST_CLUB_ACTIVITY = { "/club/activity/**", "/club/activities" }; + private static final String[] AUTH_WHITELIST_NORMAL_BOARD = { + "/board/count" + }; @Order(1) @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true) @@ -82,10 +85,11 @@ public void configure(AuthenticationManagerBuilder auth) throws Exception { @Override public void configure(WebSecurity web) throws Exception { web.ignoring() - .antMatchers(HttpMethod.GET, AUTH_WHITELIST_POLICY) - .antMatchers(HttpMethod.GET, AUTH_WHITELIST_SIGNUP) - .antMatchers(HttpMethod.GET, AUTH_WHITELIST_CLUB) - .antMatchers(AUTH_WHITELIST_SWAGGER) + .antMatchers(HttpMethod.GET, AUTH_WHITELIST_POLICY) + .antMatchers(HttpMethod.GET, AUTH_WHITELIST_SIGNUP) + .antMatchers(HttpMethod.GET, AUTH_WHITELIST_CLUB) + .antMatchers(HttpMethod.GET, AUTH_WHITELIST_NORMAL_BOARD) + .antMatchers(AUTH_WHITELIST_SWAGGER) .antMatchers(AUTH_WHITELIST_STATIC) .antMatchers(AUTH_WHITELIST_PATH); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java index 073af9ab..8213eec6 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java @@ -6,6 +6,5 @@ public interface BaseBoardRepositoryCustom { - List countRowsGroupByMenuId(); - + List countRowsGroupByMenuName(Integer menuGroupId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java index eb375686..05310f61 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java @@ -6,6 +6,8 @@ import lombok.RequiredArgsConstructor; import static com.inhabas.api.domain.board.domain.QBaseBoard.baseBoard; +import static com.inhabas.api.domain.menu.domain.QMenu.*; + import java.util.List; @RequiredArgsConstructor @@ -14,16 +16,18 @@ public class BaseBoardRepositoryImpl implements BaseBoardRepositoryCustom { private final JPAQueryFactory queryFactory; @Override - public List countRowsGroupByMenuId() { + public List countRowsGroupByMenuName(Integer menuGroupId) { return queryFactory .select( Projections.constructor( BoardCountDto.class, - baseBoard.menu.id, - baseBoard.id.count() + menu.name.value, + baseBoard.id.count().intValue() )) - .from(baseBoard) - .groupBy(baseBoard.menu.id) + .from(menu) + .leftJoin(baseBoard).on(menu.id.eq(baseBoard.menu.id)) + .where(menu.menuGroup.id.eq(menuGroupId)) + .groupBy(menu.name) .fetch(); } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberProfileServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberProfileServiceImpl.java index 242a6d9d..84cd5581 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberProfileServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberProfileServiceImpl.java @@ -61,7 +61,8 @@ public void updateMyProfileDetail(Long memberId, ProfileDetailDto profileDetailD member.setPhone(profileDetailDto.getPhoneNumber()); if (profileDetailDto.getGrade() != null) member.getSchoolInformation().setGrade(profileDetailDto.getGrade()); - if (profileDetailDto.getGrade() != null) member.setMemberType(profileDetailDto.getType()); + if (profileDetailDto.getType() != null) + member.setMemberType(profileDetailDto.getType()); } @Override diff --git a/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java b/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java index c34ad092..cf331b19 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java @@ -51,7 +51,7 @@ public ResponseEntity getMyProfile(@Authenticated Long memberId) { return ResponseEntity.ok(memberProfileService.getMyProfile(memberId)); } - @Operation(summary = "내 [학과, 학년, 전화번호] 수정", description = "학과, 학년, 전화번호 수정. ") + @Operation(summary = "내 [학과, 학년, 전화번호, 타입] 수정", description = "학과, 학년, 전화번호 수정. ") @ApiResponses( value = { @ApiResponse(responseCode = "204"), From 4781c45604c09c4b51385a3a90939b1e72650740 Mon Sep 17 00:00:00 2001 From: whitemark Date: Sun, 18 Feb 2024 23:12:11 +0900 Subject: [PATCH 13/19] =?UTF-8?q?[feature/#233]=20NormalBoard=20IsPinned?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../normalBoard/dto/SaveNormalBoardDto.java | 7 +- .../NormalBoardRepositoryCustom.java | 1 + .../repository/NormalBoardRepositoryImpl.java | 19 +++++ .../usecase/NormalBoardService.java | 4 +- .../usecase/NormalBoardServiceImpl.java | 73 +++++++++++++------ .../api/web/NormalBoardController.java | 20 +++-- 6 files changed, 87 insertions(+), 37 deletions(-) diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java index 3e7b4040..4f7ef404 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java @@ -5,8 +5,6 @@ import org.springframework.web.multipart.MultipartFile; import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.util.ArrayList; import java.util.List; @Getter @@ -20,13 +18,12 @@ public class SaveNormalBoardDto { private List files; - @NotNull - private Boolean isPinned; + private Boolean isPinned = false; public SaveNormalBoardDto(String title, String content, List files, Boolean isPinned) { this.title = title; this.content = content; - this.files = (files != null) ? files : new ArrayList<>(); + this.files = files; this.isPinned = isPinned; } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java index 7b501db5..2e5f93a2 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java @@ -9,6 +9,7 @@ public interface NormalBoardRepositoryCustom { + List findAllByTypeAndIsPinned(NormalBoardType boardType); List findAllByMemberIdAndTypeAndSearch(Long memberId, NormalBoardType boardType, String search); List findAllByTypeAndSearch(NormalBoardType boardType, String search); Optional findByMemberIdAndTypeAndId(Long memberId, NormalBoardType boardType, Long boardId); diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java index d4b63206..bdda4996 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java @@ -19,6 +19,25 @@ public class NormalBoardRepositoryImpl implements NormalBoardRepositoryCustom { private final JPAQueryFactory queryFactory; + @Override + public List findAllByTypeAndIsPinned(NormalBoardType boardType) { + return queryFactory + .select( + Projections.constructor( + NormalBoardDto.class, + normalBoard.id, + normalBoard.title.value, + normalBoard.writer.name.value, + normalBoard.dateCreated, + normalBoard.dateUpdated, + normalBoard.isPinned)) + .from(normalBoard) + .where(eqNormalBoardType(boardType) + .and(normalBoard.isPinned.isTrue())) + .orderBy(normalBoard.dateCreated.desc()) + .fetch(); + } + @Override public List findAllByMemberIdAndTypeAndSearch(Long memberId, NormalBoardType boardType, String search) { return queryFactory diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java index 17fe6802..eddd1ce4 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java @@ -9,7 +9,9 @@ public interface NormalBoardService { - List getPosts(Long memberId, NormalBoardType boardType, String search); + List getPinned(NormalBoardType boardType); + + List getPosts(NormalBoardType boardType, String search); NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Long boardId); diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java index de479723..6babf100 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java @@ -1,5 +1,7 @@ package com.inhabas.api.domain.normalBoard.usecase; +import com.inhabas.api.auth.domain.error.authException.InvalidAuthorityException; +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; import com.inhabas.api.auth.domain.error.businessException.NotFoundException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.exception.MemberNotFoundException; @@ -19,13 +21,16 @@ import com.inhabas.api.global.util.FileUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import javax.transaction.Transactional; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; +import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.EXECUTIVE; +import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.NOTICE; + @Service @Slf4j @Transactional @@ -37,14 +42,30 @@ public class NormalBoardServiceImpl implements NormalBoardService { private final MemberRepository memberRepository; private final S3Service s3Service; + private static final Set hasPinnedBoardTypeSet = new HashSet<>( + Arrays.asList(NOTICE, EXECUTIVE)); + + + @Override + public List getPinned(NormalBoardType boardType) { + List normalBoardList = new ArrayList<>(); + if (boardType.equals(NOTICE) || boardType.equals(NormalBoardType.EXECUTIVE)) { + normalBoardList = normalBoardRepository.findAllByTypeAndIsPinned(boardType); + } + return normalBoardList; + } @Override - public List getPosts(Long memberId, NormalBoardType boardType, String search) { - List normalBoardList; + public List getPosts(NormalBoardType boardType, String search) { + List normalBoardList = getPinned(boardType); if (boardType.equals(NormalBoardType.SUGGEST)) { - normalBoardList = normalBoardRepository.findAllByMemberIdAndTypeAndSearch(memberId, boardType, search); + if (SecurityContextHolder.getContext() == null) { + throw new InvalidAuthorityException(); + } + Long memberId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + normalBoardList.addAll(normalBoardRepository.findAllByMemberIdAndTypeAndSearch(memberId, boardType, search)); } else { - normalBoardList = normalBoardRepository.findAllByTypeAndSearch(boardType, search); + normalBoardList.addAll(normalBoardRepository.findAllByTypeAndSearch(boardType, search)); } return normalBoardList; } @@ -79,29 +100,31 @@ public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Lo } @Override - public Long write(Long memberId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto) { + public Long write(Long memberId, NormalBoardType boardType, SaveNormalBoardDto saveNormalBoardDto) { Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - Menu menu = menuRepository.findById(normalBoardType.getMenuId()).orElseThrow(NotFoundException::new); - - NormalBoard normalBoard = - new NormalBoard( - saveNormalBoardDto.getTitle(), - menu, - saveNormalBoardDto.getContent(), - saveNormalBoardDto.getIsPinned()) - .writtenBy(writer, NormalBoard.class); - - return updateNormalBoardFiles(saveNormalBoardDto, normalBoardType, normalBoard); - } + Menu menu = menuRepository.findById(boardType.getMenuId()).orElseThrow(NotFoundException::new); + if (!hasPinned(boardType) && saveNormalBoardDto.getIsPinned()) { + throw new InvalidInputException(); + } + NormalBoard normalBoard = + new NormalBoard( + saveNormalBoardDto.getTitle(), + menu, + saveNormalBoardDto.getContent(), + saveNormalBoardDto.getIsPinned()) + .writtenBy(writer, NormalBoard.class); + + return updateNormalBoardFiles(saveNormalBoardDto, boardType, normalBoard); + } @Override - public void update(Long boardId, NormalBoardType normalBoardType, SaveNormalBoardDto saveNormalBoardDto) { + public void update(Long boardId, NormalBoardType boardType, SaveNormalBoardDto saveNormalBoardDto) { NormalBoard normalBoard = normalBoardRepository.findById(boardId).orElseThrow(NotFoundException::new); - updateNormalBoardFiles(saveNormalBoardDto, normalBoardType, normalBoard); + updateNormalBoardFiles(saveNormalBoardDto, boardType, normalBoard); } @Override @@ -111,8 +134,8 @@ public void delete(Long boardId) { private Long updateNormalBoardFiles( - SaveNormalBoardDto saveNormalBoardDto, NormalBoardType normalBoardType, NormalBoard normalBoard) { - final String DIR_NAME = "/" + normalBoardType.getBoardType(); + SaveNormalBoardDto saveNormalBoardDto, NormalBoardType boardType, NormalBoard normalBoard) { + final String DIR_NAME = "/" + boardType.getBoardType(); List updateFiles = new ArrayList<>(); List urlListForDelete = new ArrayList<>(); @@ -146,4 +169,8 @@ private Long updateNormalBoardFiles( return normalBoardRepository.save(normalBoard).getId(); } + private boolean hasPinned(NormalBoardType boardType) { + return hasPinnedBoardTypeSet.contains(boardType); + } + } diff --git a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java index 5554fc4d..1650dffb 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java @@ -1,7 +1,7 @@ package com.inhabas.api.web; import com.inhabas.api.auth.domain.error.ErrorResponse; -import com.inhabas.api.domain.board.dto.*; +import com.inhabas.api.domain.board.dto.BoardCountDto; import com.inhabas.api.domain.board.repository.BaseBoardRepository; import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; import com.inhabas.api.domain.normalBoard.dto.NormalBoardDetailDto; @@ -26,9 +26,11 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import javax.validation.Valid; @@ -54,7 +56,7 @@ public class NormalBoardController { @GetMapping("/board/count") @SecurityRequirements(value = {}) public ResponseEntity> getBoardCount() { - return ResponseEntity.ok(baseBoardRepository.countRowsGroupByMenuId()); + return ResponseEntity.ok(baseBoardRepository.countRowsGroupByMenuName(2)); } @Operation(summary = "게시글 목록 조회") @@ -88,11 +90,10 @@ public ResponseEntity> getBoardList( @Parameter(description = "검색어 (작성자 이름 or 제목 or 내용)", example = "") @RequestParam(name = "search", defaultValue = "") String search, - @PathVariable NormalBoardType boardType, - @Authenticated Long memberId) { + @PathVariable NormalBoardType boardType) { Pageable pageable = PageRequest.of(page, size); - List allDtos = normalBoardService.getPosts(memberId, boardType, search); + List allDtos = normalBoardService.getPosts(boardType, search); List pagedDtos = PageUtil.getPagedDtoList(pageable, allDtos); PageImpl normalBoardDtoPage = @@ -141,7 +142,7 @@ public ResponseEntity getBoard( } @Operation(summary = "게시글 추가") - @PostMapping("/board/{boardType}") + @PostMapping(path = "/board/{boardType}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @PreAuthorize( "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).CREATE_BOARD)" ) @@ -161,8 +162,11 @@ public ResponseEntity getBoard( public ResponseEntity addBoard( @Authenticated Long memberId, @PathVariable NormalBoardType boardType, - @Valid @RequestBody SaveNormalBoardDto saveNormalBoardDto) { - + @RequestPart("title") String title, + @RequestPart("content") String content, + @RequestPart(value = "files", required = false) List files, + @RequestPart(value = "isPinned", required = false) Boolean isPinned) { + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto(title, content, files, isPinned); Long newNormalBoardId = normalBoardService.write(memberId, boardType, saveNormalBoardDto); URI location = ServletUriComponentsBuilder.fromCurrentRequest() From 774a314da2e6698184852dd660ee78cd92411ff9 Mon Sep 17 00:00:00 2001 From: whitemark Date: Mon, 19 Feb 2024 23:29:28 +0900 Subject: [PATCH 14/19] =?UTF-8?q?[feature/#233]=20NormalBoard=20=EC=84=B8?= =?UTF-8?q?=EB=B6=80=20=EC=82=AC=ED=95=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/usecase/MemberManageServiceImpl.java | 15 +++++++++------ .../normalBoard/dto/NormalBoardDetailDto.java | 4 ++++ .../domain/normalBoard/dto/NormalBoardDto.java | 4 ++++ .../repository/NormalBoardRepositoryImpl.java | 13 +++++++++---- .../usecase/NormalBoardServiceImpl.java | 7 ++++--- .../inhabas/api/web/NormalBoardController.java | 17 ++++++++++------- 6 files changed, 40 insertions(+), 20 deletions(-) diff --git a/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberManageServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberManageServiceImpl.java index 80a5f9fe..06a46f85 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberManageServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberManageServiceImpl.java @@ -2,16 +2,14 @@ import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -44,6 +42,7 @@ public class MemberManageServiceImpl implements MemberManageService { private static final String FAIL_STATE = "fail"; private static final String PASS_EMAIL_SUBJECT = "[IBAS] 축하합니다. 동아리에 입부되셨습니다."; private static final String FAIL_EMAIL_SUBJECT = "[IBAS] 입부 신청 결과를 알립니다."; + private static final String ROLE_PREFIX = "ROLE_"; private final MemberRepository memberRepository; private final SMTPService amazonSMTPService; private final AnswerRepository answerRepository; @@ -198,8 +197,7 @@ private void validateMemberRolesToUpdate( List members = memberRepository.findAllById(memberIdList); boolean allApprovedMembers; - if (authentication.getAuthorities().contains("ROLE_" + VICE_CHIEF) - || authentication.getAuthorities().contains("ROLE_" + CHIEF)) { + if (hasRoleToChange(authentication, CHIEF) || hasRoleToChange(authentication, VICE_CHIEF)) { if (!CHIEF_CHANGEABLE_ROLES.contains(role)) { throw new InvalidInputException(); } @@ -217,6 +215,11 @@ private void validateMemberRolesToUpdate( } } + private boolean hasRoleToChange(Authentication authentication, Role role) { + return authentication.getAuthorities().stream() + .anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(ROLE_PREFIX + role)); + } + private boolean checkAllMembersHaveAllowedRoles(List members, Set allowedRoles) { return members.stream().allMatch(member -> allowedRoles.contains(member.getRole())); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java index ff5af0a9..2547c457 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java @@ -25,6 +25,8 @@ public class NormalBoardDetailDto { private String title; @NotBlank private String content; + @NotNull + private Long writerId; @NotBlank private String writerName; @@ -48,6 +50,7 @@ public NormalBoardDetailDto( Long id, String title, String content, + Long writerId, String writerName, LocalDateTime dateCreated, LocalDateTime dateUpdated, @@ -56,6 +59,7 @@ public NormalBoardDetailDto( this.id = id; this.title = title; this.content = content; + this.writerId = writerId; this.writerName = writerName; this.dateCreated = dateCreated; this.dateUpdated = dateUpdated; diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java index c6108ed2..7e74b29a 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java @@ -22,6 +22,9 @@ public class NormalBoardDto { @NotBlank private String title; + @NotNull + private Long writerId; + @NotBlank private String writerName; @@ -42,6 +45,7 @@ public class NormalBoardDto { public NormalBoardDto(Long id, String title, String writerName, LocalDateTime dateCreated, LocalDateTime dateUpdated, Boolean isPinned) { this.id = id; this.title = title; + this.writerId = writerId; this.writerName = writerName; this.dateCreated = dateCreated; this.dateUpdated = dateUpdated; diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java index bdda4996..b12dfbe5 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java @@ -5,9 +5,11 @@ import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.DateTimePath; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -27,6 +29,7 @@ public List findAllByTypeAndIsPinned(NormalBoardType boardType) NormalBoardDto.class, normalBoard.id, normalBoard.title.value, + normalBoard.writer.id, normalBoard.writer.name.value, normalBoard.dateCreated, normalBoard.dateUpdated, @@ -46,15 +49,16 @@ public List findAllByMemberIdAndTypeAndSearch(Long memberId, Nor NormalBoardDto.class, normalBoard.id, normalBoard.title.value, + normalBoard.writer.id, normalBoard.writer.name.value, + normalBoard.datePinExpiration, normalBoard.dateCreated, normalBoard.dateUpdated, normalBoard.isPinned)) .from(normalBoard) .where(eqMemberId(memberId) .and(eqNormalBoardType(boardType)) - .and(likeTitle(search)) - .or(likeContent(search))) + .and(likeTitle(search).or(likeContent(search)))) .orderBy(normalBoard.dateCreated.desc()) .fetch(); } @@ -67,14 +71,15 @@ public List findAllByTypeAndSearch(NormalBoardType boardType, St NormalBoardDto.class, normalBoard.id, normalBoard.title.value, + normalBoard.writer.id, normalBoard.writer.name.value, + normalBoard.datePinExpiration, normalBoard.dateCreated, normalBoard.dateUpdated, normalBoard.isPinned)) .from(normalBoard) .where(eqNormalBoardType(boardType) - .and(likeTitle(search)) - .or(likeContent(search))) + .and(likeTitle(search).or(likeContent(search)))) .orderBy(normalBoard.dateCreated.desc()) .fetch(); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java index 6babf100..8abc8da9 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java @@ -57,8 +57,8 @@ public List getPinned(NormalBoardType boardType) { @Override public List getPosts(NormalBoardType boardType, String search) { - List normalBoardList = getPinned(boardType); - if (boardType.equals(NormalBoardType.SUGGEST)) { + List normalBoardList = new ArrayList<>(); + if (boardType.equals(SUGGEST)) { if (SecurityContextHolder.getContext() == null) { throw new InvalidAuthorityException(); } @@ -74,7 +74,7 @@ public List getPosts(NormalBoardType boardType, String search) { public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Long boardId) { NormalBoard normalBoard; List fileDownloadDtoList = null; - if (boardType.equals(NormalBoardType.SUGGEST)) { + if (boardType.equals(SUGGEST)) { normalBoard = normalBoardRepository.findByMemberIdAndTypeAndId(memberId, boardType, boardId).orElseThrow(NotFoundException::new); } else { normalBoard = normalBoardRepository.findByTypeAndId(boardType, boardId).orElseThrow(NotFoundException::new); @@ -91,6 +91,7 @@ public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Lo .id(normalBoard.getId()) .title(normalBoard.getTitle()) .content(normalBoard.getContent()) + .writerId(normalBoard.getWriter().getId()) .writerName(normalBoard.getWriter().getName()) .dateCreated(normalBoard.getDateCreated()) .dateUpdated(normalBoard.getDateUpdated()) diff --git a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java index 1650dffb..7d41f1aa 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java @@ -33,7 +33,6 @@ import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import javax.validation.Valid; import java.net.URI; import java.util.List; @@ -165,11 +164,12 @@ public ResponseEntity addBoard( @RequestPart("title") String title, @RequestPart("content") String content, @RequestPart(value = "files", required = false) List files, - @RequestPart(value = "isPinned", required = false) Boolean isPinned) { - SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto(title, content, files, isPinned); + @RequestParam(value = "pinOption", required = false) Integer pinOption) { + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto(title, content, files, pinOption); Long newNormalBoardId = normalBoardService.write(memberId, boardType, saveNormalBoardDto); URI location = ServletUriComponentsBuilder.fromCurrentRequest() + .replaceQueryParam("pinOption") .path("/board/{boardType}/{boardId}") .buildAndExpand(boardType.getBoardType(), newNormalBoardId) .toUri(); @@ -178,7 +178,7 @@ public ResponseEntity addBoard( } @Operation(summary = "게시글 수정") - @PutMapping("/board/{boardType}/{boardId}") + @PostMapping(value = "/board/{boardType}/{boardId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @ApiResponses({ @ApiResponse(responseCode = "200"), @ApiResponse( @@ -207,13 +207,16 @@ public ResponseEntity updateBoard( @Authenticated Long memberId, @PathVariable NormalBoardType boardType, @PathVariable Long boardId, - @Valid @RequestBody SaveNormalBoardDto saveNormalBoardDto) { - + @RequestPart("title") String title, + @RequestPart("content") String content, + @RequestPart(value = "files", required = false) List files, + @RequestParam(value = "pinOption", required = false) Integer pinOption) { + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto(title, content, files, pinOption); normalBoardService.update(boardId, boardType, saveNormalBoardDto); return ResponseEntity.noContent().build(); } - @Operation(description = "게시글 삭제") + @Operation(summary = "게시글 삭제") @DeleteMapping("/board/{boardType}/{boardId}") @ApiResponses({ @ApiResponse(responseCode = "204"), From 941cbd668f82977ad53d376f0bad10902bb5a10a Mon Sep 17 00:00:00 2001 From: whitemark Date: Mon, 19 Feb 2024 23:32:30 +0900 Subject: [PATCH 15/19] =?UTF-8?q?[feature/#233]=20NormalBoard=20Pin=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../normalBoard/domain/NormalBoard.java | 17 +++++- .../domain/normalBoard/domain/PinOption.java | 18 ++++++ .../normalBoard/dto/NormalBoardDetailDto.java | 7 +++ .../normalBoard/dto/NormalBoardDto.java | 9 ++- .../normalBoard/dto/SaveNormalBoardDto.java | 6 +- .../repository/NormalBoardRepositoryImpl.java | 5 +- .../usecase/NormalBoardServiceImpl.java | 59 ++++++++++++++----- .../global/dto/PagedPinnedResponseDto.java | 28 +++++++++ .../api/web/NormalBoardController.java | 12 ++-- 9 files changed, 133 insertions(+), 28 deletions(-) create mode 100644 resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/PinOption.java create mode 100644 resource-server/src/main/java/com/inhabas/api/global/dto/PagedPinnedResponseDto.java diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java index 57a51542..7c0701e1 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java @@ -11,6 +11,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -28,15 +29,20 @@ public class NormalBoard extends BaseBoard { @Column private Boolean isPinned = false; + @Column(columnDefinition = "DATETIME(0)") + private LocalDateTime datePinExpiration; + @OneToMany(mappedBy = "parentBoard", cascade = CascadeType.ALL, orphanRemoval = true) private List comments = new ArrayList<>(); /* constructor */ - public NormalBoard(String title, Menu menu, String content, Boolean isPinned) { + public NormalBoard(String title, Menu menu, String content, + Boolean isPinned, LocalDateTime datePinExpiration) { super(title, menu); this.content = new Content(content); this.isPinned = isPinned; + this.datePinExpiration = datePinExpiration; } /* getter */ @@ -45,6 +51,10 @@ public Boolean getPinned() { return isPinned; } + public LocalDateTime getDatePinExpiration() { + return datePinExpiration; + } + public String getContent() { return content.getValue(); } @@ -73,4 +83,9 @@ public void updateFiles(List files) { } } + public void updatePinned(Boolean isPinned, LocalDateTime datePinExpiration) { + this.isPinned = isPinned; + this.datePinExpiration = datePinExpiration; + } + } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/PinOption.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/PinOption.java new file mode 100644 index 00000000..5f825db3 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/PinOption.java @@ -0,0 +1,18 @@ +package com.inhabas.api.domain.normalBoard.domain; + +public enum PinOption { + + DISABLED(0), + TEMPORARY(1), + PERMANENT(2); + + private final Integer option; + + PinOption(Integer option) { + this.option = option; + } + + public Integer getOption() { + return option; + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java index 2547c457..ff82fc15 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java @@ -30,6 +30,11 @@ public class NormalBoardDetailDto { @NotBlank private String writerName; + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime datePinExpiration; + @NotNull @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") @Schema(type = "string", example = "2024-11-01T00:00:00") @@ -52,6 +57,7 @@ public NormalBoardDetailDto( String content, Long writerId, String writerName, + LocalDateTime datePinExpiration, LocalDateTime dateCreated, LocalDateTime dateUpdated, List files, @@ -61,6 +67,7 @@ public NormalBoardDetailDto( this.content = content; this.writerId = writerId; this.writerName = writerName; + this.datePinExpiration = datePinExpiration; this.dateCreated = dateCreated; this.dateUpdated = dateUpdated; this.files = files; diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java index 7e74b29a..f1e6e808 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java @@ -28,6 +28,11 @@ public class NormalBoardDto { @NotBlank private String writerName; + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime datePinExpiration; + @NotNull @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") @Schema(type = "string", example = "2024-11-01T00:00:00") @@ -42,11 +47,13 @@ public class NormalBoardDto { private Boolean isPinned; @Builder - public NormalBoardDto(Long id, String title, String writerName, LocalDateTime dateCreated, LocalDateTime dateUpdated, Boolean isPinned) { + public NormalBoardDto(Long id, String title, Long writerId, String writerName, LocalDateTime datePinExpiration, + LocalDateTime dateCreated, LocalDateTime dateUpdated, Boolean isPinned) { this.id = id; this.title = title; this.writerId = writerId; this.writerName = writerName; + this.datePinExpiration = datePinExpiration; this.dateCreated = dateCreated; this.dateUpdated = dateUpdated; this.isPinned = isPinned; diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java index 4f7ef404..58667bae 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java @@ -18,12 +18,12 @@ public class SaveNormalBoardDto { private List files; - private Boolean isPinned = false; + private Integer pinOption; - public SaveNormalBoardDto(String title, String content, List files, Boolean isPinned) { + public SaveNormalBoardDto(String title, String content, List files, Integer pinOption) { this.title = title; this.content = content; this.files = files; - this.isPinned = isPinned; + this.pinOption = pinOption; } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java index b12dfbe5..109c7a03 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java @@ -5,7 +5,6 @@ import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.core.types.dsl.DateTimePath; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; @@ -31,12 +30,14 @@ public List findAllByTypeAndIsPinned(NormalBoardType boardType) normalBoard.title.value, normalBoard.writer.id, normalBoard.writer.name.value, + normalBoard.datePinExpiration, normalBoard.dateCreated, normalBoard.dateUpdated, normalBoard.isPinned)) .from(normalBoard) .where(eqNormalBoardType(boardType) - .and(normalBoard.isPinned.isTrue())) + .and(normalBoard.isPinned.isTrue()) + .and(normalBoard.datePinExpiration.after(LocalDateTime.now()))) .orderBy(normalBoard.dateCreated.desc()) .fetch(); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java index 8abc8da9..a2effa42 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java @@ -25,11 +25,14 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; +import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.*; import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.EXECUTIVE; import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.NOTICE; +import static com.inhabas.api.domain.normalBoard.domain.PinOption.*; @Service @Slf4j @@ -44,12 +47,14 @@ public class NormalBoardServiceImpl implements NormalBoardService { private static final Set hasPinnedBoardTypeSet = new HashSet<>( Arrays.asList(NOTICE, EXECUTIVE)); - + private static final LocalDateTime PERMANENT_DATE = + LocalDateTime.of(2200, 1, 1, 0, 0, 0); + private static final Integer TEMPORARY_DAYS = 14; @Override public List getPinned(NormalBoardType boardType) { List normalBoardList = new ArrayList<>(); - if (boardType.equals(NOTICE) || boardType.equals(NormalBoardType.EXECUTIVE)) { + if (boardType.equals(NOTICE) || boardType.equals(EXECUTIVE)) { normalBoardList = normalBoardRepository.findAllByTypeAndIsPinned(boardType); } return normalBoardList; @@ -93,6 +98,7 @@ public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Lo .content(normalBoard.getContent()) .writerId(normalBoard.getWriter().getId()) .writerName(normalBoard.getWriter().getName()) + .datePinExpiration(normalBoard.getDatePinExpiration()) .dateCreated(normalBoard.getDateCreated()) .dateUpdated(normalBoard.getDateUpdated()) .files(fileDownloadDtoList) @@ -105,26 +111,27 @@ public Long write(Long memberId, NormalBoardType boardType, SaveNormalBoardDto s Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); Menu menu = menuRepository.findById(boardType.getMenuId()).orElseThrow(NotFoundException::new); - if (!hasPinned(boardType) && saveNormalBoardDto.getIsPinned()) { - throw new InvalidInputException(); - } - NormalBoard normalBoard = - new NormalBoard( - saveNormalBoardDto.getTitle(), - menu, - saveNormalBoardDto.getContent(), - saveNormalBoardDto.getIsPinned()) - .writtenBy(writer, NormalBoard.class); - - return updateNormalBoardFiles(saveNormalBoardDto, boardType, normalBoard); - } + + NormalBoard normalBoard = new NormalBoard( + saveNormalBoardDto.getTitle(), + menu, + saveNormalBoardDto.getContent(), + false, + null + ).writtenBy(writer, NormalBoard.class); + + updateNormalBoardPinned(saveNormalBoardDto, boardType, normalBoard); + return updateNormalBoardFiles(saveNormalBoardDto, boardType, normalBoard); + + } + @Override public void update(Long boardId, NormalBoardType boardType, SaveNormalBoardDto saveNormalBoardDto) { NormalBoard normalBoard = normalBoardRepository.findById(boardId).orElseThrow(NotFoundException::new); - + updateNormalBoardPinned(saveNormalBoardDto, boardType, normalBoard); updateNormalBoardFiles(saveNormalBoardDto, boardType, normalBoard); } @@ -170,6 +177,26 @@ private Long updateNormalBoardFiles( return normalBoardRepository.save(normalBoard).getId(); } + private void updateNormalBoardPinned(SaveNormalBoardDto saveNormalBoardDto, NormalBoardType boardType, NormalBoard normalBoard) { + boolean isPinned = false; + LocalDateTime datePinExpiration = null; + + if (hasPinned(boardType)) { + if (saveNormalBoardDto.getPinOption() == null) { + throw new InvalidInputException(); + } else if (saveNormalBoardDto.getPinOption().equals(TEMPORARY.getOption())) { + isPinned = true; + datePinExpiration = LocalDateTime.now().plusDays(TEMPORARY_DAYS); + } else if (saveNormalBoardDto.getPinOption().equals(PERMANENT.getOption())) { + isPinned = true; + datePinExpiration = PERMANENT_DATE; + } + } + + normalBoard.updatePinned(isPinned, datePinExpiration); + + } + private boolean hasPinned(NormalBoardType boardType) { return hasPinnedBoardTypeSet.contains(boardType); } diff --git a/resource-server/src/main/java/com/inhabas/api/global/dto/PagedPinnedResponseDto.java b/resource-server/src/main/java/com/inhabas/api/global/dto/PagedPinnedResponseDto.java new file mode 100644 index 00000000..24eb2ed9 --- /dev/null +++ b/resource-server/src/main/java/com/inhabas/api/global/dto/PagedPinnedResponseDto.java @@ -0,0 +1,28 @@ +package com.inhabas.api.global.dto; + +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + + +import javax.validation.constraints.NotNull; +import java.util.List; + +@Data +@NoArgsConstructor +public class PagedPinnedResponseDto { + + @NotNull + private PageInfoDto pageInfo; + + private List pinnedData; + + @NotNull private List data; + + @Builder + public PagedPinnedResponseDto(PageInfoDto pageInfo, List pinnedData, List data) { + this.pageInfo = pageInfo; + this.pinnedData = pinnedData; + this.data = data; + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java index 7d41f1aa..5d63d29d 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java @@ -9,6 +9,7 @@ import com.inhabas.api.domain.normalBoard.dto.SaveNormalBoardDto; import com.inhabas.api.domain.normalBoard.usecase.NormalBoardService; import com.inhabas.api.global.dto.PageInfoDto; +import com.inhabas.api.global.dto.PagedPinnedResponseDto; import com.inhabas.api.global.dto.PagedResponseDto; import com.inhabas.api.global.util.PageUtil; import com.inhabas.api.web.argumentResolver.Authenticated; @@ -79,7 +80,7 @@ public ResponseEntity> getBoardCount() { @PreAuthorize( "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD_LIST)" ) - public ResponseEntity> getBoardList( + public ResponseEntity> getBoardList( @Parameter(description = "페이지", example = "0") @RequestParam(name = "page", defaultValue = "0") int page, @@ -92,14 +93,15 @@ public ResponseEntity> getBoardList( @PathVariable NormalBoardType boardType) { Pageable pageable = PageRequest.of(page, size); - List allDtos = normalBoardService.getPosts(boardType, search); - List pagedDtos = PageUtil.getPagedDtoList(pageable, allDtos); + List allDtoList = normalBoardService.getPosts(boardType, search); + List pinnedDtoList = normalBoardService.getPinned(boardType); + List pagedDtoList = PageUtil.getPagedDtoList(pageable, allDtoList); PageImpl normalBoardDtoPage = - new PageImpl<>(pagedDtos, pageable, allDtos.size()); + new PageImpl<>(pagedDtoList, pageable, allDtoList.size()); PageInfoDto pageInfoDto = new PageInfoDto(normalBoardDtoPage); - return ResponseEntity.ok(new PagedResponseDto<>(pageInfoDto, pagedDtos)); + return ResponseEntity.ok(new PagedPinnedResponseDto<>(pageInfoDto, pinnedDtoList, pagedDtoList)); } @Operation(summary = "게시글 단일 조회") From 725c0cb5a7622fcfad3598db0af6283d50263568 Mon Sep 17 00:00:00 2001 From: whitemark Date: Tue, 20 Feb 2024 00:50:27 +0900 Subject: [PATCH 16/19] =?UTF-8?q?[feature/#233]=20NormalBoard=20test=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inhabas/api/web/ExceptionController.java | 9 +++ .../domain/NormalBoardExampleTest.java | 10 ++- .../normalBoard/domain/NormalBoardTest.java | 5 +- .../dto/NormalBoardDetailDtoTest.java | 12 ++-- .../normalBoard/dto/NormalBoardDtoTest.java | 10 ++- .../dto/SaveNormalBoardDtoTest.java | 4 +- .../usecase/NormalBoardServiceImplTest.java | 20 +++--- .../api/securityConfig/RoleHierarchyTest.java | 8 +-- .../api/web/NormalBoardControllerTest.java | 72 +++++++++++-------- 9 files changed, 82 insertions(+), 68 deletions(-) diff --git a/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java b/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java index 79e25367..2da0acab 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java @@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; +import org.springframework.web.multipart.support.MissingServletRequestPartException; import org.springframework.web.servlet.NoHandlerFoundException; import com.inhabas.api.auth.domain.error.ErrorResponse; @@ -114,4 +115,12 @@ protected ResponseEntity processValidationError(MethodArgumentNotValidEx final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); return new ResponseEntity<>(response, BAD_REQUEST); } + + @ExceptionHandler(MissingServletRequestPartException.class) + protected ResponseEntity processRequestPartError(MissingServletRequestPartException e) { + log.error("RequestPart validation failed", e); + final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); + return new ResponseEntity<>(response, BAD_REQUEST); + } + } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java index ce185d14..e79556de 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java @@ -1,27 +1,25 @@ package com.inhabas.api.domain.normalBoard.domain; import com.inhabas.api.domain.menu.domain.Menu; -import com.inhabas.api.domain.menu.domain.MenuGroup; -import com.inhabas.api.domain.menu.domain.valueObject.MenuType; import org.springframework.test.util.ReflectionTestUtils; public class NormalBoardExampleTest { public static NormalBoard getBoard1(Menu menu) { - return new NormalBoard("이건 공지1", menu, "이건 공지1입니다.", false); + return new NormalBoard("이건 공지1", menu, "이건 공지1입니다.", false, null); } public static NormalBoard getBoard2(Menu menu) { - return new NormalBoard("이건 공지2", menu, "이건 공지2입니다.", false); + return new NormalBoard("이건 공지2", menu, "이건 공지2입니다.", false, null); } public static NormalBoard getBoard3(Menu menu) { - return new NormalBoard("이건 공지3", menu, "이건 공지3입니다.", false); + return new NormalBoard("이건 공지3", menu, "이건 공지3입니다.", false, null); } public static NormalBoard getTestBoard(Integer id, Menu menu) { - NormalBoard board = new NormalBoard("이건 공지", menu, "이건 공지입니다.", false); + NormalBoard board = new NormalBoard("이건 공지", menu, "이건 공지입니다.", false, null); ReflectionTestUtils.setField(board, "id", id); return board; } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java index eada2b73..e283f60c 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java @@ -1,7 +1,5 @@ package com.inhabas.api.domain.normalBoard.domain; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.domain.board.domain.AlbumBoard; import com.inhabas.api.domain.file.domain.BoardFile; import com.inhabas.api.domain.menu.domain.Menu; import org.assertj.core.api.Assertions; @@ -10,7 +8,6 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.springframework.test.util.ReflectionTestUtils; import java.util.ArrayList; import java.util.List; @@ -29,7 +26,7 @@ public void setUp() { String title = "title1"; String content = "content1"; - normalBoard = new NormalBoard(title, menu, content, false); + normalBoard = new NormalBoard(title, menu, content, false, null); } @DisplayName("올바른 NormalBoard 를 생성한다.") diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java index 937fb758..197f3a4c 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java @@ -5,7 +5,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.web.multipart.MultipartFile; import javax.validation.ConstraintViolation; import javax.validation.Validation; @@ -16,7 +15,8 @@ import java.util.List; import java.util.Set; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; class NormalBoardDetailDtoTest { @@ -40,8 +40,8 @@ public static void close() { public void NormalBoardDetailDto_is_OK() { // given NormalBoardDetailDto normalBoardDetailDto = - new NormalBoardDetailDto(1L, "title", "content", "writer", - LocalDateTime.now(), LocalDateTime.now(), emptyList, false); + new NormalBoardDetailDto(1L, "title", "content", 1L, "writer", + LocalDateTime.now(), LocalDateTime.now(), LocalDateTime.now(), emptyList, false); // when Set> violations = validator.validate(normalBoardDetailDto); @@ -55,8 +55,8 @@ public void NormalBoardDetailDto_is_OK() { public void Title_is_null() { // given NormalBoardDetailDto normalBoardDetailDto = - new NormalBoardDetailDto(1L, null, "content", "writer", - LocalDateTime.now(), LocalDateTime.now(), emptyList, false); + new NormalBoardDetailDto(1L, null, "content", 1L, "writer", + LocalDateTime.now(), LocalDateTime.now(), LocalDateTime.now(), emptyList, false); // when Set> violations = validator.validate(normalBoardDetailDto); diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java index 82e3207f..08d4cc56 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java @@ -4,18 +4,16 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.web.multipart.MultipartFile; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; import java.util.Set; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; class NormalBoardDtoTest { @@ -38,7 +36,7 @@ public static void close() { public void NormalBoardDto_is_OK() { // given NormalBoardDto normalBoardDto = - new NormalBoardDto(1L, "title", "writer", + new NormalBoardDto(1L, "title", 1L, "writer", LocalDateTime.now(), LocalDateTime.now(), LocalDateTime.now(), false); // when @@ -53,7 +51,7 @@ public void NormalBoardDto_is_OK() { public void Title_is_null() { // given NormalBoardDto normalBoardDto = - new NormalBoardDto(1L, null, "writer", + new NormalBoardDto(1L, null, 1L, "writer", LocalDateTime.now(), LocalDateTime.now(), LocalDateTime.now(), false); // when diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java index d8607a8e..2c86b083 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java @@ -39,7 +39,7 @@ public static void close() { public void SaveNormalBoardDto_is_OK() { // given SaveNormalBoardDto saveNormalBoardDto = - new SaveNormalBoardDto("title", "content", emptyList, false); + new SaveNormalBoardDto("title", "content", emptyList, 2); // when Set> violations = validator.validate(saveNormalBoardDto); @@ -52,7 +52,7 @@ public void SaveNormalBoardDto_is_OK() { @Test public void Content_is_null() { // given - SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", null, emptyList,false); + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", null, emptyList,2); // when Set> violations = validator.validate(saveNormalBoardDto); diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java index fedbf678..c4ebf3cb 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java @@ -20,7 +20,6 @@ import org.springframework.test.util.ReflectionTestUtils; import java.time.LocalDateTime; -import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -54,15 +53,14 @@ public class NormalBoardServiceImplTest { @Test void getPosts() { // given - Member member = MemberTest.chiefMember(); - NormalBoardDto dto = new NormalBoardDto( - 1L, "title", member.getName(), LocalDateTime.now(), LocalDateTime.now(), false); + NormalBoardDto dto = new NormalBoardDto(1L, "title", 1L, "writer", LocalDateTime.now(), + LocalDateTime.now(), LocalDateTime.now(), false); given(normalBoardRepository.findAllByTypeAndSearch(any(), any())) - .willReturn(Arrays.asList(dto)); + .willReturn(List.of(dto)); // when - List clubActivityDtoList = normalBoardService.getPosts(1L, NOTICE, ""); + List clubActivityDtoList = normalBoardService.getPosts(NOTICE, ""); // then assertThat(clubActivityDtoList).hasSize(1); @@ -75,7 +73,7 @@ void getPost() { Member member = MemberTest.chiefMember(); Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); NormalBoard normalBoard = - new NormalBoard("title", menu, "content", false) + new NormalBoard("title", menu, "content", false, LocalDateTime.now()) .writtenBy(member, NormalBoard.class); given(normalBoardRepository.findByTypeAndId(any(), any())).willReturn(Optional.of(normalBoard)); @@ -93,10 +91,10 @@ void getPost() { void write() { //given Member member = MemberTest.chiefMember(); - SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", "content", null, false); + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", "content", null, 2); Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); NormalBoard normalBoard = - new NormalBoard("title", menu, "content", false) + new NormalBoard("title", menu, "content", false, LocalDateTime.now()) .writtenBy(member, NormalBoard.class); given(memberRepository.findById(any())).willReturn(Optional.of(member)); @@ -115,9 +113,9 @@ void write() { @Test void update() { //given - SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", "content", null, false); + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", "content", null, 2); Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); - NormalBoard normalBoard = new NormalBoard("title", menu, "content", false); + NormalBoard normalBoard = new NormalBoard("title", menu, "content", false, LocalDateTime.now()); ReflectionTestUtils.setField(normalBoard, "id", 1L); given(normalBoardRepository.findById(any())).willReturn(Optional.of(normalBoard)); diff --git a/resource-server/src/test/java/com/inhabas/api/securityConfig/RoleHierarchyTest.java b/resource-server/src/test/java/com/inhabas/api/securityConfig/RoleHierarchyTest.java index 2a17e3c2..45bc9496 100644 --- a/resource-server/src/test/java/com/inhabas/api/securityConfig/RoleHierarchyTest.java +++ b/resource-server/src/test/java/com/inhabas/api/securityConfig/RoleHierarchyTest.java @@ -1,19 +1,19 @@ package com.inhabas.api.securityConfig; -import com.inhabas.api.web.BoardController; +import com.inhabas.api.web.NormalBoardController; import com.inhabas.testAnnotataion.DefaultWebMvcTest; -@DefaultWebMvcTest(BoardController.class) +@DefaultWebMvcTest(NormalBoardController.class) public class RoleHierarchyTest { // @Autowired // private MockMvc mockMvc; // // @Autowired - // BoardController boardController; + // NormalBoardController boardController; // // @MockBean - // BoardService boardService; + // NormalBoardService boardService; // // @MockBean // MemberManageService memberService; diff --git a/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java index e27519df..89dad1df 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java @@ -10,7 +10,6 @@ import com.inhabas.api.domain.member.domain.entity.MemberTest; import com.inhabas.api.domain.normalBoard.dto.NormalBoardDetailDto; import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; -import com.inhabas.api.domain.normalBoard.dto.SaveNormalBoardDto; import com.inhabas.api.domain.normalBoard.usecase.NormalBoardService; import com.inhabas.testAnnotataion.NoSecureWebMvcTest; import org.junit.jupiter.api.DisplayName; @@ -18,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.MockMvc; import java.nio.charset.StandardCharsets; @@ -58,7 +58,7 @@ void getBoardCount_Success() throws Exception { // given BoardCountDto boardCountDto = new BoardCountDto("공지사항", 10); List dtoList = List.of(boardCountDto); - given(baseBoardRepository.countRowsGroupByMenuId()).willReturn(dtoList); + given(baseBoardRepository.countRowsGroupByMenuName(any())).willReturn(dtoList); // when String response = @@ -87,7 +87,7 @@ void getBoardList_Success() throws Exception { .isPinned(false) .build(); List dtoList = List.of(normalBoardDto); - given(normalBoardService.getPosts(any(),any(),any())).willReturn(dtoList); + given(normalBoardService.getPosts(any(),any())).willReturn(dtoList); // when String response = @@ -183,16 +183,19 @@ void getBoard_Not_Found() throws Exception { @Test void addBoard() throws Exception { // given - SaveNormalBoardDto saveNormalBoardDto = - new SaveNormalBoardDto("title", "content", null, false); given(normalBoardService.write(any(),any(),any())).willReturn(1L); + MockMultipartFile titlePart = + new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); // when String header = mvc.perform( - post("/board/notice") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(saveNormalBoardDto))) + multipart("/board/notice?pinOption=2") + .file(titlePart) + .file(contentPart) + .contentType(MediaType.MULTIPART_FORM_DATA)) .andExpect(status().isCreated()) .andReturn() .getResponse() @@ -206,14 +209,16 @@ void addBoard() throws Exception { @Test void addBoard_Invalid_Input() throws Exception { //given - SaveNormalBoardDto saveNormalBoardDto = - new SaveNormalBoardDto("meaningless", "meaningless", null, false); - + MockMultipartFile titlePart = + new MockMultipartFile("title", "".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); // when String response = - mvc.perform(post("/board/invalid") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(saveNormalBoardDto))) + mvc.perform(multipart("/board/notice?pinOption=2") + .file(titlePart) + .file(contentPart) + .contentType(MediaType.MULTIPART_FORM_DATA)) .andExpect(status().isBadRequest()) .andReturn() .getResponse() @@ -227,15 +232,18 @@ void addBoard_Invalid_Input() throws Exception { @Test void updateBoard() throws Exception { // given - SaveNormalBoardDto saveNormalBoardDto = - new SaveNormalBoardDto("title", "content", null, false); + MockMultipartFile titlePart = + new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); doNothing().when(normalBoardService).update(any(), any(), any()); // when then mvc.perform( - put("/board/notice/1") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(saveNormalBoardDto))) + multipart("/board/notice/1?pinOption=2") + .file(titlePart) + .file(contentPart) + .contentType(MediaType.MULTIPART_FORM_DATA)) .andExpect(status().isNoContent()); } @@ -243,15 +251,18 @@ void updateBoard() throws Exception { @Test void updateBoard_Invalid_Input() throws Exception { //given - SaveNormalBoardDto saveNormalBoardDto = - new SaveNormalBoardDto("title", "content", null, false); + MockMultipartFile titlePart = + new MockMultipartFile("title", "".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); doThrow(InvalidInputException.class).when(normalBoardService).update(any(), any(), any()); // when String response = - mvc.perform(put("/board/notice/1") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(saveNormalBoardDto))) + mvc.perform(multipart("/board/notice?pinOption=2") + .file(titlePart) + .file(contentPart) + .contentType(MediaType.MULTIPART_FORM_DATA)) .andExpect(status().isBadRequest()) .andReturn() .getResponse() @@ -265,15 +276,18 @@ void updateBoard_Invalid_Input() throws Exception { @Test void updateBoard_Not_Found() throws Exception { //given - SaveNormalBoardDto saveNormalBoardDto = - new SaveNormalBoardDto("title", "content", null, false); + MockMultipartFile titlePart = + new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); doThrow(NotFoundException.class).when(normalBoardService).update(any(), any(), any()); // when String response = - mvc.perform(put("/board/notice/1") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(saveNormalBoardDto))) + mvc.perform(multipart("/board/notice/1?pinOption=2") + .file(titlePart) + .file(contentPart) + .contentType(MediaType.MULTIPART_FORM_DATA)) .andExpect(status().isNotFound()) .andReturn() .getResponse() From ff6152f4896fc4fc612c5afb87d6de70b9940712 Mon Sep 17 00:00:00 2001 From: whitemark Date: Tue, 20 Feb 2024 10:18:29 +0900 Subject: [PATCH 17/19] =?UTF-8?q?[feature/#233]=20NormalBoard=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80,=20=ED=8C=8C=EC=9D=BC=20=EB=B6=84=EB=A6=AC?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../normalBoard/dto/NormalBoardDetailDto.java | 10 +++++++--- .../usecase/NormalBoardServiceImpl.java | 16 ++++++---------- .../inhabas/api/web/ClubActivityController.java | 2 +- .../inhabas/api/web/ClubHistoryController.java | 2 +- .../com/inhabas/api/web/CommentController.java | 2 +- .../inhabas/api/web/NormalBoardController.java | 4 ++-- .../dto/NormalBoardDetailDtoTest.java | 4 ++-- .../api/web/NormalBoardControllerTest.java | 3 ++- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java index ff82fc15..26466147 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java @@ -45,7 +45,9 @@ public class NormalBoardDetailDto { @Schema(type = "string", example = "2024-11-01T00:00:00") private LocalDateTime dateUpdated; - @NotNull private List files; + @NotNull private List images; + + @NotNull private List otherFiles; @NotNull private Boolean isPinned; @@ -60,7 +62,8 @@ public NormalBoardDetailDto( LocalDateTime datePinExpiration, LocalDateTime dateCreated, LocalDateTime dateUpdated, - List files, + List images, + List otherFiles, Boolean isPinned) { this.id = id; this.title = title; @@ -70,7 +73,8 @@ public NormalBoardDetailDto( this.datePinExpiration = datePinExpiration; this.dateCreated = dateCreated; this.dateUpdated = dateUpdated; - this.files = files; + this.images = images; + this.otherFiles = otherFiles; this.isPinned = isPinned; } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java index a2effa42..06ea67ce 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java @@ -8,7 +8,6 @@ import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; import com.inhabas.api.domain.board.exception.S3UploadFailedException; import com.inhabas.api.domain.file.domain.BoardFile; -import com.inhabas.api.domain.file.dto.FileDownloadDto; import com.inhabas.api.domain.file.usecase.S3Service; import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.repository.MenuRepository; @@ -18,6 +17,8 @@ import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; import com.inhabas.api.domain.normalBoard.dto.SaveNormalBoardDto; import com.inhabas.api.domain.normalBoard.repository.NormalBoardRepository; +import com.inhabas.api.global.util.ClassifiedFiles; +import com.inhabas.api.global.util.ClassifyFiles; import com.inhabas.api.global.util.FileUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -78,19 +79,13 @@ public List getPosts(NormalBoardType boardType, String search) { @Override public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Long boardId) { NormalBoard normalBoard; - List fileDownloadDtoList = null; if (boardType.equals(SUGGEST)) { normalBoard = normalBoardRepository.findByMemberIdAndTypeAndId(memberId, boardType, boardId).orElseThrow(NotFoundException::new); } else { normalBoard = normalBoardRepository.findByTypeAndId(boardType, boardId).orElseThrow(NotFoundException::new); } - if (!normalBoard.getFiles().isEmpty()) { - fileDownloadDtoList = - normalBoard.getFiles().stream() - .map(obj -> FileDownloadDto.builder().name(obj.getName()).url(obj.getUrl()).build()) - .collect(Collectors.toList()); - } + ClassifiedFiles classifiedFiles = ClassifyFiles.classifyFiles(normalBoard.getFiles()); return NormalBoardDetailDto.builder() .id(normalBoard.getId()) @@ -101,7 +96,8 @@ public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Lo .datePinExpiration(normalBoard.getDatePinExpiration()) .dateCreated(normalBoard.getDateCreated()) .dateUpdated(normalBoard.getDateUpdated()) - .files(fileDownloadDtoList) + .images(classifiedFiles.getImages()) + .otherFiles(classifiedFiles.getOtherFiles()) .isPinned(normalBoard.getPinned()) .build(); } @@ -143,7 +139,7 @@ public void delete(Long boardId) { private Long updateNormalBoardFiles( SaveNormalBoardDto saveNormalBoardDto, NormalBoardType boardType, NormalBoard normalBoard) { - final String DIR_NAME = "/" + boardType.getBoardType(); + final String DIR_NAME = boardType.getBoardType() + "/"; List updateFiles = new ArrayList<>(); List urlListForDelete = new ArrayList<>(); diff --git a/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java b/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java index 95c1521c..de4d71af 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java @@ -100,7 +100,7 @@ public ResponseEntity writeClubActivity( Long newClubActivityId = clubActivityService.writeClubActivity(memberId, saveClubActivityDto); URI location = ServletUriComponentsBuilder.fromCurrentRequest() - .path("/club/activity/{boardId}") + .path("/{boardId}") .buildAndExpand(newClubActivityId) .toUri(); diff --git a/resource-server/src/main/java/com/inhabas/api/web/ClubHistoryController.java b/resource-server/src/main/java/com/inhabas/api/web/ClubHistoryController.java index e0d10fe9..78773eb6 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/ClubHistoryController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/ClubHistoryController.java @@ -106,7 +106,7 @@ public ResponseEntity writeClubHistory( Long newClubHistoryId = clubHistoryService.writeClubHistory(memberId, saveClubHistoryDto); URI location = ServletUriComponentsBuilder.fromCurrentRequest() - .path("/club/history/{clubHistoryId}") + .path("/{clubHistoryId}") .buildAndExpand(newClubHistoryId) .toUri(); return ResponseEntity.created(location).build(); diff --git a/resource-server/src/main/java/com/inhabas/api/web/CommentController.java b/resource-server/src/main/java/com/inhabas/api/web/CommentController.java index 0fe95e83..114acbcf 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/CommentController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/CommentController.java @@ -116,7 +116,7 @@ public ResponseEntity createNewComment( commentService.create(commentSaveDto, menuId, boardId, memberId); URI location = - ServletUriComponentsBuilder.fromCurrentRequest() + ServletUriComponentsBuilder.fromCurrentContextPath() .path("/board/{menuId}/{boardId}/comments") .buildAndExpand(menuId, boardId) .toUri(); diff --git a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java index 5d63d29d..4800acbf 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java @@ -172,8 +172,8 @@ public ResponseEntity addBoard( URI location = ServletUriComponentsBuilder.fromCurrentRequest() .replaceQueryParam("pinOption") - .path("/board/{boardType}/{boardId}") - .buildAndExpand(boardType.getBoardType(), newNormalBoardId) + .path("/{boardId}") + .buildAndExpand(newNormalBoardId) .toUri(); return ResponseEntity.created(location).build(); diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java index 197f3a4c..1929946e 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java @@ -41,7 +41,7 @@ public void NormalBoardDetailDto_is_OK() { // given NormalBoardDetailDto normalBoardDetailDto = new NormalBoardDetailDto(1L, "title", "content", 1L, "writer", - LocalDateTime.now(), LocalDateTime.now(), LocalDateTime.now(), emptyList, false); + LocalDateTime.now(), LocalDateTime.now(), LocalDateTime.now(), emptyList, emptyList, false); // when Set> violations = validator.validate(normalBoardDetailDto); @@ -56,7 +56,7 @@ public void Title_is_null() { // given NormalBoardDetailDto normalBoardDetailDto = new NormalBoardDetailDto(1L, null, "content", 1L, "writer", - LocalDateTime.now(), LocalDateTime.now(), LocalDateTime.now(), emptyList, false); + LocalDateTime.now(), LocalDateTime.now(), LocalDateTime.now(), emptyList, emptyList, false); // when Set> violations = validator.validate(normalBoardDetailDto); diff --git a/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java index 89dad1df..9032a966 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java @@ -127,7 +127,8 @@ void getBoard() throws Exception { .title("title") .content("content") .writerName(writer.getName()) - .files(null) + .images(null) + .otherFiles(null) .dateCreated(LocalDateTime.now()) .dateUpdated(LocalDateTime.now()) .isPinned(false) From ad680d3b3bf6adf4dfdc327afdb8362b108f70f8 Mon Sep 17 00:00:00 2001 From: whitemark Date: Tue, 20 Feb 2024 10:46:26 +0900 Subject: [PATCH 18/19] [feature/#233] spotlessApply --- .../oauth2/member/domain/entity/Member.java | 2 +- .../com/inhabas/api/config/SwaggerConfig.java | 6 +- .../inhabas/api/config/WebSecurityConfig.java | 14 +- .../api/domain/board/domain/AlbumBoard.java | 2 +- .../api/domain/board/dto/BoardCountDto.java | 23 +- .../board/repository/BaseBoardRepository.java | 3 +- .../repository/BaseBoardRepositoryCustom.java | 6 +- .../repository/BaseBoardRepositoryImpl.java | 41 +- .../domain/contest/domain/ContestBoard.java | 4 +- .../usecase/MemberManageServiceImpl.java | 3 +- .../usecase/MemberProfileServiceImpl.java | 3 +- .../normalBoard/domain/NormalBoard.java | 29 +- .../normalBoard/domain/NormalBoardType.java | 38 +- .../domain/normalBoard/domain/PinOption.java | 21 +- .../normalBoard/dto/NormalBoardDetailDto.java | 133 ++-- .../normalBoard/dto/NormalBoardDto.java | 42 +- .../normalBoard/dto/SaveNormalBoardDto.java | 17 +- .../repository/NormalBoardRepository.java | 3 +- .../NormalBoardRepositoryCustom.java | 16 +- .../repository/NormalBoardRepositoryImpl.java | 136 ++-- .../usecase/NormalBoardService.java | 4 +- .../usecase/NormalBoardServiceImpl.java | 128 ++-- .../global/dto/PagedPinnedResponseDto.java | 27 +- .../api/web/ClubActivityController.java | 2 +- .../inhabas/api/web/ExceptionController.java | 1 - .../com/inhabas/api/web/MemberController.java | 21 +- .../api/web/NormalBoardController.java | 446 ++++++------ .../converter/NormalBoardTypeConverter.java | 47 +- .../valueObject/MenuGroupExampleTest.java | 1 + .../domain/NormalBoardExampleTest.java | 32 +- .../normalBoard/domain/NormalBoardTest.java | 14 +- .../dto/NormalBoardDetailDtoTest.java | 120 ++-- .../normalBoard/dto/NormalBoardDtoTest.java | 104 +-- .../dto/SaveNormalBoardDtoTest.java | 33 +- .../repository/NormalBoardRepositoryTest.java | 224 +++--- .../usecase/NormalBoardServiceImplTest.java | 251 +++---- .../api/web/NormalBoardControllerTest.java | 651 +++++++++--------- 37 files changed, 1355 insertions(+), 1293 deletions(-) diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java index b8c15a49..4c73b7ef 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java @@ -22,7 +22,7 @@ @Entity @Table( - name = "USER", + name = "USER", uniqueConstraints = { @UniqueConstraint( name = "UNIQUE_PROVIDER_UID", diff --git a/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java b/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java index d4883e92..b626b410 100644 --- a/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java +++ b/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java @@ -102,9 +102,9 @@ public GroupedOpenApi getIBASApi() { public GroupedOpenApi getBoardApi() { return GroupedOpenApi.builder() - .group("게시판 관련") - .pathsToMatch("/board/**", "/**/**/**/comment/**", "/**/**/**/comments") - .build(); + .group("게시판 관련") + .pathsToMatch("/board/**", "/**/**/**/comment/**", "/**/**/**/comments") + .build(); } @Bean diff --git a/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java b/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java index f2f01e87..83374417 100644 --- a/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java +++ b/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java @@ -59,9 +59,7 @@ public class WebSecurityConfig { private static final String[] AUTH_WHITELIST_CLUB_ACTIVITY = { "/club/activity/**", "/club/activities" }; - private static final String[] AUTH_WHITELIST_NORMAL_BOARD = { - "/board/count" - }; + private static final String[] AUTH_WHITELIST_NORMAL_BOARD = {"/board/count"}; @Order(1) @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true) @@ -85,11 +83,11 @@ public void configure(AuthenticationManagerBuilder auth) throws Exception { @Override public void configure(WebSecurity web) throws Exception { web.ignoring() - .antMatchers(HttpMethod.GET, AUTH_WHITELIST_POLICY) - .antMatchers(HttpMethod.GET, AUTH_WHITELIST_SIGNUP) - .antMatchers(HttpMethod.GET, AUTH_WHITELIST_CLUB) - .antMatchers(HttpMethod.GET, AUTH_WHITELIST_NORMAL_BOARD) - .antMatchers(AUTH_WHITELIST_SWAGGER) + .antMatchers(HttpMethod.GET, AUTH_WHITELIST_POLICY) + .antMatchers(HttpMethod.GET, AUTH_WHITELIST_SIGNUP) + .antMatchers(HttpMethod.GET, AUTH_WHITELIST_CLUB) + .antMatchers(HttpMethod.GET, AUTH_WHITELIST_NORMAL_BOARD) + .antMatchers(AUTH_WHITELIST_SWAGGER) .antMatchers(AUTH_WHITELIST_STATIC) .antMatchers(AUTH_WHITELIST_PATH); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java index 52421c01..18430333 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java @@ -21,7 +21,7 @@ @Table(name = "ALBUM_BOARD") @NoArgsConstructor(access = AccessLevel.PROTECTED) @EntityListeners(AuditingEntityListener.class) - @Inheritance(strategy = InheritanceType.JOINED) +@Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorValue("ALBUM") public class AlbumBoard extends BaseBoard { diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java index 1e7baf56..e40344c3 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java @@ -1,26 +1,23 @@ package com.inhabas.api.domain.board.dto; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.PositiveOrZero; + import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.PositiveOrZero; - @Getter @NoArgsConstructor public class BoardCountDto { - @NotNull - private String menuName; + @NotNull private String menuName; - @NotNull - @PositiveOrZero - private Integer count; + @NotNull @PositiveOrZero private Integer count; - @Builder - public BoardCountDto(String menuName, Integer count) { - this.menuName = menuName; - this.count = count; - } + @Builder + public BoardCountDto(String menuName, Integer count) { + this.menuName = menuName; + this.count = count; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java index e4685ac2..b6288f53 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java @@ -4,4 +4,5 @@ import com.inhabas.api.domain.board.domain.BaseBoard; -public interface BaseBoardRepository extends JpaRepository, BaseBoardRepositoryCustom {} +public interface BaseBoardRepository + extends JpaRepository, BaseBoardRepositoryCustom {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java index 8213eec6..daa552f2 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryCustom.java @@ -1,10 +1,10 @@ package com.inhabas.api.domain.board.repository; -import com.inhabas.api.domain.board.dto.BoardCountDto; - import java.util.List; +import com.inhabas.api.domain.board.dto.BoardCountDto; + public interface BaseBoardRepositoryCustom { - List countRowsGroupByMenuName(Integer menuGroupId); + List countRowsGroupByMenuName(Integer menuGroupId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java index 05310f61..8b8cb250 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepositoryImpl.java @@ -1,33 +1,32 @@ package com.inhabas.api.domain.board.repository; -import com.inhabas.api.domain.board.dto.BoardCountDto; -import com.querydsl.core.types.Projections; -import com.querydsl.jpa.impl.JPAQueryFactory; -import lombok.RequiredArgsConstructor; - import static com.inhabas.api.domain.board.domain.QBaseBoard.baseBoard; import static com.inhabas.api.domain.menu.domain.QMenu.*; import java.util.List; +import lombok.RequiredArgsConstructor; + +import com.inhabas.api.domain.board.dto.BoardCountDto; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; + @RequiredArgsConstructor public class BaseBoardRepositoryImpl implements BaseBoardRepositoryCustom { - private final JPAQueryFactory queryFactory; + private final JPAQueryFactory queryFactory; - @Override - public List countRowsGroupByMenuName(Integer menuGroupId) { - return queryFactory - .select( - Projections.constructor( - BoardCountDto.class, - menu.name.value, - baseBoard.id.count().intValue() - )) - .from(menu) - .leftJoin(baseBoard).on(menu.id.eq(baseBoard.menu.id)) - .where(menu.menuGroup.id.eq(menuGroupId)) - .groupBy(menu.name) - .fetch(); - } + @Override + public List countRowsGroupByMenuName(Integer menuGroupId) { + return queryFactory + .select( + Projections.constructor( + BoardCountDto.class, menu.name.value, baseBoard.id.count().intValue())) + .from(menu) + .leftJoin(baseBoard) + .on(menu.id.eq(baseBoard.menu.id)) + .where(menu.menuGroup.id.eq(menuGroupId)) + .groupBy(menu.name) + .fetch(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java index 975dd368..5c9cd840 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java @@ -7,7 +7,6 @@ import javax.persistence.Entity; import javax.persistence.Table; -import com.inhabas.api.domain.normalBoard.domain.NormalBoard; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -16,6 +15,7 @@ import com.inhabas.api.domain.board.domain.valueObject.Title; import com.inhabas.api.domain.contest.domain.valueObject.Association; import com.inhabas.api.domain.contest.domain.valueObject.Topic; +import com.inhabas.api.domain.normalBoard.domain.NormalBoard; @Entity @Table(name = "contest_board") @@ -52,7 +52,7 @@ public ContestBoard( LocalDate deadline) { this.title = new Title(title); -// this.content = new Content(contents); + // this.content = new Content(contents); this.association = new Association(association); this.topic = new Topic(topic); this.start = start; diff --git a/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberManageServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberManageServiceImpl.java index 06a46f85..c5c6ac36 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberManageServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberManageServiceImpl.java @@ -9,7 +9,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -217,7 +216,7 @@ private void validateMemberRolesToUpdate( private boolean hasRoleToChange(Authentication authentication, Role role) { return authentication.getAuthorities().stream() - .anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(ROLE_PREFIX + role)); + .anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(ROLE_PREFIX + role)); } private boolean checkAllMembersHaveAllowedRoles(List members, Set allowedRoles) { diff --git a/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberProfileServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberProfileServiceImpl.java index 84cd5581..5ada11cf 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberProfileServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/member/usecase/MemberProfileServiceImpl.java @@ -61,8 +61,7 @@ public void updateMyProfileDetail(Long memberId, ProfileDetailDto profileDetailD member.setPhone(profileDetailDto.getPhoneNumber()); if (profileDetailDto.getGrade() != null) member.getSchoolInformation().setGrade(profileDetailDto.getGrade()); - if (profileDetailDto.getType() != null) - member.setMemberType(profileDetailDto.getType()); + if (profileDetailDto.getType() != null) member.setMemberType(profileDetailDto.getType()); } @Override diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java index 7c0701e1..6bf9526f 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoard.java @@ -1,20 +1,23 @@ package com.inhabas.api.domain.normalBoard.domain; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.persistence.*; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + import com.inhabas.api.domain.board.domain.BaseBoard; import com.inhabas.api.domain.board.domain.valueObject.Content; import com.inhabas.api.domain.board.domain.valueObject.Title; import com.inhabas.api.domain.comment.domain.Comment; import com.inhabas.api.domain.file.domain.BoardFile; import com.inhabas.api.domain.menu.domain.Menu; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import javax.persistence.*; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; @Entity @Table(name = "NORMAL_BOARD") @@ -26,8 +29,7 @@ public class NormalBoard extends BaseBoard { @Embedded private Content content; - @Column - private Boolean isPinned = false; + @Column private Boolean isPinned = false; @Column(columnDefinition = "DATETIME(0)") private LocalDateTime datePinExpiration; @@ -37,8 +39,8 @@ public class NormalBoard extends BaseBoard { /* constructor */ - public NormalBoard(String title, Menu menu, String content, - Boolean isPinned, LocalDateTime datePinExpiration) { + public NormalBoard( + String title, Menu menu, String content, Boolean isPinned, LocalDateTime datePinExpiration) { super(title, menu); this.content = new Content(content); this.isPinned = isPinned; @@ -87,5 +89,4 @@ public void updatePinned(Boolean isPinned, LocalDateTime datePinExpiration) { this.isPinned = isPinned; this.datePinExpiration = datePinExpiration; } - } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardType.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardType.java index a1cd26e2..f11cc03b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardType.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardType.java @@ -1,26 +1,26 @@ - package com.inhabas.api.domain.normalBoard.domain; +package com.inhabas.api.domain.normalBoard.domain; public enum NormalBoardType { - NOTICE("notice", 4), - FREE("free", 5), - QUESTION("question", 6), - SUGGEST("suggest", 7), - STORAGE("storage", 8), - EXECUTIVE("executive", 9); + NOTICE("notice", 4), + FREE("free", 5), + QUESTION("question", 6), + SUGGEST("suggest", 7), + STORAGE("storage", 8), + EXECUTIVE("executive", 9); - private String boardType; - private int menuId; + private final String boardType; + private final int menuId; - NormalBoardType(String boardType, int menuId) { - this.boardType = boardType; - this.menuId = menuId; - } + NormalBoardType(String boardType, int menuId) { + this.boardType = boardType; + this.menuId = menuId; + } - public String getBoardType() { - return boardType; - } + public String getBoardType() { + return boardType; + } - public int getMenuId() { - return menuId; - } + public int getMenuId() { + return menuId; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/PinOption.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/PinOption.java index 5f825db3..312ed7f4 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/PinOption.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/domain/PinOption.java @@ -1,18 +1,17 @@ package com.inhabas.api.domain.normalBoard.domain; public enum PinOption { + DISABLED(0), + TEMPORARY(1), + PERMANENT(2); - DISABLED(0), - TEMPORARY(1), - PERMANENT(2); + private final Integer option; - private final Integer option; + PinOption(Integer option) { + this.option = option; + } - PinOption(Integer option) { - this.option = option; - } - - public Integer getOption() { - return option; - } + public Integer getOption() { + return option; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java index 26466147..618a221b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDto.java @@ -1,80 +1,77 @@ package com.inhabas.api.domain.normalBoard.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.file.dto.FileDownloadDto; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import java.time.LocalDateTime; +import java.util.List; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Positive; -import java.time.LocalDateTime; -import java.util.List; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.domain.file.dto.FileDownloadDto; +import io.swagger.v3.oas.annotations.media.Schema; @Getter @NoArgsConstructor public class NormalBoardDetailDto { - @NotNull - @Positive - private Long id; - - @NotBlank - private String title; - - @NotBlank private String content; - @NotNull - private Long writerId; - - @NotBlank private String writerName; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") - @Schema(type = "string", example = "2024-11-01T00:00:00") - private LocalDateTime datePinExpiration; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") - @Schema(type = "string", example = "2024-11-01T00:00:00") - private LocalDateTime dateCreated; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") - @Schema(type = "string", example = "2024-11-01T00:00:00") - private LocalDateTime dateUpdated; - - @NotNull private List images; - - @NotNull private List otherFiles; - - @NotNull - private Boolean isPinned; - - @Builder - public NormalBoardDetailDto( - Long id, - String title, - String content, - Long writerId, - String writerName, - LocalDateTime datePinExpiration, - LocalDateTime dateCreated, - LocalDateTime dateUpdated, - List images, - List otherFiles, - Boolean isPinned) { - this.id = id; - this.title = title; - this.content = content; - this.writerId = writerId; - this.writerName = writerName; - this.datePinExpiration = datePinExpiration; - this.dateCreated = dateCreated; - this.dateUpdated = dateUpdated; - this.images = images; - this.otherFiles = otherFiles; - this.isPinned = isPinned; - } + @NotNull @Positive private Long id; + + @NotBlank private String title; + + @NotBlank private String content; + @NotNull private Long writerId; + + @NotBlank private String writerName; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime datePinExpiration; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateCreated; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateUpdated; + + @NotNull private List images; + + @NotNull private List otherFiles; + + @NotNull private Boolean isPinned; + + @Builder + public NormalBoardDetailDto( + Long id, + String title, + String content, + Long writerId, + String writerName, + LocalDateTime datePinExpiration, + LocalDateTime dateCreated, + LocalDateTime dateUpdated, + List images, + List otherFiles, + Boolean isPinned) { + this.id = id; + this.title = title; + this.content = content; + this.writerId = writerId; + this.writerName = writerName; + this.datePinExpiration = datePinExpiration; + this.dateCreated = dateCreated; + this.dateUpdated = dateUpdated; + this.images = images; + this.otherFiles = otherFiles; + this.isPinned = isPinned; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java index f1e6e808..a4efe260 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDto.java @@ -1,32 +1,29 @@ package com.inhabas.api.domain.normalBoard.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import java.time.LocalDateTime; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Positive; -import java.time.LocalDateTime; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; @Getter @NoArgsConstructor public class NormalBoardDto { - @NotNull - @Positive - private Long id; + @NotNull @Positive private Long id; - @NotBlank - private String title; + @NotBlank private String title; - @NotNull - private Long writerId; + @NotNull private Long writerId; - @NotBlank - private String writerName; + @NotBlank private String writerName; @NotNull @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") @@ -43,12 +40,18 @@ public class NormalBoardDto { @Schema(type = "string", example = "2024-11-01T00:00:00") private LocalDateTime dateUpdated; - @NotNull - private Boolean isPinned; + @NotNull private Boolean isPinned; @Builder - public NormalBoardDto(Long id, String title, Long writerId, String writerName, LocalDateTime datePinExpiration, - LocalDateTime dateCreated, LocalDateTime dateUpdated, Boolean isPinned) { + public NormalBoardDto( + Long id, + String title, + Long writerId, + String writerName, + LocalDateTime datePinExpiration, + LocalDateTime dateCreated, + LocalDateTime dateUpdated, + Boolean isPinned) { this.id = id; this.title = title; this.writerId = writerId; @@ -58,5 +61,4 @@ public NormalBoardDto(Long id, String title, Long writerId, String writerName, L this.dateUpdated = dateUpdated; this.isPinned = isPinned; } - } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java index 58667bae..fd3ff50d 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDto.java @@ -1,26 +1,27 @@ package com.inhabas.api.domain.normalBoard.dto; +import java.util.List; + +import javax.validation.constraints.NotBlank; + import lombok.Getter; import lombok.NoArgsConstructor; -import org.springframework.web.multipart.MultipartFile; -import javax.validation.constraints.NotBlank; -import java.util.List; +import org.springframework.web.multipart.MultipartFile; @Getter @NoArgsConstructor public class SaveNormalBoardDto { - @NotBlank - private String title; + @NotBlank private String title; - @NotBlank - private String content; + @NotBlank private String content; private List files; private Integer pinOption; - public SaveNormalBoardDto(String title, String content, List files, Integer pinOption) { + public SaveNormalBoardDto( + String title, String content, List files, Integer pinOption) { this.title = title; this.content = content; this.files = files; diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepository.java index 676e8f73..fe9b073a 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepository.java @@ -1,7 +1,8 @@ package com.inhabas.api.domain.normalBoard.repository; -import com.inhabas.api.domain.normalBoard.domain.NormalBoard; import org.springframework.data.jpa.repository.JpaRepository; +import com.inhabas.api.domain.normalBoard.domain.NormalBoard; + public interface NormalBoardRepository extends JpaRepository, NormalBoardRepositoryCustom {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java index 2e5f93a2..75f7c569 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryCustom.java @@ -1,17 +1,23 @@ package com.inhabas.api.domain.normalBoard.repository; +import java.util.List; +import java.util.Optional; + import com.inhabas.api.domain.normalBoard.domain.NormalBoard; import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; -import java.util.List; -import java.util.Optional; - public interface NormalBoardRepositoryCustom { List findAllByTypeAndIsPinned(NormalBoardType boardType); - List findAllByMemberIdAndTypeAndSearch(Long memberId, NormalBoardType boardType, String search); + + List findAllByMemberIdAndTypeAndSearch( + Long memberId, NormalBoardType boardType, String search); + List findAllByTypeAndSearch(NormalBoardType boardType, String search); - Optional findByMemberIdAndTypeAndId(Long memberId, NormalBoardType boardType, Long boardId); + + Optional findByMemberIdAndTypeAndId( + Long memberId, NormalBoardType boardType, Long boardId); + Optional findByTypeAndId(NormalBoardType boardType, Long boardId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java index 109c7a03..58cab1bf 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryImpl.java @@ -1,19 +1,19 @@ package com.inhabas.api.domain.normalBoard.repository; -import com.inhabas.api.domain.normalBoard.domain.NormalBoard; -import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; -import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; -import com.querydsl.core.types.Projections; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.jpa.impl.JPAQueryFactory; -import lombok.RequiredArgsConstructor; +import static com.inhabas.api.domain.normalBoard.domain.QNormalBoard.normalBoard; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; -import static com.inhabas.api.domain.normalBoard.domain.QNormalBoard.normalBoard; +import lombok.RequiredArgsConstructor; +import com.inhabas.api.domain.normalBoard.domain.NormalBoard; +import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; +import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; @RequiredArgsConstructor public class NormalBoardRepositoryImpl implements NormalBoardRepositoryCustom { @@ -23,73 +23,78 @@ public class NormalBoardRepositoryImpl implements NormalBoardRepositoryCustom { @Override public List findAllByTypeAndIsPinned(NormalBoardType boardType) { return queryFactory - .select( - Projections.constructor( - NormalBoardDto.class, - normalBoard.id, - normalBoard.title.value, - normalBoard.writer.id, - normalBoard.writer.name.value, - normalBoard.datePinExpiration, - normalBoard.dateCreated, - normalBoard.dateUpdated, - normalBoard.isPinned)) - .from(normalBoard) - .where(eqNormalBoardType(boardType) - .and(normalBoard.isPinned.isTrue()) - .and(normalBoard.datePinExpiration.after(LocalDateTime.now()))) - .orderBy(normalBoard.dateCreated.desc()) - .fetch(); + .select( + Projections.constructor( + NormalBoardDto.class, + normalBoard.id, + normalBoard.title.value, + normalBoard.writer.id, + normalBoard.writer.name.value, + normalBoard.datePinExpiration, + normalBoard.dateCreated, + normalBoard.dateUpdated, + normalBoard.isPinned)) + .from(normalBoard) + .where( + eqNormalBoardType(boardType) + .and(normalBoard.isPinned.isTrue()) + .and(normalBoard.datePinExpiration.after(LocalDateTime.now()))) + .orderBy(normalBoard.dateCreated.desc()) + .fetch(); } @Override - public List findAllByMemberIdAndTypeAndSearch(Long memberId, NormalBoardType boardType, String search) { + public List findAllByMemberIdAndTypeAndSearch( + Long memberId, NormalBoardType boardType, String search) { return queryFactory - .select( - Projections.constructor( - NormalBoardDto.class, - normalBoard.id, - normalBoard.title.value, - normalBoard.writer.id, - normalBoard.writer.name.value, - normalBoard.datePinExpiration, - normalBoard.dateCreated, - normalBoard.dateUpdated, - normalBoard.isPinned)) - .from(normalBoard) - .where(eqMemberId(memberId) - .and(eqNormalBoardType(boardType)) - .and(likeTitle(search).or(likeContent(search)))) - .orderBy(normalBoard.dateCreated.desc()) - .fetch(); + .select( + Projections.constructor( + NormalBoardDto.class, + normalBoard.id, + normalBoard.title.value, + normalBoard.writer.id, + normalBoard.writer.name.value, + normalBoard.datePinExpiration, + normalBoard.dateCreated, + normalBoard.dateUpdated, + normalBoard.isPinned)) + .from(normalBoard) + .where( + eqMemberId(memberId) + .and(eqNormalBoardType(boardType)) + .and(likeTitle(search).or(likeContent(search)))) + .orderBy(normalBoard.dateCreated.desc()) + .fetch(); } @Override public List findAllByTypeAndSearch(NormalBoardType boardType, String search) { return queryFactory - .select( - Projections.constructor( - NormalBoardDto.class, - normalBoard.id, - normalBoard.title.value, - normalBoard.writer.id, - normalBoard.writer.name.value, - normalBoard.datePinExpiration, - normalBoard.dateCreated, - normalBoard.dateUpdated, - normalBoard.isPinned)) - .from(normalBoard) - .where(eqNormalBoardType(boardType) - .and(likeTitle(search).or(likeContent(search)))) - .orderBy(normalBoard.dateCreated.desc()) - .fetch(); + .select( + Projections.constructor( + NormalBoardDto.class, + normalBoard.id, + normalBoard.title.value, + normalBoard.writer.id, + normalBoard.writer.name.value, + normalBoard.datePinExpiration, + normalBoard.dateCreated, + normalBoard.dateUpdated, + normalBoard.isPinned)) + .from(normalBoard) + .where(eqNormalBoardType(boardType).and(likeTitle(search).or(likeContent(search)))) + .orderBy(normalBoard.dateCreated.desc()) + .fetch(); } @Override - public Optional findByMemberIdAndTypeAndId(Long memberId, NormalBoardType boardType, Long boardId) { - return Optional.ofNullable(queryFactory + public Optional findByMemberIdAndTypeAndId( + Long memberId, NormalBoardType boardType, Long boardId) { + return Optional.ofNullable( + queryFactory .selectFrom(normalBoard) - .where(eqMemberId(memberId) + .where( + eqMemberId(memberId) .and(eqNormalBoardType(boardType)) .and(normalBoard.id.eq(boardId))) .orderBy(normalBoard.dateCreated.desc()) @@ -98,10 +103,10 @@ public Optional findByMemberIdAndTypeAndId(Long memberId, NormalBoa @Override public Optional findByTypeAndId(NormalBoardType boardType, Long boardId) { - return Optional.ofNullable(queryFactory + return Optional.ofNullable( + queryFactory .selectFrom(normalBoard) - .where((eqNormalBoardType(boardType)) - .and(normalBoard.id.eq(boardId))) + .where((eqNormalBoardType(boardType)).and(normalBoard.id.eq(boardId))) .orderBy(normalBoard.dateCreated.desc()) .fetchOne()); } @@ -121,5 +126,4 @@ private BooleanExpression likeTitle(String search) { private BooleanExpression likeContent(String search) { return normalBoard.content.value.like("%" + search + "%"); } - } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java index eddd1ce4..0f5acd35 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardService.java @@ -1,12 +1,12 @@ package com.inhabas.api.domain.normalBoard.usecase; +import java.util.List; + import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; import com.inhabas.api.domain.normalBoard.dto.NormalBoardDetailDto; import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; import com.inhabas.api.domain.normalBoard.dto.SaveNormalBoardDto; -import java.util.List; - public interface NormalBoardService { List getPinned(NormalBoardType boardType); diff --git a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java index 06ea67ce..b0c21d02 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImpl.java @@ -1,5 +1,22 @@ package com.inhabas.api.domain.normalBoard.usecase; +import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.*; +import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.EXECUTIVE; +import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.NOTICE; +import static com.inhabas.api.domain.normalBoard.domain.PinOption.*; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import javax.transaction.Transactional; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + import com.inhabas.api.auth.domain.error.authException.InvalidAuthorityException; import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; import com.inhabas.api.auth.domain.error.businessException.NotFoundException; @@ -20,20 +37,6 @@ import com.inhabas.api.global.util.ClassifiedFiles; import com.inhabas.api.global.util.ClassifyFiles; import com.inhabas.api.global.util.FileUtil; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Service; - -import javax.transaction.Transactional; -import java.time.LocalDateTime; -import java.util.*; -import java.util.stream.Collectors; - -import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.*; -import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.EXECUTIVE; -import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.NOTICE; -import static com.inhabas.api.domain.normalBoard.domain.PinOption.*; @Service @Slf4j @@ -46,10 +49,9 @@ public class NormalBoardServiceImpl implements NormalBoardService { private final MemberRepository memberRepository; private final S3Service s3Service; - private static final Set hasPinnedBoardTypeSet = new HashSet<>( - Arrays.asList(NOTICE, EXECUTIVE)); - private static final LocalDateTime PERMANENT_DATE = - LocalDateTime.of(2200, 1, 1, 0, 0, 0); + private static final Set hasPinnedBoardTypeSet = + new HashSet<>(Arrays.asList(NOTICE, EXECUTIVE)); + private static final LocalDateTime PERMANENT_DATE = LocalDateTime.of(2200, 1, 1, 0, 0, 0); private static final Integer TEMPORARY_DAYS = 14; @Override @@ -69,7 +71,8 @@ public List getPosts(NormalBoardType boardType, String search) { throw new InvalidAuthorityException(); } Long memberId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - normalBoardList.addAll(normalBoardRepository.findAllByMemberIdAndTypeAndSearch(memberId, boardType, search)); + normalBoardList.addAll( + normalBoardRepository.findAllByMemberIdAndTypeAndSearch(memberId, boardType, search)); } else { normalBoardList.addAll(normalBoardRepository.findAllByTypeAndSearch(boardType, search)); } @@ -80,50 +83,53 @@ public List getPosts(NormalBoardType boardType, String search) { public NormalBoardDetailDto getPost(Long memberId, NormalBoardType boardType, Long boardId) { NormalBoard normalBoard; if (boardType.equals(SUGGEST)) { - normalBoard = normalBoardRepository.findByMemberIdAndTypeAndId(memberId, boardType, boardId).orElseThrow(NotFoundException::new); + normalBoard = + normalBoardRepository + .findByMemberIdAndTypeAndId(memberId, boardType, boardId) + .orElseThrow(NotFoundException::new); } else { - normalBoard = normalBoardRepository.findByTypeAndId(boardType, boardId).orElseThrow(NotFoundException::new); + normalBoard = + normalBoardRepository + .findByTypeAndId(boardType, boardId) + .orElseThrow(NotFoundException::new); } ClassifiedFiles classifiedFiles = ClassifyFiles.classifyFiles(normalBoard.getFiles()); return NormalBoardDetailDto.builder() - .id(normalBoard.getId()) - .title(normalBoard.getTitle()) - .content(normalBoard.getContent()) - .writerId(normalBoard.getWriter().getId()) - .writerName(normalBoard.getWriter().getName()) - .datePinExpiration(normalBoard.getDatePinExpiration()) - .dateCreated(normalBoard.getDateCreated()) - .dateUpdated(normalBoard.getDateUpdated()) - .images(classifiedFiles.getImages()) - .otherFiles(classifiedFiles.getOtherFiles()) - .isPinned(normalBoard.getPinned()) - .build(); + .id(normalBoard.getId()) + .title(normalBoard.getTitle()) + .content(normalBoard.getContent()) + .writerId(normalBoard.getWriter().getId()) + .writerName(normalBoard.getWriter().getName()) + .datePinExpiration(normalBoard.getDatePinExpiration()) + .dateCreated(normalBoard.getDateCreated()) + .dateUpdated(normalBoard.getDateUpdated()) + .images(classifiedFiles.getImages()) + .otherFiles(classifiedFiles.getOtherFiles()) + .isPinned(normalBoard.getPinned()) + .build(); } @Override - public Long write(Long memberId, NormalBoardType boardType, SaveNormalBoardDto saveNormalBoardDto) { + public Long write( + Long memberId, NormalBoardType boardType, SaveNormalBoardDto saveNormalBoardDto) { Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); Menu menu = menuRepository.findById(boardType.getMenuId()).orElseThrow(NotFoundException::new); - NormalBoard normalBoard = new NormalBoard( - saveNormalBoardDto.getTitle(), - menu, - saveNormalBoardDto.getContent(), - false, - null - ).writtenBy(writer, NormalBoard.class); + NormalBoard normalBoard = + new NormalBoard( + saveNormalBoardDto.getTitle(), menu, saveNormalBoardDto.getContent(), false, null) + .writtenBy(writer, NormalBoard.class); updateNormalBoardPinned(saveNormalBoardDto, boardType, normalBoard); return updateNormalBoardFiles(saveNormalBoardDto, boardType, normalBoard); - } - @Override - public void update(Long boardId, NormalBoardType boardType, SaveNormalBoardDto saveNormalBoardDto) { + public void update( + Long boardId, NormalBoardType boardType, SaveNormalBoardDto saveNormalBoardDto) { NormalBoard normalBoard = normalBoardRepository.findById(boardId).orElseThrow(NotFoundException::new); @@ -136,9 +142,8 @@ public void delete(Long boardId) { normalBoardRepository.deleteById(boardId); } - private Long updateNormalBoardFiles( - SaveNormalBoardDto saveNormalBoardDto, NormalBoardType boardType, NormalBoard normalBoard) { + SaveNormalBoardDto saveNormalBoardDto, NormalBoardType boardType, NormalBoard normalBoard) { final String DIR_NAME = boardType.getBoardType() + "/"; List updateFiles = new ArrayList<>(); List urlListForDelete = new ArrayList<>(); @@ -147,19 +152,19 @@ private Long updateNormalBoardFiles( normalBoard.updateText(saveNormalBoardDto.getTitle(), saveNormalBoardDto.getContent()); try { updateFiles = - saveNormalBoardDto.getFiles().stream() - .map( - file -> { - String path = FileUtil.generateFileName(file, DIR_NAME); - String url = s3Service.uploadS3File(file, path); - urlListForDelete.add(url); - return BoardFile.builder() - .name(file.getOriginalFilename()) - .url(url) - .board(normalBoard) - .build(); - }) - .collect(Collectors.toList()); + saveNormalBoardDto.getFiles().stream() + .map( + file -> { + String path = FileUtil.generateFileName(file, DIR_NAME); + String url = s3Service.uploadS3File(file, path); + urlListForDelete.add(url); + return BoardFile.builder() + .name(file.getOriginalFilename()) + .url(url) + .board(normalBoard) + .build(); + }) + .collect(Collectors.toList()); } catch (RuntimeException e) { for (String url : urlListForDelete) { @@ -173,7 +178,8 @@ private Long updateNormalBoardFiles( return normalBoardRepository.save(normalBoard).getId(); } - private void updateNormalBoardPinned(SaveNormalBoardDto saveNormalBoardDto, NormalBoardType boardType, NormalBoard normalBoard) { + private void updateNormalBoardPinned( + SaveNormalBoardDto saveNormalBoardDto, NormalBoardType boardType, NormalBoard normalBoard) { boolean isPinned = false; LocalDateTime datePinExpiration = null; @@ -190,11 +196,9 @@ private void updateNormalBoardPinned(SaveNormalBoardDto saveNormalBoardDto, Norm } normalBoard.updatePinned(isPinned, datePinExpiration); - } private boolean hasPinned(NormalBoardType boardType) { return hasPinnedBoardTypeSet.contains(boardType); } - } diff --git a/resource-server/src/main/java/com/inhabas/api/global/dto/PagedPinnedResponseDto.java b/resource-server/src/main/java/com/inhabas/api/global/dto/PagedPinnedResponseDto.java index 24eb2ed9..30851468 100644 --- a/resource-server/src/main/java/com/inhabas/api/global/dto/PagedPinnedResponseDto.java +++ b/resource-server/src/main/java/com/inhabas/api/global/dto/PagedPinnedResponseDto.java @@ -1,28 +1,27 @@ package com.inhabas.api.global.dto; +import java.util.List; + +import javax.validation.constraints.NotNull; + import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; -import java.util.List; - @Data @NoArgsConstructor public class PagedPinnedResponseDto { - @NotNull - private PageInfoDto pageInfo; + @NotNull private PageInfoDto pageInfo; - private List pinnedData; + private List pinnedData; - @NotNull private List data; + @NotNull private List data; - @Builder - public PagedPinnedResponseDto(PageInfoDto pageInfo, List pinnedData, List data) { - this.pageInfo = pageInfo; - this.pinnedData = pinnedData; - this.data = data; - } + @Builder + public PagedPinnedResponseDto(PageInfoDto pageInfo, List pinnedData, List data) { + this.pageInfo = pageInfo; + this.pinnedData = pinnedData; + this.data = data; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java b/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java index de4d71af..971404b7 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java @@ -21,7 +21,7 @@ import com.inhabas.api.domain.club.dto.SaveClubActivityDto; import com.inhabas.api.domain.club.usecase.ClubActivityService; import com.inhabas.api.global.dto.PageInfoDto; - import com.inhabas.api.global.dto.PagedResponseDto; +import com.inhabas.api.global.dto.PagedResponseDto; import com.inhabas.api.global.util.PageUtil; import com.inhabas.api.web.argumentResolver.Authenticated; import io.swagger.v3.oas.annotations.Operation; diff --git a/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java b/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java index 2da0acab..423b90e4 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java @@ -122,5 +122,4 @@ protected ResponseEntity processRequestPartError(MissingServletRequestPa final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); return new ResponseEntity<>(response, BAD_REQUEST); } - } diff --git a/resource-server/src/main/java/com/inhabas/api/web/MemberController.java b/resource-server/src/main/java/com/inhabas/api/web/MemberController.java index 2b6d3b29..53dc29b3 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/MemberController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/MemberController.java @@ -46,17 +46,16 @@ public class MemberController { content = {@Content(schema = @Schema(implementation = PagedResponseDto.class))}), }) @GetMapping("/members/unapproved") - public ResponseEntity> - getUnapprovedMembers( - @Parameter(description = "페이지", example = "0") - @RequestParam(name = "page", defaultValue = "0") - int page, - @Parameter(description = "페이지당 개수", example = "10") - @RequestParam(name = "size", defaultValue = "10") - int size, - @Parameter(description = "검색어 (학번 or 이름)", example = "홍길동") - @RequestParam(name = "search", defaultValue = "") - String search) { + public ResponseEntity> getUnapprovedMembers( + @Parameter(description = "페이지", example = "0") + @RequestParam(name = "page", defaultValue = "0") + int page, + @Parameter(description = "페이지당 개수", example = "10") + @RequestParam(name = "size", defaultValue = "10") + int size, + @Parameter(description = "검색어 (학번 or 이름)", example = "홍길동") + @RequestParam(name = "search", defaultValue = "") + String search) { Pageable pageable = PageRequest.of(page, size); List allDtos = diff --git a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java index 4800acbf..f81671a6 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/NormalBoardController.java @@ -1,5 +1,21 @@ package com.inhabas.api.web; +import java.net.URI; +import java.util.List; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + import com.inhabas.api.auth.domain.error.ErrorResponse; import com.inhabas.api.domain.board.dto.BoardCountDto; import com.inhabas.api.domain.board.repository.BaseBoardRepository; @@ -22,20 +38,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; - -import java.net.URI; -import java.util.List; @Slf4j @Tag(name = "게시글 관리") @@ -43,213 +45,215 @@ @RequiredArgsConstructor public class NormalBoardController { - private final NormalBoardService normalBoardService; - private final BaseBoardRepository baseBoardRepository; - - @Operation(summary = "게시판 종류 당 글 개수 조회") - @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - content = {@Content(schema = @Schema(implementation = BoardCountDto.class))}), - }) - @GetMapping("/board/count") - @SecurityRequirements(value = {}) - public ResponseEntity> getBoardCount() { - return ResponseEntity.ok(baseBoardRepository.countRowsGroupByMenuName(2)); - } - - @Operation(summary = "게시글 목록 조회") - @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - content = {@Content(schema = @Schema(implementation = PagedResponseDto.class))}), - @ApiResponse( - responseCode = "400 ", - description = "입력값이 없거나, 타입이 유효하지 않습니다.", - content = - @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = - @ExampleObject( - value = - "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), - }) - @GetMapping("/board/{boardType}") - @PreAuthorize( - "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD_LIST)" - ) - public ResponseEntity> getBoardList( - @Parameter(description = "페이지", example = "0") - @RequestParam(name = "page", defaultValue = "0") - int page, - @Parameter(description = "페이지당 개수", example = "10") - @RequestParam(name = "size", defaultValue = "10") - int size, - @Parameter(description = "검색어 (작성자 이름 or 제목 or 내용)", example = "") - @RequestParam(name = "search", defaultValue = "") - String search, - @PathVariable NormalBoardType boardType) { - - Pageable pageable = PageRequest.of(page, size); - List allDtoList = normalBoardService.getPosts(boardType, search); - List pinnedDtoList = normalBoardService.getPinned(boardType); - List pagedDtoList = PageUtil.getPagedDtoList(pageable, allDtoList); - - PageImpl normalBoardDtoPage = - new PageImpl<>(pagedDtoList, pageable, allDtoList.size()); - PageInfoDto pageInfoDto = new PageInfoDto(normalBoardDtoPage); - - return ResponseEntity.ok(new PagedPinnedResponseDto<>(pageInfoDto, pinnedDtoList, pagedDtoList)); - } - - @Operation(summary = "게시글 단일 조회") - @GetMapping("/board/{boardType}/{boardId}") - @PreAuthorize( - "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD)" - ) - @ApiResponses({ - @ApiResponse( - responseCode = "200", - content = {@Content(schema = @Schema(implementation = NormalBoardDto.class))}), - @ApiResponse( - responseCode = "400 ", - description = "입력값이 없거나, 타입이 유효하지 않습니다.", - content = - @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = - @ExampleObject( - value = - "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), - @ApiResponse( - responseCode = "404", - description = "데이터가 존재하지 않습니다.", - content = - @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = - @ExampleObject( - value = - "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) - }) - public ResponseEntity getBoard( - @PathVariable Long boardId, - @PathVariable NormalBoardType boardType, - @Authenticated Long memberId) { - - return ResponseEntity.ok(normalBoardService.getPost(memberId, boardType, boardId)); - } - - @Operation(summary = "게시글 추가") - @PostMapping(path = "/board/{boardType}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @PreAuthorize( - "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).CREATE_BOARD)" - ) - @ApiResponses({ - @ApiResponse(responseCode = "201", description = "'Location' 헤더에 생성된 리소스의 URI 가 포함됩니다."), - @ApiResponse( - responseCode = "400 ", - description = "입력값이 없거나, 타입이 유효하지 않습니다.", - content = - @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = - @ExampleObject( - value = - "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), - }) - public ResponseEntity addBoard( - @Authenticated Long memberId, - @PathVariable NormalBoardType boardType, - @RequestPart("title") String title, - @RequestPart("content") String content, - @RequestPart(value = "files", required = false) List files, - @RequestParam(value = "pinOption", required = false) Integer pinOption) { - SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto(title, content, files, pinOption); - Long newNormalBoardId = normalBoardService.write(memberId, boardType, saveNormalBoardDto); - URI location = - ServletUriComponentsBuilder.fromCurrentRequest() - .replaceQueryParam("pinOption") - .path("/{boardId}") - .buildAndExpand(newNormalBoardId) - .toUri(); - - return ResponseEntity.created(location).build(); - } - - @Operation(summary = "게시글 수정") - @PostMapping(value = "/board/{boardType}/{boardId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @ApiResponses({ - @ApiResponse(responseCode = "200"), - @ApiResponse( - responseCode = "400 ", - description = "입력값이 없거나, 타입이 유효하지 않습니다.", - content = - @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = - @ExampleObject( - value = - "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), - @ApiResponse( - responseCode = "404", - description = "데이터가 존재하지 않습니다.", - content = - @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = - @ExampleObject( - value = - "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + private final NormalBoardService normalBoardService; + private final BaseBoardRepository baseBoardRepository; + + @Operation(summary = "게시판 종류 당 글 개수 조회") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = BoardCountDto.class))}), }) - @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") - public ResponseEntity updateBoard( - @Authenticated Long memberId, - @PathVariable NormalBoardType boardType, - @PathVariable Long boardId, - @RequestPart("title") String title, - @RequestPart("content") String content, - @RequestPart(value = "files", required = false) List files, - @RequestParam(value = "pinOption", required = false) Integer pinOption) { - SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto(title, content, files, pinOption); - normalBoardService.update(boardId, boardType, saveNormalBoardDto); - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "게시글 삭제") - @DeleteMapping("/board/{boardType}/{boardId}") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse( - responseCode = "400 ", - description = "입력값이 없거나, 타입이 유효하지 않습니다.", - content = - @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = - @ExampleObject( - value = - "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), - @ApiResponse( - responseCode = "404", - description = "데이터가 존재하지 않습니다.", - content = - @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = - @ExampleObject( - value = - "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + @GetMapping("/board/count") + @SecurityRequirements(value = {}) + public ResponseEntity> getBoardCount() { + return ResponseEntity.ok(baseBoardRepository.countRowsGroupByMenuName(2)); + } + + @Operation(summary = "게시글 목록 조회") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = PagedResponseDto.class))}), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), }) - @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") - public ResponseEntity deleteBoard( - @Authenticated Long memberId, - @PathVariable NormalBoardType boardType, - @PathVariable Long boardId) { - - normalBoardService.delete(boardId); - return ResponseEntity.noContent().build(); - } + @GetMapping("/board/{boardType}") + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD_LIST)") + public ResponseEntity> getBoardList( + @Parameter(description = "페이지", example = "0") + @RequestParam(name = "page", defaultValue = "0") + int page, + @Parameter(description = "페이지당 개수", example = "10") + @RequestParam(name = "size", defaultValue = "10") + int size, + @Parameter(description = "검색어 (작성자 이름 or 제목 or 내용)", example = "") + @RequestParam(name = "search", defaultValue = "") + String search, + @PathVariable NormalBoardType boardType) { + + Pageable pageable = PageRequest.of(page, size); + List allDtoList = normalBoardService.getPosts(boardType, search); + List pinnedDtoList = normalBoardService.getPinned(boardType); + List pagedDtoList = PageUtil.getPagedDtoList(pageable, allDtoList); + + PageImpl normalBoardDtoPage = + new PageImpl<>(pagedDtoList, pageable, allDtoList.size()); + PageInfoDto pageInfoDto = new PageInfoDto(normalBoardDtoPage); + + return ResponseEntity.ok( + new PagedPinnedResponseDto<>(pageInfoDto, pinnedDtoList, pagedDtoList)); + } + + @Operation(summary = "게시글 단일 조회") + @GetMapping("/board/{boardType}/{boardId}") + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD)") + @ApiResponses({ + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = NormalBoardDto.class))}), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + public ResponseEntity getBoard( + @PathVariable Long boardId, + @PathVariable NormalBoardType boardType, + @Authenticated Long memberId) { + + return ResponseEntity.ok(normalBoardService.getPost(memberId, boardType, boardId)); + } + + @Operation(summary = "게시글 추가") + @PostMapping(path = "/board/{boardType}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(#boardType.menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).CREATE_BOARD)") + @ApiResponses({ + @ApiResponse(responseCode = "201", description = "'Location' 헤더에 생성된 리소스의 URI 가 포함됩니다."), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + }) + public ResponseEntity addBoard( + @Authenticated Long memberId, + @PathVariable NormalBoardType boardType, + @RequestPart("title") String title, + @RequestPart("content") String content, + @RequestPart(value = "files", required = false) List files, + @RequestParam(value = "pinOption", required = false) Integer pinOption) { + SaveNormalBoardDto saveNormalBoardDto = + new SaveNormalBoardDto(title, content, files, pinOption); + Long newNormalBoardId = normalBoardService.write(memberId, boardType, saveNormalBoardDto); + URI location = + ServletUriComponentsBuilder.fromCurrentRequest() + .replaceQueryParam("pinOption") + .path("/{boardId}") + .buildAndExpand(newNormalBoardId) + .toUri(); + + return ResponseEntity.created(location).build(); + } + + @Operation(summary = "게시글 수정") + @PostMapping( + value = "/board/{boardType}/{boardId}", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @ApiResponses({ + @ApiResponse(responseCode = "200"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") + public ResponseEntity updateBoard( + @Authenticated Long memberId, + @PathVariable NormalBoardType boardType, + @PathVariable Long boardId, + @RequestPart("title") String title, + @RequestPart("content") String content, + @RequestPart(value = "files", required = false) List files, + @RequestParam(value = "pinOption", required = false) Integer pinOption) { + SaveNormalBoardDto saveNormalBoardDto = + new SaveNormalBoardDto(title, content, files, pinOption); + normalBoardService.update(boardId, boardType, saveNormalBoardDto); + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "게시글 삭제") + @DeleteMapping("/board/{boardType}/{boardId}") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") + public ResponseEntity deleteBoard( + @Authenticated Long memberId, + @PathVariable NormalBoardType boardType, + @PathVariable Long boardId) { + + normalBoardService.delete(boardId); + return ResponseEntity.noContent().build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/converter/NormalBoardTypeConverter.java b/resource-server/src/main/java/com/inhabas/api/web/converter/NormalBoardTypeConverter.java index 1a7fed74..0e34d4fd 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/converter/NormalBoardTypeConverter.java +++ b/resource-server/src/main/java/com/inhabas/api/web/converter/NormalBoardTypeConverter.java @@ -1,35 +1,36 @@ package com.inhabas.api.web.converter; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import com.inhabas.api.auth.domain.error.businessException.NotFoundException; -import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import com.inhabas.api.auth.domain.error.businessException.NotFoundException; +import com.inhabas.api.domain.normalBoard.domain.NormalBoardType; + public class NormalBoardTypeConverter { - @Component - public static class StringToContestTypeConverter implements Converter { + @Component + public static class StringToNormalTypeConverter implements Converter { - @Override - public NormalBoardType convert(String source) { - if (!StringUtils.hasText(source)) { - throw new InvalidInputException(); - } - try { - return NormalBoardType.valueOf(source.trim().toUpperCase()); - } catch (IllegalArgumentException e) { - throw new NotFoundException(); - } - } + @Override + public NormalBoardType convert(String source) { + if (!StringUtils.hasText(source)) { + throw new InvalidInputException(); + } + try { + return NormalBoardType.valueOf(source.trim().toUpperCase()); + } catch (IllegalArgumentException e) { + throw new NotFoundException(); + } } + } - @Component - public static class ContestTypeToStringConverter implements Converter { - @Override - public String convert(NormalBoardType source) { - return source != null ? source.toString().toLowerCase() : null; - } + @Component + public static class NormalTypeToStringConverter implements Converter { + @Override + public String convert(NormalBoardType source) { + return source != null ? source.toString().toLowerCase() : null; } -} \ No newline at end of file + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java index 746a6708..b427d696 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java @@ -7,6 +7,7 @@ public class MenuGroupExampleTest { public static MenuGroup getIBASMenuGroup() { return new MenuGroup("IBAS"); } + public static MenuGroup getNormalMenuGroup() { return new MenuGroup("게시판"); } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java index e79556de..b09248d8 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardExampleTest.java @@ -1,27 +1,27 @@ package com.inhabas.api.domain.normalBoard.domain; -import com.inhabas.api.domain.menu.domain.Menu; import org.springframework.test.util.ReflectionTestUtils; -public class NormalBoardExampleTest { +import com.inhabas.api.domain.menu.domain.Menu; - public static NormalBoard getBoard1(Menu menu) { - return new NormalBoard("이건 공지1", menu, "이건 공지1입니다.", false, null); - } +public class NormalBoardExampleTest { - public static NormalBoard getBoard2(Menu menu) { - return new NormalBoard("이건 공지2", menu, "이건 공지2입니다.", false, null); - } + public static NormalBoard getBoard1(Menu menu) { + return new NormalBoard("이건 공지1", menu, "이건 공지1입니다.", false, null); + } - public static NormalBoard getBoard3(Menu menu) { - return new NormalBoard("이건 공지3", menu, "이건 공지3입니다.", false, null); - } + public static NormalBoard getBoard2(Menu menu) { + return new NormalBoard("이건 공지2", menu, "이건 공지2입니다.", false, null); + } - public static NormalBoard getTestBoard(Integer id, Menu menu) { + public static NormalBoard getBoard3(Menu menu) { + return new NormalBoard("이건 공지3", menu, "이건 공지3입니다.", false, null); + } - NormalBoard board = new NormalBoard("이건 공지", menu, "이건 공지입니다.", false, null); - ReflectionTestUtils.setField(board, "id", id); - return board; - } + public static NormalBoard getTestBoard(Integer id, Menu menu) { + NormalBoard board = new NormalBoard("이건 공지", menu, "이건 공지입니다.", false, null); + ReflectionTestUtils.setField(board, "id", id); + return board; + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java index e283f60c..fd404d3a 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/domain/NormalBoardTest.java @@ -1,21 +1,21 @@ package com.inhabas.api.domain.normalBoard.domain; +import java.util.ArrayList; +import java.util.List; + import com.inhabas.api.domain.file.domain.BoardFile; import com.inhabas.api.domain.menu.domain.Menu; import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import java.util.ArrayList; -import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; public class NormalBoardTest { - @Mock - private Menu menu; + @Mock private Menu menu; private NormalBoard normalBoard; diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java index 1929946e..daf90bcf 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java @@ -1,67 +1,91 @@ package com.inhabas.api.domain.normalBoard.dto; -import com.inhabas.api.domain.file.dto.FileDownloadDto; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Set; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import com.inhabas.api.domain.file.dto.FileDownloadDto; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; class NormalBoardDetailDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - private final List emptyList = new ArrayList<>(); + private static ValidatorFactory validatorFactory; + private static Validator validator; + private final List emptyList = new ArrayList<>(); - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } - @AfterAll - public static void close() { - validatorFactory.close(); - } + @AfterAll + public static void close() { + validatorFactory.close(); + } - @DisplayName("NormalBoardDetailDto 객체를 정상적으로 생성한다.") - @Test - public void NormalBoardDetailDto_is_OK() { - // given - NormalBoardDetailDto normalBoardDetailDto = - new NormalBoardDetailDto(1L, "title", "content", 1L, "writer", - LocalDateTime.now(), LocalDateTime.now(), LocalDateTime.now(), emptyList, emptyList, false); + @DisplayName("NormalBoardDetailDto 객체를 정상적으로 생성한다.") + @Test + public void NormalBoardDetailDto_is_OK() { + // given + NormalBoardDetailDto normalBoardDetailDto = + new NormalBoardDetailDto( + 1L, + "title", + "content", + 1L, + "writer", + LocalDateTime.now(), + LocalDateTime.now(), + LocalDateTime.now(), + emptyList, + emptyList, + false); - // when - Set> violations = validator.validate(normalBoardDetailDto); + // when + Set> violations = + validator.validate(normalBoardDetailDto); - // then - assertTrue(violations.isEmpty()); - } + // then + assertTrue(violations.isEmpty()); + } - @DisplayName("normalBoardDetailDto title 필드가 null 이면 validation 실패") - @Test - public void Title_is_null() { - // given - NormalBoardDetailDto normalBoardDetailDto = - new NormalBoardDetailDto(1L, null, "content", 1L, "writer", - LocalDateTime.now(), LocalDateTime.now(), LocalDateTime.now(), emptyList, emptyList, false); + @DisplayName("normalBoardDetailDto title 필드가 null 이면 validation 실패") + @Test + public void Title_is_null() { + // given + NormalBoardDetailDto normalBoardDetailDto = + new NormalBoardDetailDto( + 1L, + null, + "content", + 1L, + "writer", + LocalDateTime.now(), + LocalDateTime.now(), + LocalDateTime.now(), + emptyList, + emptyList, + false); - // when - Set> violations = validator.validate(normalBoardDetailDto); + // when + Set> violations = + validator.validate(normalBoardDetailDto); - // then - assertEquals(1, violations.size()); - } -} \ No newline at end of file + // then + assertEquals(1, violations.size()); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java index 08d4cc56..43f5b176 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java @@ -1,64 +1,78 @@ package com.inhabas.api.domain.normalBoard.dto; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.LocalDateTime; +import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; -import java.time.LocalDateTime; -import java.util.Set; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; class NormalBoardDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } + private static ValidatorFactory validatorFactory; + private static Validator validator; - @AfterAll - public static void close() { - validatorFactory.close(); - } + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } - @DisplayName("NormalBoardDto 객체를 정상적으로 생성한다.") - @Test - public void NormalBoardDto_is_OK() { - // given - NormalBoardDto normalBoardDto = - new NormalBoardDto(1L, "title", 1L, "writer", LocalDateTime.now(), - LocalDateTime.now(), LocalDateTime.now(), false); + @AfterAll + public static void close() { + validatorFactory.close(); + } - // when - Set> violations = validator.validate(normalBoardDto); + @DisplayName("NormalBoardDto 객체를 정상적으로 생성한다.") + @Test + public void NormalBoardDto_is_OK() { + // given + NormalBoardDto normalBoardDto = + new NormalBoardDto( + 1L, + "title", + 1L, + "writer", + LocalDateTime.now(), + LocalDateTime.now(), + LocalDateTime.now(), + false); - // then - assertTrue(violations.isEmpty()); - } + // when + Set> violations = validator.validate(normalBoardDto); - @DisplayName("NormalBoardDto title 필드가 null 이면 validation 실패") - @Test - public void Title_is_null() { - // given - NormalBoardDto normalBoardDto = - new NormalBoardDto(1L, null, 1L, "writer", LocalDateTime.now(), - LocalDateTime.now(), LocalDateTime.now(), false); + // then + assertTrue(violations.isEmpty()); + } - // when - Set> violations = validator.validate(normalBoardDto); + @DisplayName("NormalBoardDto title 필드가 null 이면 validation 실패") + @Test + public void Title_is_null() { + // given + NormalBoardDto normalBoardDto = + new NormalBoardDto( + 1L, + null, + 1L, + "writer", + LocalDateTime.now(), + LocalDateTime.now(), + LocalDateTime.now(), + false); - // then - assertEquals(1, violations.size()); - } + // when + Set> violations = validator.validate(normalBoardDto); -} \ No newline at end of file + // then + assertEquals(1, violations.size()); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java index 2c86b083..a6829a75 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java @@ -1,21 +1,23 @@ package com.inhabas.api.domain.normalBoard.dto; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.web.multipart.MultipartFile; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import org.springframework.web.multipart.MultipartFile; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; public class SaveNormalBoardDtoTest { @@ -39,10 +41,11 @@ public static void close() { public void SaveNormalBoardDto_is_OK() { // given SaveNormalBoardDto saveNormalBoardDto = - new SaveNormalBoardDto("title", "content", emptyList, 2); + new SaveNormalBoardDto("title", "content", emptyList, 2); // when - Set> violations = validator.validate(saveNormalBoardDto); + Set> violations = + validator.validate(saveNormalBoardDto); // then assertTrue(violations.isEmpty()); @@ -52,13 +55,13 @@ public void SaveNormalBoardDto_is_OK() { @Test public void Content_is_null() { // given - SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", null, emptyList,2); + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", null, emptyList, 2); // when - Set> violations = validator.validate(saveNormalBoardDto); + Set> violations = + validator.validate(saveNormalBoardDto); // then assertEquals(1, violations.size()); } - } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryTest.java index 2c64fd77..6001b2b5 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/repository/NormalBoardRepositoryTest.java @@ -1,5 +1,15 @@ package com.inhabas.api.domain.normalBoard.repository; +import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; +import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.NOTICE; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.domain.MenuGroup; @@ -8,126 +18,124 @@ import com.inhabas.api.domain.normalBoard.domain.NormalBoardExampleTest; import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; import com.inhabas.testAnnotataion.DefaultDataJpaTest; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import org.springframework.test.util.ReflectionTestUtils; - -import java.util.List; - -import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; -import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.NOTICE; -import static org.assertj.core.api.Assertions.assertThat; @DefaultDataJpaTest public class NormalBoardRepositoryTest { - @Autowired - NormalBoardRepository normalBoardRepository; + @Autowired NormalBoardRepository normalBoardRepository; @Autowired TestEntityManager em; NormalBoard NOTICE_BOARD; NormalBoard NOTICE_BOARD_2; Member writer; - @BeforeEach - public void setUp() { - em.getEntityManager().createNativeQuery("ALTER TABLE MENU ALTER COLUMN `id` RESTART WITH 4").executeUpdate(); - writer = em.persist(basicMember1()); - MenuGroup boardMenuGroup = em.persist(new MenuGroup("게시판")); - Menu noticeBoardMenu = em.persist( - Menu.builder() - .menuGroup(boardMenuGroup) - .priority(1) - .type(MenuType.NORMAL_NOTICE) - .name("공지사항") - .description("부원이 알아야 할 내용을 게시합니다.") - .build()); - ReflectionTestUtils.setField(noticeBoardMenu, "id", 4); - NOTICE_BOARD = NormalBoardExampleTest.getBoard1(noticeBoardMenu) - .writtenBy(writer, NormalBoard.class); - NOTICE_BOARD_2 = NormalBoardExampleTest.getBoard2(noticeBoardMenu) - .writtenBy(writer, NormalBoard.class); - } - - @AfterEach - public void deleteAll() { - - this.normalBoardRepository.deleteAll(); - this.em.clear(); - } - - @DisplayName("저장 후 반환값이 처음과 같다.") - @Test - public void save() { - //when - NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); - - //then - assertThat(saveBoard.getWriter()).isEqualTo(writer); - } - - @DisplayName("memberId, type, search 로 게시글 목록 조회한다.") - @Test - public void findAllByMemberIdAndTypeAndSearch() { - //given - NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); - NormalBoard saveBoard2 = normalBoardRepository.save(NOTICE_BOARD_2); - Long writerId = writer.getId(); - - //when - List dtoList = normalBoardRepository.findAllByMemberIdAndTypeAndSearch(writerId, NOTICE, ""); - - //then - assertThat(dtoList).hasSize(2); - assertThat(dtoList.get(0).getTitle()).isEqualTo(saveBoard.getTitle()); - } - - @DisplayName("type, search 로 게시글 목록 조회한다.") - @Test - public void findAllByTypeAndSearch() { - //given - NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); - NormalBoard saveBoard2 = normalBoardRepository.save(NOTICE_BOARD_2); - - //when - List dtoList = normalBoardRepository.findAllByTypeAndSearch(NOTICE, ""); - - //then - assertThat(dtoList).hasSize(2); - assertThat(dtoList.get(0).getTitle()).isEqualTo(saveBoard.getTitle()); - } - - @DisplayName("memberId, type, id 로 게시글 상세 조회한다.") - @Test - public void findByMemberIdAndTypeAndId() { - //given - NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); - Long writerId = writer.getId(); - - //when - NormalBoard normalBoard = normalBoardRepository.findByMemberIdAndTypeAndId(writerId, NOTICE, saveBoard.getId()).orElse(null); - - //then - assertThat(normalBoard).isNotNull(); - assertThat(normalBoard.getTitle()).isEqualTo(saveBoard.getTitle()); - } - - @DisplayName("type, id 로 게시글 상세 조회한다.") - @Test - public void findByTypeAndId() { - //given - NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); - - //when - NormalBoard normalBoard = normalBoardRepository.findByTypeAndId(NOTICE, saveBoard.getId()).orElse(null); - - //then - assertThat(normalBoard).isNotNull(); - assertThat(normalBoard.getTitle()).isEqualTo(saveBoard.getTitle()); - } - + @BeforeEach + public void setUp() { + em.getEntityManager() + .createNativeQuery("ALTER TABLE MENU ALTER COLUMN `id` RESTART WITH 4") + .executeUpdate(); + writer = em.persist(basicMember1()); + MenuGroup boardMenuGroup = em.persist(new MenuGroup("게시판")); + Menu noticeBoardMenu = + em.persist( + Menu.builder() + .menuGroup(boardMenuGroup) + .priority(1) + .type(MenuType.NORMAL_NOTICE) + .name("공지사항") + .description("부원이 알아야 할 내용을 게시합니다.") + .build()); + ReflectionTestUtils.setField(noticeBoardMenu, "id", 4); + NOTICE_BOARD = + NormalBoardExampleTest.getBoard1(noticeBoardMenu).writtenBy(writer, NormalBoard.class); + NOTICE_BOARD_2 = + NormalBoardExampleTest.getBoard2(noticeBoardMenu).writtenBy(writer, NormalBoard.class); + } + + @AfterEach + public void deleteAll() { + + this.normalBoardRepository.deleteAll(); + this.em.clear(); + } + + @DisplayName("저장 후 반환값이 처음과 같다.") + @Test + public void save() { + // when + NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); + + // then + assertThat(saveBoard.getWriter()).isEqualTo(writer); + } + + @DisplayName("memberId, type, search 로 게시글 목록 조회한다.") + @Test + public void findAllByMemberIdAndTypeAndSearch() { + // given + NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); + NormalBoard saveBoard2 = normalBoardRepository.save(NOTICE_BOARD_2); + Long writerId = writer.getId(); + + // when + List dtoList = + normalBoardRepository.findAllByMemberIdAndTypeAndSearch(writerId, NOTICE, ""); + + // then + assertThat(dtoList).hasSize(2); + assertThat(dtoList.get(0).getTitle()).isEqualTo(saveBoard.getTitle()); + } + + @DisplayName("type, search 로 게시글 목록 조회한다.") + @Test + public void findAllByTypeAndSearch() { + // given + NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); + NormalBoard saveBoard2 = normalBoardRepository.save(NOTICE_BOARD_2); + + // when + List dtoList = normalBoardRepository.findAllByTypeAndSearch(NOTICE, ""); + + // then + assertThat(dtoList).hasSize(2); + assertThat(dtoList.get(0).getTitle()).isEqualTo(saveBoard.getTitle()); + } + + @DisplayName("memberId, type, id 로 게시글 상세 조회한다.") + @Test + public void findByMemberIdAndTypeAndId() { + // given + NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); + Long writerId = writer.getId(); + + // when + NormalBoard normalBoard = + normalBoardRepository + .findByMemberIdAndTypeAndId(writerId, NOTICE, saveBoard.getId()) + .orElse(null); + + // then + assertThat(normalBoard).isNotNull(); + assertThat(normalBoard.getTitle()).isEqualTo(saveBoard.getTitle()); + } + + @DisplayName("type, id 로 게시글 상세 조회한다.") + @Test + public void findByTypeAndId() { + // given + NormalBoard saveBoard = normalBoardRepository.save(NOTICE_BOARD); + + // when + NormalBoard normalBoard = + normalBoardRepository.findByTypeAndId(NOTICE, saveBoard.getId()).orElse(null); + + // then + assertThat(normalBoard).isNotNull(); + assertThat(normalBoard.getTitle()).isEqualTo(saveBoard.getTitle()); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java index c4ebf3cb..01fd5d7c 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/usecase/NormalBoardServiceImplTest.java @@ -1,5 +1,22 @@ package com.inhabas.api.domain.normalBoard.usecase; +import static com.inhabas.api.domain.menu.domain.MenuExampleTest.getNormalNoticeMenu; +import static com.inhabas.api.domain.menu.domain.valueObject.MenuGroupExampleTest.getNormalMenuGroup; +import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.NOTICE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; import com.inhabas.api.domain.file.usecase.S3Service; @@ -11,135 +28,121 @@ import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; import com.inhabas.api.domain.normalBoard.dto.SaveNormalBoardDto; import com.inhabas.api.domain.normalBoard.repository.NormalBoardRepository; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; -import static com.inhabas.api.domain.menu.domain.MenuExampleTest.getNormalNoticeMenu; -import static com.inhabas.api.domain.menu.domain.valueObject.MenuGroupExampleTest.getNormalMenuGroup; -import static com.inhabas.api.domain.normalBoard.domain.NormalBoardType.NOTICE; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.times; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class NormalBoardServiceImplTest { - @InjectMocks - NormalBoardServiceImpl normalBoardService; - - @Mock - MemberRepository memberRepository; - @Mock - NormalBoardRepository normalBoardRepository; - @Mock - MenuRepository menuRepository; - @Mock - S3Service s3Service; - - @DisplayName("normal board 게시글 목록을 조회한다.") - @Test - void getPosts() { - // given - NormalBoardDto dto = new NormalBoardDto(1L, "title", 1L, "writer", LocalDateTime.now(), - LocalDateTime.now(), LocalDateTime.now(), false); - - given(normalBoardRepository.findAllByTypeAndSearch(any(), any())) - .willReturn(List.of(dto)); - - // when - List clubActivityDtoList = normalBoardService.getPosts(NOTICE, ""); - - // then - assertThat(clubActivityDtoList).hasSize(1); - } - - @DisplayName("normal board 게시글 단일 조회한다.") - @Test - void getPost() { - // given - Member member = MemberTest.chiefMember(); - Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); - NormalBoard normalBoard = - new NormalBoard("title", menu, "content", false, LocalDateTime.now()) - .writtenBy(member, NormalBoard.class); - - given(normalBoardRepository.findByTypeAndId(any(), any())).willReturn(Optional.of(normalBoard)); - - // when - NormalBoardDetailDto dto = normalBoardService.getPost(1L, NOTICE, 1L); - - // then - assertThat(dto.getTitle()).isEqualTo(normalBoard.getTitle()); - - } - - @DisplayName("normal board 게시글을 작성한다.") - @Test - void write() { - //given - Member member = MemberTest.chiefMember(); - SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", "content", null, 2); - Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); - NormalBoard normalBoard = - new NormalBoard("title", menu, "content", false, LocalDateTime.now()) - .writtenBy(member, NormalBoard.class); - - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - given(normalBoardRepository.save(any())).willReturn(normalBoard); - given(menuRepository.findById(anyInt())).willReturn(Optional.of(menu)); - - // when - normalBoardService.write(1L, NOTICE, saveNormalBoardDto); - - // then - then(menuRepository).should(times(1)).findById(anyInt()); - then(normalBoardRepository).should(times(1)).save(any()); - } - - @DisplayName("normal board 게시글을 수정한다.") - @Test - void update() { - //given - SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", "content", null, 2); - Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); - NormalBoard normalBoard = new NormalBoard("title", menu, "content", false, LocalDateTime.now()); - ReflectionTestUtils.setField(normalBoard, "id", 1L); - - given(normalBoardRepository.findById(any())).willReturn(Optional.of(normalBoard)); - given(normalBoardRepository.save(any())).willReturn(normalBoard); - - // when - normalBoardService.update(normalBoard.getId(), NOTICE, saveNormalBoardDto); - - // then - then(normalBoardRepository).should(times(1)).findById(any()); - then(normalBoardRepository).should(times(1)).save(any()); - } - - @DisplayName("normal board 게시글을 삭제한다.") - @Test - void delete() { - // given - Long boardId = 1L; - doNothing().when(normalBoardRepository).deleteById(boardId); - - // when - normalBoardService.delete(boardId); - - // then - then(normalBoardRepository).should(times(1)).deleteById(boardId); - } -} \ No newline at end of file + @InjectMocks NormalBoardServiceImpl normalBoardService; + + @Mock MemberRepository memberRepository; + @Mock NormalBoardRepository normalBoardRepository; + @Mock MenuRepository menuRepository; + @Mock S3Service s3Service; + + @DisplayName("normal board 게시글 목록을 조회한다.") + @Test + void getPosts() { + // given + NormalBoardDto dto = + new NormalBoardDto( + 1L, + "title", + 1L, + "writer", + LocalDateTime.now(), + LocalDateTime.now(), + LocalDateTime.now(), + false); + + given(normalBoardRepository.findAllByTypeAndSearch(any(), any())).willReturn(List.of(dto)); + + // when + List clubActivityDtoList = normalBoardService.getPosts(NOTICE, ""); + + // then + assertThat(clubActivityDtoList).hasSize(1); + } + + @DisplayName("normal board 게시글 단일 조회한다.") + @Test + void getPost() { + // given + Member member = MemberTest.chiefMember(); + Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); + NormalBoard normalBoard = + new NormalBoard("title", menu, "content", false, LocalDateTime.now()) + .writtenBy(member, NormalBoard.class); + + given(normalBoardRepository.findByTypeAndId(any(), any())).willReturn(Optional.of(normalBoard)); + + // when + NormalBoardDetailDto dto = normalBoardService.getPost(1L, NOTICE, 1L); + + // then + assertThat(dto.getTitle()).isEqualTo(normalBoard.getTitle()); + } + + @DisplayName("normal board 게시글을 작성한다.") + @Test + void write() { + // given + Member member = MemberTest.chiefMember(); + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", "content", null, 2); + Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); + NormalBoard normalBoard = + new NormalBoard("title", menu, "content", false, LocalDateTime.now()) + .writtenBy(member, NormalBoard.class); + + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + given(normalBoardRepository.save(any())).willReturn(normalBoard); + given(menuRepository.findById(anyInt())).willReturn(Optional.of(menu)); + + // when + normalBoardService.write(1L, NOTICE, saveNormalBoardDto); + + // then + then(menuRepository).should(times(1)).findById(anyInt()); + then(normalBoardRepository).should(times(1)).save(any()); + } + + @DisplayName("normal board 게시글을 수정한다.") + @Test + void update() { + // given + SaveNormalBoardDto saveNormalBoardDto = new SaveNormalBoardDto("title", "content", null, 2); + Menu menu = getNormalNoticeMenu(getNormalMenuGroup()); + NormalBoard normalBoard = new NormalBoard("title", menu, "content", false, LocalDateTime.now()); + ReflectionTestUtils.setField(normalBoard, "id", 1L); + + given(normalBoardRepository.findById(any())).willReturn(Optional.of(normalBoard)); + given(normalBoardRepository.save(any())).willReturn(normalBoard); + + // when + normalBoardService.update(normalBoard.getId(), NOTICE, saveNormalBoardDto); + + // then + then(normalBoardRepository).should(times(1)).findById(any()); + then(normalBoardRepository).should(times(1)).save(any()); + } + + @DisplayName("normal board 게시글을 삭제한다.") + @Test + void delete() { + // given + Long boardId = 1L; + doNothing().when(normalBoardRepository).deleteById(boardId); + + // when + normalBoardService.delete(boardId); + + // then + then(normalBoardRepository).should(times(1)).deleteById(boardId); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java index 9032a966..3d84d67a 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/NormalBoardControllerTest.java @@ -1,5 +1,25 @@ package com.inhabas.api.web; +import static com.inhabas.api.auth.domain.error.ErrorCode.INVALID_INPUT_VALUE; +import static com.inhabas.api.auth.domain.error.ErrorCode.NOT_FOUND; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @@ -12,337 +32,316 @@ import com.inhabas.api.domain.normalBoard.dto.NormalBoardDto; import com.inhabas.api.domain.normalBoard.usecase.NormalBoardService; import com.inhabas.testAnnotataion.NoSecureWebMvcTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.web.servlet.MockMvc; - -import java.nio.charset.StandardCharsets; -import java.time.LocalDateTime; -import java.util.List; - -import static com.inhabas.api.auth.domain.error.ErrorCode.INVALID_INPUT_VALUE; -import static com.inhabas.api.auth.domain.error.ErrorCode.NOT_FOUND; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @NoSecureWebMvcTest(NormalBoardController.class) public class NormalBoardControllerTest { - @Autowired - private MockMvc mvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private NormalBoardService normalBoardService; - @MockBean - private BaseBoardRepository baseBoardRepository; - - private String jsonOf(Object response) throws JsonProcessingException { - return objectMapper.writeValueAsString(response); - } - - @DisplayName("게시판 종류 당 글 개수 조회 성공 200") - @Test - void getBoardCount_Success() throws Exception { - // given - BoardCountDto boardCountDto = new BoardCountDto("공지사항", 10); - List dtoList = List.of(boardCountDto); - given(baseBoardRepository.countRowsGroupByMenuName(any())).willReturn(dtoList); - - // when - String response = - mvc.perform(get("/board/count")) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - // then - assertThat(response).contains(jsonOf(dtoList)); - } - - @DisplayName("게시글 목록 조회 성공 200") - @Test - void getBoardList_Success() throws Exception { - // given - Member writer = MemberTest.chiefMember(); - NormalBoardDto normalBoardDto = - NormalBoardDto.builder() - .id(1L) - .title("title") - .writerName(writer.getName()) - .dateCreated(LocalDateTime.now()) - .dateUpdated(LocalDateTime.now()) - .isPinned(false) - .build(); - List dtoList = List.of(normalBoardDto); - given(normalBoardService.getPosts(any(),any())).willReturn(dtoList); - - // when - String response = - mvc.perform(get("/board/notice")) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - // then - assertThat(response).contains(jsonOf(dtoList)); - } - - @DisplayName("게시글 목록 조회 데이터가 올바르지 않다면 400") - @Test - void getBoardList_Invalid_Input() throws Exception { - // when - String response = - mvc.perform(get("/board/invalid")) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - // then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - } - - @DisplayName("게시글 단일 조회 성공 200") - @Test - void getBoard() throws Exception { - // given - Member writer = MemberTest.chiefMember(); - NormalBoardDetailDto normalBoardDetailDto = - NormalBoardDetailDto.builder() - .id(1L) - .title("title") - .content("content") - .writerName(writer.getName()) - .images(null) - .otherFiles(null) - .dateCreated(LocalDateTime.now()) - .dateUpdated(LocalDateTime.now()) - .isPinned(false) - .build(); - given(normalBoardService.getPost(any(),any(),any())).willReturn(normalBoardDetailDto); - - // when - String response = - mvc.perform(get("/board/notice/1")) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - // then - assertThat(response).contains(jsonOf(normalBoardDetailDto)); - } - - @DisplayName("게시글 단일 조회 데이터가 올바르지 않다면 400") - @Test - void getBoard_Invalid_Input() throws Exception { - // when - String response = - mvc.perform(get("/board/notice/invalid")) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - // then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - } - - @DisplayName("게시글 단일 조회 데이터가 올바르지 않다면 404") - @Test - void getBoard_Not_Found() throws Exception { - // given - doThrow(NotFoundException.class).when(normalBoardService).getPost(any(), any(), any()); - - // when - String response = - mvc.perform(get("/board/notice/1")) - .andExpect(status().isNotFound()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - // then - assertThat(response).contains(NOT_FOUND.getMessage()); - } - - @DisplayName("게시글 추가 성공 201") - @Test - void addBoard() throws Exception { - // given - given(normalBoardService.write(any(),any(),any())).willReturn(1L); - MockMultipartFile titlePart = - new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); - MockMultipartFile contentPart = - new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); - - // when - String header = - mvc.perform( - multipart("/board/notice?pinOption=2") - .file(titlePart) - .file(contentPart) - .contentType(MediaType.MULTIPART_FORM_DATA)) - .andExpect(status().isCreated()) - .andReturn() - .getResponse() - .getHeader("Location"); - - // then - assertThat(header).contains("/board/notice/1"); - } - - @DisplayName("게시글 추가 데이터가 올바르지 않다면 400") - @Test - void addBoard_Invalid_Input() throws Exception { - //given - MockMultipartFile titlePart = - new MockMultipartFile("title", "".getBytes(StandardCharsets.UTF_8)); - MockMultipartFile contentPart = - new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); - // when - String response = - mvc.perform(multipart("/board/notice?pinOption=2") - .file(titlePart) - .file(contentPart) - .contentType(MediaType.MULTIPART_FORM_DATA)) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - // then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - } - - @DisplayName("게시글 수정 성공 204") - @Test - void updateBoard() throws Exception { - // given - MockMultipartFile titlePart = - new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); - MockMultipartFile contentPart = - new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); - doNothing().when(normalBoardService).update(any(), any(), any()); - - // when then + @Autowired private MockMvc mvc; + + @Autowired private ObjectMapper objectMapper; + + @MockBean private NormalBoardService normalBoardService; + @MockBean private BaseBoardRepository baseBoardRepository; + + private String jsonOf(Object response) throws JsonProcessingException { + return objectMapper.writeValueAsString(response); + } + + @DisplayName("게시판 종류 당 글 개수 조회 성공 200") + @Test + void getBoardCount_Success() throws Exception { + // given + BoardCountDto boardCountDto = new BoardCountDto("공지사항", 10); + List dtoList = List.of(boardCountDto); + given(baseBoardRepository.countRowsGroupByMenuName(any())).willReturn(dtoList); + + // when + String response = + mvc.perform(get("/board/count")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(jsonOf(dtoList)); + } + + @DisplayName("게시글 목록 조회 성공 200") + @Test + void getBoardList_Success() throws Exception { + // given + Member writer = MemberTest.chiefMember(); + NormalBoardDto normalBoardDto = + NormalBoardDto.builder() + .id(1L) + .title("title") + .writerName(writer.getName()) + .dateCreated(LocalDateTime.now()) + .dateUpdated(LocalDateTime.now()) + .isPinned(false) + .build(); + List dtoList = List.of(normalBoardDto); + given(normalBoardService.getPosts(any(), any())).willReturn(dtoList); + + // when + String response = + mvc.perform(get("/board/notice")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(jsonOf(dtoList)); + } + + @DisplayName("게시글 목록 조회 데이터가 올바르지 않다면 400") + @Test + void getBoardList_Invalid_Input() throws Exception { + // when + String response = + mvc.perform(get("/board/invalid")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("게시글 단일 조회 성공 200") + @Test + void getBoard() throws Exception { + // given + Member writer = MemberTest.chiefMember(); + NormalBoardDetailDto normalBoardDetailDto = + NormalBoardDetailDto.builder() + .id(1L) + .title("title") + .content("content") + .writerName(writer.getName()) + .images(null) + .otherFiles(null) + .dateCreated(LocalDateTime.now()) + .dateUpdated(LocalDateTime.now()) + .isPinned(false) + .build(); + given(normalBoardService.getPost(any(), any(), any())).willReturn(normalBoardDetailDto); + + // when + String response = + mvc.perform(get("/board/notice/1")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(jsonOf(normalBoardDetailDto)); + } + + @DisplayName("게시글 단일 조회 데이터가 올바르지 않다면 400") + @Test + void getBoard_Invalid_Input() throws Exception { + // when + String response = + mvc.perform(get("/board/notice/invalid")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("게시글 단일 조회 데이터가 올바르지 않다면 404") + @Test + void getBoard_Not_Found() throws Exception { + // given + doThrow(NotFoundException.class).when(normalBoardService).getPost(any(), any(), any()); + + // when + String response = + mvc.perform(get("/board/notice/1")) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } + + @DisplayName("게시글 추가 성공 201") + @Test + void addBoard() throws Exception { + // given + given(normalBoardService.write(any(), any(), any())).willReturn(1L); + MockMultipartFile titlePart = + new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); + + // when + String header = + mvc.perform( + multipart("/board/notice?pinOption=2") + .file(titlePart) + .file(contentPart) + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader("Location"); + + // then + assertThat(header).contains("/board/notice/1"); + } + + @DisplayName("게시글 추가 데이터가 올바르지 않다면 400") + @Test + void addBoard_Invalid_Input() throws Exception { + // given + MockMultipartFile titlePart = + new MockMultipartFile("title", "".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); + // when + String response = + mvc.perform( + multipart("/board/notice?pinOption=2") + .file(titlePart) + .file(contentPart) + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("게시글 수정 성공 204") + @Test + void updateBoard() throws Exception { + // given + MockMultipartFile titlePart = + new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); + doNothing().when(normalBoardService).update(any(), any(), any()); + + // when then + mvc.perform( + multipart("/board/notice/1?pinOption=2") + .file(titlePart) + .file(contentPart) + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(status().isNoContent()); + } + + @DisplayName("게시글 수정 데이터가 올바르지 않다면 400") + @Test + void updateBoard_Invalid_Input() throws Exception { + // given + MockMultipartFile titlePart = + new MockMultipartFile("title", "".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); + doThrow(InvalidInputException.class).when(normalBoardService).update(any(), any(), any()); + + // when + String response = + mvc.perform( + multipart("/board/notice?pinOption=2") + .file(titlePart) + .file(contentPart) + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("게시글 수정 데이터가 올바르지 않다면 404") + @Test + void updateBoard_Not_Found() throws Exception { + // given + MockMultipartFile titlePart = + new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); + doThrow(NotFoundException.class).when(normalBoardService).update(any(), any(), any()); + + // when + String response = mvc.perform( - multipart("/board/notice/1?pinOption=2") - .file(titlePart) - .file(contentPart) - .contentType(MediaType.MULTIPART_FORM_DATA)) - .andExpect(status().isNoContent()); - } - - @DisplayName("게시글 수정 데이터가 올바르지 않다면 400") - @Test - void updateBoard_Invalid_Input() throws Exception { - //given - MockMultipartFile titlePart = - new MockMultipartFile("title", "".getBytes(StandardCharsets.UTF_8)); - MockMultipartFile contentPart = - new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); - doThrow(InvalidInputException.class).when(normalBoardService).update(any(), any(), any()); - - // when - String response = - mvc.perform(multipart("/board/notice?pinOption=2") - .file(titlePart) - .file(contentPart) - .contentType(MediaType.MULTIPART_FORM_DATA)) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - // then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - } - - @DisplayName("게시글 수정 데이터가 올바르지 않다면 404") - @Test - void updateBoard_Not_Found() throws Exception { - //given - MockMultipartFile titlePart = - new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); - MockMultipartFile contentPart = - new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); - doThrow(NotFoundException.class).when(normalBoardService).update(any(), any(), any()); - - // when - String response = - mvc.perform(multipart("/board/notice/1?pinOption=2") - .file(titlePart) - .file(contentPart) - .contentType(MediaType.MULTIPART_FORM_DATA)) - .andExpect(status().isNotFound()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - // then - assertThat(response).contains(NOT_FOUND.getMessage()); - } - - @DisplayName("게시글 삭제 성공 204") - @Test - void deleteBoard() throws Exception { - // given - doNothing().when(normalBoardService).delete(any()); - - // when then + multipart("/board/notice/1?pinOption=2") + .file(titlePart) + .file(contentPart) + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } + + @DisplayName("게시글 삭제 성공 204") + @Test + void deleteBoard() throws Exception { + // given + doNothing().when(normalBoardService).delete(any()); + + // when then + mvc.perform(delete("/board/notice/1")).andExpect(status().isNoContent()); + } + + @DisplayName("게시글 삭제 데이터가 올바르지 않다면 400") + @Test + void deleteBoard_Invalid_Input() throws Exception { + // given + doNothing().when(normalBoardService).delete(any()); + + // when + String response = + mvc.perform(delete("/board/invalid/invalid")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("게시글 삭제 데이터가 올바르지 않다면 404") + @Test + void deleteBoard_Not_Found() throws Exception { + // given + doThrow(NotFoundException.class).when(normalBoardService).delete(any()); + + // when + String response = mvc.perform(delete("/board/notice/1")) - .andExpect(status().isNoContent()); - } - - @DisplayName("게시글 삭제 데이터가 올바르지 않다면 400") - @Test - void deleteBoard_Invalid_Input() throws Exception { - //given - doNothing().when(normalBoardService).delete(any()); - - // when - String response = - mvc.perform(delete("/board/invalid/invalid")) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - // then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - } - - @DisplayName("게시글 삭제 데이터가 올바르지 않다면 404") - @Test - void deleteBoard_Not_Found() throws Exception { - //given - doThrow(NotFoundException.class).when(normalBoardService).delete(any()); - - // when - String response = - mvc.perform(delete("/board/notice/1")) - .andExpect(status().isNotFound()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - // then - assertThat(response).contains(NOT_FOUND.getMessage()); - } - -} \ No newline at end of file + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } +} From 02b4d6710caa59717e6ac521ff5d4839dde9a338 Mon Sep 17 00:00:00 2001 From: whitemark Date: Tue, 20 Feb 2024 22:16:14 +0900 Subject: [PATCH 19/19] =?UTF-8?q?[feature/#233]=20assertj=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/normalBoard/dto/NormalBoardDetailDtoTest.java | 7 +++---- .../api/domain/normalBoard/dto/NormalBoardDtoTest.java | 7 +++---- .../api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java | 7 +++---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java index daf90bcf..ed2219a2 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDetailDtoTest.java @@ -1,7 +1,6 @@ package com.inhabas.api.domain.normalBoard.dto; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.assertj.core.api.Assertions.*; import java.time.LocalDateTime; import java.util.ArrayList; @@ -60,7 +59,7 @@ public void NormalBoardDetailDto_is_OK() { validator.validate(normalBoardDetailDto); // then - assertTrue(violations.isEmpty()); + assertThat(violations).isEmpty(); } @DisplayName("normalBoardDetailDto title 필드가 null 이면 validation 실패") @@ -86,6 +85,6 @@ public void Title_is_null() { validator.validate(normalBoardDetailDto); // then - assertEquals(1, violations.size()); + assertThat(violations.size()).isEqualTo(1); } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java index 43f5b176..ccc68989 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/NormalBoardDtoTest.java @@ -1,7 +1,6 @@ package com.inhabas.api.domain.normalBoard.dto; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import java.time.LocalDateTime; import java.util.Set; @@ -51,7 +50,7 @@ public void NormalBoardDto_is_OK() { Set> violations = validator.validate(normalBoardDto); // then - assertTrue(violations.isEmpty()); + assertThat(violations).isEmpty(); } @DisplayName("NormalBoardDto title 필드가 null 이면 validation 실패") @@ -73,6 +72,6 @@ public void Title_is_null() { Set> violations = validator.validate(normalBoardDto); // then - assertEquals(1, violations.size()); + assertThat(violations.size()).isEqualTo(1); } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java index a6829a75..cc8b9d4f 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/normalBoard/dto/SaveNormalBoardDtoTest.java @@ -1,7 +1,6 @@ package com.inhabas.api.domain.normalBoard.dto; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.List; @@ -48,7 +47,7 @@ public void SaveNormalBoardDto_is_OK() { validator.validate(saveNormalBoardDto); // then - assertTrue(violations.isEmpty()); + assertThat(violations).isEmpty(); } @DisplayName("SaveNormalBoardDto content 필드가 null 이면 validation 실패") @@ -62,6 +61,6 @@ public void Content_is_null() { validator.validate(saveNormalBoardDto); // then - assertEquals(1, violations.size()); + assertThat(violations.size()).isEqualTo(1); } }