diff --git a/backend/src/main/java/com/example/booktree/domain/book/controller/BookController.java b/backend/src/main/java/com/example/booktree/domain/book/controller/BookController.java index 6951808..c008da2 100644 --- a/backend/src/main/java/com/example/booktree/domain/book/controller/BookController.java +++ b/backend/src/main/java/com/example/booktree/domain/book/controller/BookController.java @@ -2,22 +2,31 @@ import com.example.booktree.domain.book.dto.request.BookRequestDto; +import com.example.booktree.domain.book.dto.request.BookUpdateRequestDto; import com.example.booktree.domain.book.dto.response.BookResponseDto; +import com.example.booktree.domain.book.entity.Book; import com.example.booktree.domain.book.service.BookService; import com.example.booktree.global.utils.dto.ApiResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @@ -53,6 +62,28 @@ public ResponseEntity getBookById(@Valid @PathVariable Long bookId) { return ResponseEntity.ok(apiResponse); } + @GetMapping + @Operation( + summary = "사용자가 보유한 모든 책 조회 ", + description = "유저가 보유한 모든 책을 조회 합니다. " + ) + @PreAuthorize("hasAnyRole('USER','ADMIN')") + public ResponseEntity getBookListById( @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "10") int size) { + // ✅ 생성일 기준 내림차순 정렬 + Pageable pageable = PageRequest.of(page-1, size, Sort.by(Sort.Direction.DESC, "createdAt")); + Page bookList = bookService.getBookList(pageable); + Page bookResponseDto = bookList.map(BookResponseDto::new); + ApiResponse apiResponse = ApiResponse.of(HttpStatus.OK.value(),"모든 책 조회 성공",bookResponseDto); + return ResponseEntity.ok(apiResponse); + } + + + + + + + diff --git a/backend/src/main/java/com/example/booktree/domain/book/dto/request/BookUpdateRequestDto.java b/backend/src/main/java/com/example/booktree/domain/book/dto/request/BookUpdateRequestDto.java new file mode 100644 index 0000000..143b47e --- /dev/null +++ b/backend/src/main/java/com/example/booktree/domain/book/dto/request/BookUpdateRequestDto.java @@ -0,0 +1,32 @@ +package com.example.booktree.domain.book.dto.request; + +import com.example.booktree.enums.TransactionStatus; +import com.example.booktree.enums.TransactionType; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; +import org.springframework.web.multipart.MultipartFile; + +@Getter +@Setter +public class BookUpdateRequestDto { + + @NotNull + private Long mainCategoryId; + + @NotBlank + @NotNull + private String name; + + @NotNull + private String author; + + @NotNull + private TransactionType transactionType; + + private MultipartFile image; + + private TransactionStatus transactionStatus; + +} diff --git a/backend/src/main/java/com/example/booktree/domain/book/repository/BookRepository.java b/backend/src/main/java/com/example/booktree/domain/book/repository/BookRepository.java index 1a0fee6..e722c3a 100644 --- a/backend/src/main/java/com/example/booktree/domain/book/repository/BookRepository.java +++ b/backend/src/main/java/com/example/booktree/domain/book/repository/BookRepository.java @@ -1,11 +1,15 @@ package com.example.booktree.domain.book.repository; import com.example.booktree.domain.book.entity.Book; +import com.example.booktree.domain.user.entity.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface BookRepository extends JpaRepository { + Page findAllByUser(User user, Pageable pageable); } diff --git a/backend/src/main/java/com/example/booktree/domain/book/service/BookService.java b/backend/src/main/java/com/example/booktree/domain/book/service/BookService.java index c222dd2..d133655 100644 --- a/backend/src/main/java/com/example/booktree/domain/book/service/BookService.java +++ b/backend/src/main/java/com/example/booktree/domain/book/service/BookService.java @@ -2,6 +2,7 @@ import com.example.booktree.domain.book.dto.request.BookRequestDto; +import com.example.booktree.domain.book.dto.request.BookUpdateRequestDto; import com.example.booktree.domain.book.entity.Book; import com.example.booktree.domain.book.repository.BookRepository; import com.example.booktree.domain.maincategory.entity.MainCategory; @@ -14,8 +15,12 @@ import com.example.booktree.global.exception.ExceptionCode; import com.example.booktree.global.image.service.ImageService; import com.example.booktree.global.security.jwt.service.TokenService; +import java.util.List; +import java.util.Optional; 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 org.springframework.transaction.annotation.Transactional; @@ -57,6 +62,13 @@ public Book getBookById(Long bookId){ } + public Page getBookList(Pageable pageable){ + User user = userService.findById(tokenService.getIdFromToken()); + return bookRepository.findAllByUser(user,pageable); + } + + + } diff --git a/backend/src/main/java/com/example/booktree/global/exception/ExceptionCode.java b/backend/src/main/java/com/example/booktree/global/exception/ExceptionCode.java index 936beb5..c9af19c 100644 --- a/backend/src/main/java/com/example/booktree/global/exception/ExceptionCode.java +++ b/backend/src/main/java/com/example/booktree/global/exception/ExceptionCode.java @@ -33,9 +33,12 @@ public enum ExceptionCode { BLOG_NOT_OWNER(403, "해당 블로그의 소유자가 아닙니다."), MAIN_CATEGORY_NOT_FOUND(404, "메인 카테고리가 존재하지 않습니다."), EMAIL_TYPE_NOT_FOUND(404, "이메일 타입이 존재하지 않습니다"), - INVALID_CONTENT_PARTS(404, "게시글의 내용 이미지와 글의 조합이 유효하지 않습니다."); + INVALID_CONTENT_PARTS(404, "게시글의 내용 이미지와 글의 조합이 유효하지 않습니다."), + + + //책 + BOOK_NOT_FOUNT(404, "존재하지 않는 책입니다. "); - // BOARD_NOT_FOUND(404, "Board not found"), // USER_NOT_FOUND(404, "User not found"), diff --git a/backend/src/test/java/com/example/booktree/domain/book/service/BookServiceTest.java b/backend/src/test/java/com/example/booktree/domain/book/service/BookServiceTest.java index b4f341d..354e9ed 100644 --- a/backend/src/test/java/com/example/booktree/domain/book/service/BookServiceTest.java +++ b/backend/src/test/java/com/example/booktree/domain/book/service/BookServiceTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -22,6 +23,7 @@ import com.example.booktree.global.exception.ExceptionCode; import com.example.booktree.global.image.service.ImageService; import com.example.booktree.global.security.jwt.service.TokenService; +import java.util.List; import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -30,6 +32,11 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.annotation.Transactional; @@ -69,7 +76,7 @@ void createBook_shouldCreateBookSuccessfully(){ dto.setAuthor("테스트 저자"); dto.setTransactionType(TransactionType.SELL); - // 이미지 파일은 MultipartFile이라서 보통 MockMultipartFile로 만듦 (필요한 경우) + // 이미지 파일은 MultipartFile이라서 보통 MockMultipartFile로 만듦 MockMultipartFile mockImage = new MockMultipartFile( "image", "test-image.jpg", @@ -138,5 +145,4 @@ void getBookById_shouldThrowException_whenBookNotFound() { assertEquals(ExceptionCode.BOOK_NOT_FOUND, exception.getExceptionCode()); } - }