Skip to content

Commit

Permalink
feat: 책 관련된 토크룸 조회 API 구현 (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
jwooo committed Apr 7, 2024
1 parent 629b969 commit e5db643
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 4 deletions.
13 changes: 12 additions & 1 deletion src/main/java/com/jisungin/api/book/BookController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import com.jisungin.api.ApiResponse;
import com.jisungin.api.book.request.BookCreateRequest;
import com.jisungin.api.book.request.BookPageRequest;
import com.jisungin.api.oauth.Auth;
import com.jisungin.application.PageResponse;
import com.jisungin.application.book.BestSellerService;
import com.jisungin.application.book.BookService;
import com.jisungin.application.book.response.BestSellerResponse;
import com.jisungin.application.book.response.BookRelatedTalkRoomPageResponse;
import com.jisungin.application.book.response.BookResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
Expand All @@ -31,9 +33,18 @@ public ApiResponse<BookResponse> getBook(@PathVariable("isbn") String isbn) {
return ApiResponse.ok(bookService.getBook(isbn));
}

@GetMapping("/books/{isbn}/talk-rooms")
public ApiResponse<BookRelatedTalkRoomPageResponse> getTalkRoomsByRelatedBook(
@PathVariable("isbn") String isbn,
@ModelAttribute BookPageRequest request,
@Auth Long userId
) {
return ApiResponse.ok(bookService.getBookRelatedTalkRooms(isbn, request.toService(), userId));
}

@GetMapping("/books/best-seller")
public ApiResponse<PageResponse<BestSellerResponse>> getBestSellers(@ModelAttribute BookPageRequest page) {
return ApiResponse.ok(bestSellerService.getBestSellers(page.toServiceRequest()));
return ApiResponse.ok(bestSellerService.getBestSellers(page.toService()));
}

@PostMapping("/books")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
@NoArgsConstructor
public class BookPageRequest {

Integer page;
Integer size;
private Integer page;
private Integer size;

@Builder
private BookPageRequest(Integer page, Integer size) {
this.page = page != null ? page : 1;
this.size = size != null ? size : 5;
}

public BookServicePageRequest toServiceRequest() {
public BookServicePageRequest toService() {
return BookServicePageRequest.builder()
.page(page)
.size(size)
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/jisungin/application/PageResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,12 @@ public void addContents(List<Long> contents) {
this.likeContents = contents;
}

public static <T> PageResponse <T> of(int size, long totalCount, List<T> queryResponse) {
return PageResponse.<T>builder()
.size(size)
.totalCount(totalCount)
.queryResponse(queryResponse)
.build();
}

}
45 changes: 45 additions & 0 deletions src/main/java/com/jisungin/application/book/BookService.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
package com.jisungin.application.book;

import com.jisungin.application.PageResponse;
import com.jisungin.application.book.request.BookCreateServiceRequest;
import com.jisungin.application.book.request.BookServicePageRequest;
import com.jisungin.application.book.response.BookRelatedTalkRoomPageResponse;
import com.jisungin.application.book.response.BookRelatedTalkRoomResponse;
import com.jisungin.application.book.response.BookResponse;
import com.jisungin.application.talkroom.response.TalkRoomQueryResponse;
import com.jisungin.domain.ReadingStatus;
import com.jisungin.domain.book.Book;
import com.jisungin.domain.book.repository.BookRepository;
import com.jisungin.domain.review.repository.ReviewRepository;
import com.jisungin.domain.talkroom.repository.TalkRoomRepository;
import com.jisungin.domain.talkroom.repository.TalkRoomRoleRepository;
import com.jisungin.domain.talkroomlike.repository.TalkRoomLikeRepository;
import com.jisungin.exception.BusinessException;
import com.jisungin.exception.ErrorCode;
import com.jisungin.infra.crawler.Crawler;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -20,6 +31,9 @@ public class BookService {

private final Crawler crawler;
private final BookRepository bookRepository;
private final TalkRoomRepository talkRoomRepository;
private final TalkRoomRoleRepository talkRoomRoleRepository;
private final TalkRoomLikeRepository talkRoomLikeRepository;
private final ReviewRepository reviewRepository;

public BookResponse getBook(String isbn) {
Expand All @@ -31,6 +45,31 @@ public BookResponse getBook(String isbn) {
return BookResponse.of(book, averageRating);
}

public BookRelatedTalkRoomPageResponse getBookRelatedTalkRooms(String isbn, BookServicePageRequest request,
Long userId
) {
Book book = bookRepository.findById(isbn)
.orElseThrow(() -> new BusinessException(ErrorCode.BOOK_NOT_FOUND));

List<TalkRoomQueryResponse> talkRooms = talkRoomRepository.findTalkRoomsRelatedBook(book.getIsbn(),
request.getOffset(), request.getSize());

List<Long> talkRoomIds = extractTalkRoomIds(talkRooms);

Map<Long, List<ReadingStatus>> readingStatuses = talkRoomRoleRepository.findTalkRoomRoleByIds(talkRoomIds);

List<BookRelatedTalkRoomResponse> responses = BookRelatedTalkRoomResponse.create(talkRooms, readingStatuses);

long totalCount = talkRoomRepository.countTalkRoomsRelatedBook(isbn);

List<Long> likeTalkRoomIds = (userId != null)
? talkRoomLikeRepository.findLikeTalkRoomIdsByUserId(userId, talkRoomIds)
: Collections.emptyList();

return BookRelatedTalkRoomPageResponse.of(PageResponse.of(request.getSize(), totalCount, responses),
likeTalkRoomIds);
}

@Transactional
public BookResponse createBook(BookCreateServiceRequest request) {
if (bookRepository.existsBookByIsbn(request.getIsbn())) {
Expand All @@ -50,4 +89,10 @@ public void addNewBooks(List<BookCreateServiceRequest> requests) {
.forEach(bookRepository::save);
}

private List<Long> extractTalkRoomIds(List<TalkRoomQueryResponse> talkRooms) {
return talkRooms.stream()
.map(TalkRoomQueryResponse::getId)
.toList();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ public Integer extractEndIndex() {
return page * size;
}

public long getOffset() {
return (long) (Math.max(1, this.page) - 1) * Math.min(this.size, 2000);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.jisungin.application.book.response;

import com.jisungin.application.PageResponse;
import java.util.ArrayList;
import java.util.List;
import lombok.Builder;
import lombok.Getter;

@Getter
public class BookRelatedTalkRoomPageResponse {

PageResponse<BookRelatedTalkRoomResponse> response;
List<Long> userLikeTalkRoomIds = new ArrayList<>();

@Builder
private BookRelatedTalkRoomPageResponse(PageResponse<BookRelatedTalkRoomResponse> response,
List<Long> userLikeTalkRoomIds) {
this.response = response;
this.userLikeTalkRoomIds = userLikeTalkRoomIds;
}

public static BookRelatedTalkRoomPageResponse of(PageResponse<BookRelatedTalkRoomResponse> response,
List<Long> userLikeTalkRoomIds) {
return BookRelatedTalkRoomPageResponse.builder()
.response(response)
.userLikeTalkRoomIds(userLikeTalkRoomIds)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.jisungin.application.book.response;

import com.jisungin.application.talkroom.response.TalkRoomQueryResponse;
import com.jisungin.domain.ReadingStatus;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import lombok.Builder;
import lombok.Getter;

@Getter
public class BookRelatedTalkRoomResponse {

private Long id;
private String profileImage;
private String username;
private String title;
private String bookName;
private String bookThumbnail;
private Long likeCount;
private List<String> readingStatuses = new ArrayList<>();

@Builder
public BookRelatedTalkRoomResponse(Long id, String profileImage, String username, String title, String bookName,
String bookThumbnail, Long likeCount, List<String> readingStatuses) {
this.id = id;
this.profileImage = profileImage;
this.username = username;
this.title = title;
this.bookName = bookName;
this.bookThumbnail = bookThumbnail;
this.likeCount = likeCount;
this.readingStatuses = readingStatuses;
}

public static List<BookRelatedTalkRoomResponse> create(List<TalkRoomQueryResponse> talkRooms,
Map<Long, List<ReadingStatus>> readingStatuses) {
return talkRooms.stream()
.map(talkRoom -> {
List<String> talkRoomReadingStatus = extractReadingStatuses(readingStatuses, talkRoom);

return BookRelatedTalkRoomResponse.builder()
.id(talkRoom.getId())
.profileImage(talkRoom.getProfileImage())
.username(talkRoom.getUsername())
.title(talkRoom.getTitle())
.bookName(talkRoom.getBookName())
.bookThumbnail(talkRoom.getBookThumbnail())
.likeCount(talkRoom.getLikeCount())
.readingStatuses(talkRoomReadingStatus)
.build();
})
.toList();
}

private static List<String> extractReadingStatuses(Map<Long, List<ReadingStatus>> readingStatuses,
TalkRoomQueryResponse talkRoom) {
return readingStatuses.get(talkRoom.getId()).stream()
.map(ReadingStatus::getText)
.toList();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.jisungin.application.talkroom.response;

import com.querydsl.core.annotations.QueryProjection;
import java.time.LocalDateTime;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class TalkRoomQueryResponse {

private Long id;
private String profileImage;
private String username;
private String title;
private String content;
private String bookName;
private String bookThumbnail;
private Long likeCount;
private LocalDateTime createTime;

@Builder
@QueryProjection
public TalkRoomQueryResponse(Long id, String profileImage, String username, String title, String content,
String bookName, String bookThumbnail, Long likeCount, LocalDateTime createTime) {
this.id = id;
this.profileImage = profileImage;
this.username = username;
this.title = title;
this.content = content;
this.bookName = bookName;
this.bookThumbnail = bookThumbnail;
this.likeCount = likeCount;
this.createTime = createTime;
}

}

0 comments on commit e5db643

Please sign in to comment.