diff --git a/src/main/java/com/back/catchmate/domain/board/controller/BoardController.java b/src/main/java/com/back/catchmate/domain/board/controller/BoardController.java index cc8f142..169e92b 100644 --- a/src/main/java/com/back/catchmate/domain/board/controller/BoardController.java +++ b/src/main/java/com/back/catchmate/domain/board/controller/BoardController.java @@ -1,9 +1,7 @@ package com.back.catchmate.domain.board.controller; -import com.back.catchmate.domain.board.dto.BoardRequest; import com.back.catchmate.domain.board.dto.BoardRequest.CreateBoardRequest; import com.back.catchmate.domain.board.dto.BoardRequest.UpdateBoardRequest; -import com.back.catchmate.domain.board.dto.BoardResponse; import com.back.catchmate.domain.board.dto.BoardResponse.BoardDeleteInfo; import com.back.catchmate.domain.board.dto.BoardResponse.BoardInfo; import com.back.catchmate.domain.board.dto.BoardResponse.PagedBoardInfo; @@ -30,7 +28,6 @@ import java.time.LocalDate; - @Tag(name = "게시글 관련 API") @RestController @RequestMapping("/board") @@ -80,6 +77,14 @@ public StateResponse addBookMark(@JwtValidation Long userId, return bookMarkService.addBookMark(userId, boardId); } + @GetMapping("/bookmark") + @Operation(summary = "찜한 게시글 조회 API", description = "사용자가 찜한 게시글을 조회하는 API입니다.") + public PagedBoardInfo getBookMarkBoardList(@JwtValidation Long userId, + @PageableDefault(sort = "createdAt", direction = Sort.Direction.DESC) + @Parameter(hidden = true) Pageable pageable) { + return bookMarkService.getBookMarkBoardList(userId, pageable); + } + @DeleteMapping("/bookmark/{boardId}") @Operation(summary = "원하는 게시글을의 찜을 삭제하는 API", description = "원하는 게시글을의 찜을 삭제하는 API 입니다.") public StateResponse removeBookMark(@JwtValidation Long userId, @@ -98,7 +103,7 @@ public BoardInfo updateBoard(@JwtValidation Long userId, @DeleteMapping("/{boardId}") @Operation(summary = "게시글 삭제 API", description = "게시글을 삭제합니다.") public BoardDeleteInfo deleteBoard(@JwtValidation Long userId, - @PathVariable Long boardId) { + @PathVariable Long boardId) { return boardService.deleteBoard(userId, boardId); } } diff --git a/src/main/java/com/back/catchmate/domain/board/converter/BoardConverter.java b/src/main/java/com/back/catchmate/domain/board/converter/BoardConverter.java index a4345a9..2e933d3 100644 --- a/src/main/java/com/back/catchmate/domain/board/converter/BoardConverter.java +++ b/src/main/java/com/back/catchmate/domain/board/converter/BoardConverter.java @@ -3,6 +3,7 @@ import com.back.catchmate.domain.board.dto.BoardRequest.*; import com.back.catchmate.domain.board.dto.BoardResponse.*; import com.back.catchmate.domain.board.entity.Board; +import com.back.catchmate.domain.board.entity.BookMark; import com.back.catchmate.domain.club.entity.Club; import com.back.catchmate.domain.game.converter.GameConverter; import com.back.catchmate.domain.game.dto.GameResponse.GameInfo; @@ -10,6 +11,7 @@ import com.back.catchmate.domain.user.entity.User; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.stereotype.Component; import java.time.LocalDateTime; @@ -33,7 +35,7 @@ public Board toEntity(User user, Game game, Club cheerClub, CreateBoardRequest b .build(); } - public PagedBoardInfo toPagedBoardInfo(Page boardList) { + public PagedBoardInfo toPagedBoardInfoFromBoardList(Page boardList) { List boardInfoList = boardList.stream() .map(board -> toBoardInfo(board, board.getGame())) .toList(); @@ -68,4 +70,13 @@ public BoardDeleteInfo toBoardDeleteInfo(Long boardId) { .deletedAt(LocalDateTime.now()) .build(); } + + public PagedBoardInfo toPagedBoardInfoFromBookMarkList(Page bookMarkList) { + List boards = bookMarkList.stream() + .map(BookMark::getBoard) + .toList(); + + Page boardPage = new PageImpl<>(boards, bookMarkList.getPageable(), bookMarkList.getTotalElements()); + return toPagedBoardInfoFromBoardList(boardPage); + } } diff --git a/src/main/java/com/back/catchmate/domain/board/entity/Board.java b/src/main/java/com/back/catchmate/domain/board/entity/Board.java index ec524f7..e0c13be 100644 --- a/src/main/java/com/back/catchmate/domain/board/entity/Board.java +++ b/src/main/java/com/back/catchmate/domain/board/entity/Board.java @@ -75,7 +75,7 @@ public class Board extends BaseTimeEntity { private Boolean isCompleted = false; public boolean isWriterSameAsLoginUser(User user) { - return this.user.equals(user); + return this.user.getId().equals(user.getId()); } public void updateBoard(Club cheerClub, Game game, UpdateBoardRequest boardRequest) { diff --git a/src/main/java/com/back/catchmate/domain/board/repository/BoardRepository.java b/src/main/java/com/back/catchmate/domain/board/repository/BoardRepository.java index 6068538..ee4f8b2 100644 --- a/src/main/java/com/back/catchmate/domain/board/repository/BoardRepository.java +++ b/src/main/java/com/back/catchmate/domain/board/repository/BoardRepository.java @@ -15,8 +15,8 @@ public interface BoardRepository extends JpaRepository, BoardReposi @Query("UPDATE Board b SET b.deletedAt = CURRENT_TIMESTAMP WHERE b.user.id = :userId AND b.id = :boardId") int softDeleteByUserIdAndBoardId(@Param("userId") Long userId, @Param("boardId") Long boardId); - @Query("SELECT b FROM Board b WHERE b.id = :boardId AND b.deletedAt IS NULL") + @Query("SELECT b FROM Board b WHERE b.id = :boardId AND b.deletedAt IS NULL AND b.isCompleted = true") Optional findByIdAndDeletedAtIsNull(Long boardId); - Page findAllByUserIdAndDeletedAtIsNull(Long userId, Pageable pageable); + Page findAllByUserIdAndDeletedAtIsNullAndIsCompletedIsTrue(Long userId, Pageable pageable); } diff --git a/src/main/java/com/back/catchmate/domain/board/repository/BoardRepositoryImpl.java b/src/main/java/com/back/catchmate/domain/board/repository/BoardRepositoryImpl.java index e30dc09..ad2baec 100644 --- a/src/main/java/com/back/catchmate/domain/board/repository/BoardRepositoryImpl.java +++ b/src/main/java/com/back/catchmate/domain/board/repository/BoardRepositoryImpl.java @@ -31,6 +31,9 @@ public Page findFilteredBoards(LocalDate gameDate, Integer maxPerson, Lon // 삭제되지 않은 게시글만 조회 builder.and(board.deletedAt.isNull()); + // 저장된 게시글만 조회 (임시 저장 X) + builder.and(board.isCompleted.isTrue()); + // 최대 인원수 필터 if (maxPerson != null) { builder.and(board.maxPerson.eq(maxPerson)); diff --git a/src/main/java/com/back/catchmate/domain/board/repository/BookMarkRepository.java b/src/main/java/com/back/catchmate/domain/board/repository/BookMarkRepository.java index 5fe7c34..c2debf7 100644 --- a/src/main/java/com/back/catchmate/domain/board/repository/BookMarkRepository.java +++ b/src/main/java/com/back/catchmate/domain/board/repository/BookMarkRepository.java @@ -3,6 +3,8 @@ import com.back.catchmate.domain.board.entity.Board; import com.back.catchmate.domain.board.entity.BookMark; import com.back.catchmate.domain.user.entity.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; @@ -11,4 +13,6 @@ public interface BookMarkRepository extends JpaRepository { boolean existsByUserAndBoard(User user, Board board); Optional findByUserIdAndBoardId(Long userId, Long boardId); + + Page findAllByUserIdAndDeletedAtIsNull(Long userId, Pageable pageable); } diff --git a/src/main/java/com/back/catchmate/domain/board/service/BoardService.java b/src/main/java/com/back/catchmate/domain/board/service/BoardService.java index 27d87f7..32e6d8d 100644 --- a/src/main/java/com/back/catchmate/domain/board/service/BoardService.java +++ b/src/main/java/com/back/catchmate/domain/board/service/BoardService.java @@ -1,8 +1,7 @@ package com.back.catchmate.domain.board.service; import com.back.catchmate.domain.board.dto.BoardRequest.CreateBoardRequest; -import com.back.catchmate.domain.board.dto.BoardRequest.*; -import com.back.catchmate.domain.board.dto.BoardResponse; +import com.back.catchmate.domain.board.dto.BoardRequest.UpdateBoardRequest; import com.back.catchmate.domain.board.dto.BoardResponse.BoardDeleteInfo; import com.back.catchmate.domain.board.dto.BoardResponse.BoardInfo; import com.back.catchmate.domain.board.dto.BoardResponse.PagedBoardInfo; diff --git a/src/main/java/com/back/catchmate/domain/board/service/BoardServiceImpl.java b/src/main/java/com/back/catchmate/domain/board/service/BoardServiceImpl.java index a1b012a..d64ea52 100644 --- a/src/main/java/com/back/catchmate/domain/board/service/BoardServiceImpl.java +++ b/src/main/java/com/back/catchmate/domain/board/service/BoardServiceImpl.java @@ -97,7 +97,7 @@ public PagedBoardInfo getBoardList(Long userId, LocalDate gameStartDate, Integer .orElseThrow(() -> new BaseException(ErrorCode.USER_NOT_FOUND)); Page boardList = boardRepository.findFilteredBoards(gameStartDate, maxPerson, preferredTeamId, pageable); - return boardConverter.toPagedBoardInfo(boardList); + return boardConverter.toPagedBoardInfoFromBoardList(boardList); } @Override @@ -109,14 +109,14 @@ public PagedBoardInfo getBoardListByUserId(Long loginUserId, Long userId, Pageab User user = userRepository.findById(userId) .orElseThrow(() -> new BaseException(ErrorCode.USER_NOT_FOUND)); - Page boardList = boardRepository.findAllByUserIdAndDeletedAtIsNull(user.getId(), pageable); - return boardConverter.toPagedBoardInfo(boardList); + Page boardList = boardRepository.findAllByUserIdAndDeletedAtIsNullAndIsCompletedIsTrue(user.getId(), pageable); + return boardConverter.toPagedBoardInfoFromBoardList(boardList); } @Override @Transactional public BoardInfo updateBoard(Long userId, Long boardId, UpdateBoardRequest request) { - Board board = this.boardRepository.findById(boardId) + Board board = this.boardRepository.findByIdAndDeletedAtIsNull(boardId) .orElseThrow(() -> new BaseException(ErrorCode.BOARD_NOT_FOUND)); User user = this.userRepository.findById(userId) diff --git a/src/main/java/com/back/catchmate/domain/board/service/BookMarkService.java b/src/main/java/com/back/catchmate/domain/board/service/BookMarkService.java index 8fd7be0..3759853 100644 --- a/src/main/java/com/back/catchmate/domain/board/service/BookMarkService.java +++ b/src/main/java/com/back/catchmate/domain/board/service/BookMarkService.java @@ -1,9 +1,14 @@ package com.back.catchmate.domain.board.service; import com.back.catchmate.global.dto.StateResponse; +import org.springframework.data.domain.Pageable; + +import static com.back.catchmate.domain.board.dto.BoardResponse.*; public interface BookMarkService { StateResponse addBookMark(Long userId, Long boardId); + PagedBoardInfo getBookMarkBoardList(Long userId, Pageable pageable); + StateResponse removeBookMark(Long userId, Long boardId); } diff --git a/src/main/java/com/back/catchmate/domain/board/service/BookMarkServiceImpl.java b/src/main/java/com/back/catchmate/domain/board/service/BookMarkServiceImpl.java index 57cd1a3..cf06b75 100644 --- a/src/main/java/com/back/catchmate/domain/board/service/BookMarkServiceImpl.java +++ b/src/main/java/com/back/catchmate/domain/board/service/BookMarkServiceImpl.java @@ -1,6 +1,8 @@ package com.back.catchmate.domain.board.service; +import com.back.catchmate.domain.board.converter.BoardConverter; import com.back.catchmate.domain.board.converter.BookMarkConverter; +import com.back.catchmate.domain.board.dto.BoardResponse.PagedBoardInfo; import com.back.catchmate.domain.board.entity.Board; import com.back.catchmate.domain.board.entity.BookMark; import com.back.catchmate.domain.board.repository.BoardRepository; @@ -11,6 +13,8 @@ import com.back.catchmate.global.error.ErrorCode; import com.back.catchmate.global.error.exception.BaseException; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,6 +25,7 @@ public class BookMarkServiceImpl implements BookMarkService { private final UserRepository userRepository; private final BoardRepository boardRepository; private final BookMarkConverter bookMarkConverter; + private final BoardConverter boardConverter; @Override @Transactional @@ -31,8 +36,13 @@ public StateResponse addBookMark(Long userId, Long boardId) { Board board = boardRepository.findById(boardId) .orElseThrow(() -> new BaseException(ErrorCode.BOARD_NOT_FOUND)); + // 본인의 게시글인지 확인 + if (user.isDifferentUserFrom(board.getUser())) { + throw new BaseException(ErrorCode.ALREADY_BOOKMARK); + } + if (bookMarkRepository.existsByUserAndBoard(user, board)) { - throw new BaseException(ErrorCode.USER_NOT_FOUND); + throw new BaseException(ErrorCode.ALREADY_BOOKMARK); } BookMark bookMark = bookMarkConverter.toEntity(user, board); @@ -40,6 +50,16 @@ public StateResponse addBookMark(Long userId, Long boardId) { return new StateResponse(true); } + @Override + @Transactional(readOnly = true) + public PagedBoardInfo getBookMarkBoardList(Long userId, Pageable pageable) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new BaseException(ErrorCode.USER_NOT_FOUND)); + + Page bookMarkList = bookMarkRepository.findAllByUserIdAndDeletedAtIsNull(user.getId(), pageable); + return boardConverter.toPagedBoardInfoFromBookMarkList(bookMarkList); + } + @Override @Transactional public StateResponse removeBookMark(Long userId, Long boardId) { diff --git a/src/main/java/com/back/catchmate/global/error/ErrorCode.java b/src/main/java/com/back/catchmate/global/error/ErrorCode.java index bb45891..35d5b67 100644 --- a/src/main/java/com/back/catchmate/global/error/ErrorCode.java +++ b/src/main/java/com/back/catchmate/global/error/ErrorCode.java @@ -34,6 +34,7 @@ public enum ErrorCode { INVALID_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED, "유효하지 않은 리프레시 토큰입니다."), ALREADY_BOOKMARK(HttpStatus.BAD_REQUEST, "이미 찜한 게시글입니다."), BOOKMARK_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 찜입니다."), + BOOKMARK_BAD_REQUEST(HttpStatus.BAD_REQUEST, "본인 게시글은 찜할 수 없습니다."), // 알림 NOTIFICATION_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 알림입니다."),