Skip to content

Commit

Permalink
refactor: bookshelf service with component
Browse files Browse the repository at this point in the history
  • Loading branch information
geneaky committed Jan 9, 2024
1 parent 61c824b commit 0475c19
Show file tree
Hide file tree
Showing 12 changed files with 281 additions and 251 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package toy.bookchat.bookchat.domain.book.service;

import java.time.LocalDate;
import org.springframework.stereotype.Component;
import toy.bookchat.bookchat.domain.book.Book;
import toy.bookchat.bookchat.domain.book.repository.BookRepository;

@Component
public class BookReader {

private final BookRepository bookRepository;

public BookReader(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}

public Book readBook(String isbn, LocalDate publishAt, Book book) {
return bookRepository.findByIsbnAndPublishAt(isbn, publishAt)
.orElseGet(() -> bookRepository.save(book));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,46 @@

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import toy.bookchat.bookchat.domain.agony.repository.AgonyRecordRepository;
import toy.bookchat.bookchat.domain.agony.repository.AgonyRepository;
import toy.bookchat.bookchat.domain.bookshelf.BookReport;
import toy.bookchat.bookchat.domain.bookshelf.BookShelf;
import toy.bookchat.bookchat.domain.bookshelf.repository.BookReportRepository;
import toy.bookchat.bookchat.domain.bookshelf.repository.BookShelfRepository;

@Component
public class BookShelfManager {

private final BookShelfRepository bookShelfRepository;
private final BookReportRepository bookReportRepository;
private final AgonyRepository agonyRepository;
private final AgonyRecordRepository agonyRecordRepository;

public BookShelfManager(BookReportRepository bookReportRepository) {

public BookShelfManager(BookReportRepository bookReportRepository, BookShelfRepository bookShelfRepository, AgonyRepository agonyRepository, AgonyRecordRepository agonyRecordRepository) {
this.bookReportRepository = bookReportRepository;
this.bookShelfRepository = bookShelfRepository;
this.agonyRepository = agonyRepository;
this.agonyRecordRepository = agonyRecordRepository;
}

@Transactional
public void append(BookShelf bookShelf, BookReport bookReport) {
bookReportRepository.save(bookReport);
bookShelf.writeReportInStateOfCompleteReading(bookReport);
}

public void store(BookShelf bookShelf) {
bookShelfRepository.save(bookShelf);
}

public void vacate(Long bookShelfId, Long userId) {
agonyRecordRepository.deleteByBookShelfIdAndUserId(bookShelfId, userId);
agonyRepository.deleteByBookShelfIdAndUserId(bookShelfId, userId);
bookShelfRepository.deleteBookShelfByIdAndUserId(bookShelfId, userId);
}

public void remove(Long userId) {
bookShelfRepository.deleteAllByUserId(userId);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package toy.bookchat.bookchat.domain.bookshelf.service;

import java.time.LocalDate;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import toy.bookchat.bookchat.domain.bookshelf.BookShelf;
import toy.bookchat.bookchat.domain.bookshelf.ReadingStatus;
import toy.bookchat.bookchat.domain.bookshelf.repository.BookShelfRepository;
import toy.bookchat.bookchat.exception.notfound.book.BookNotFoundException;

Expand All @@ -20,4 +24,14 @@ public BookShelf readBookShelf(Long bookShelfId, Long userId) {
return bookShelfRepository.findByIdAndUserId(bookShelfId, userId)
.orElseThrow(BookNotFoundException::new);
}


public Page<BookShelf> readBookShelf(Long userId, ReadingStatus readingStatus, Pageable pageable) {
return bookShelfRepository.findSpecificStatusBookByUserId(readingStatus, pageable, userId);
}

public BookShelf readBookShelf(Long userId, String isbn, LocalDate publishAt) {
return bookShelfRepository.findByUserIdAndIsbnAndPublishAt(userId, isbn, publishAt)
.orElseThrow(BookNotFoundException::new);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,108 +5,64 @@
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import toy.bookchat.bookchat.domain.agony.repository.AgonyRecordRepository;
import toy.bookchat.bookchat.domain.agony.repository.AgonyRepository;
import toy.bookchat.bookchat.domain.book.Book;
import toy.bookchat.bookchat.domain.book.repository.BookRepository;
import toy.bookchat.bookchat.domain.book.service.BookReader;
import toy.bookchat.bookchat.domain.bookshelf.BookShelf;
import toy.bookchat.bookchat.domain.bookshelf.ReadingStatus;
import toy.bookchat.bookchat.domain.bookshelf.repository.BookShelfRepository;
import toy.bookchat.bookchat.domain.bookshelf.service.dto.request.BookShelfRequest;
import toy.bookchat.bookchat.domain.bookshelf.service.dto.request.ReviseBookShelfRequest;
import toy.bookchat.bookchat.domain.bookshelf.service.dto.response.ExistenceBookOnBookShelfResponse;
import toy.bookchat.bookchat.domain.bookshelf.service.dto.response.SearchBookShelfByReadingStatus;
import toy.bookchat.bookchat.domain.user.User;
import toy.bookchat.bookchat.domain.user.repository.UserRepository;
import toy.bookchat.bookchat.exception.notfound.book.BookNotFoundException;
import toy.bookchat.bookchat.exception.notfound.user.UserNotFoundException;
import toy.bookchat.bookchat.domain.user.service.UserReader;

@Service
@Transactional(readOnly = true)
public class BookShelfService {

private final BookShelfRepository bookShelfRepository;
private final AgonyRepository agonyRepository;
private final AgonyRecordRepository agonyRecordRepository;
private final BookRepository bookRepository;
private final UserRepository userRepository;
private final BookShelfManager bookShelfManager;
private final BookShelfReader bookShelfReader;
private final BookReader bookReader;
private final UserReader userReader;

public BookShelfService(BookShelfRepository bookShelfRepository,
AgonyRepository agonyRepository, AgonyRecordRepository agonyRecordRepository,
BookRepository bookRepository,
UserRepository userRepository) {
this.bookShelfRepository = bookShelfRepository;
this.agonyRepository = agonyRepository;
this.agonyRecordRepository = agonyRecordRepository;
this.bookRepository = bookRepository;
this.userRepository = userRepository;
public BookShelfService(UserReader userReader, BookShelfManager bookShelfManager, BookShelfReader bookShelfReader, BookReader bookReader) {
this.userReader = userReader;
this.bookShelfManager = bookShelfManager;
this.bookShelfReader = bookShelfReader;
this.bookReader = bookReader;
}

@Transactional
public void putBookOnBookShelf(BookShelfRequest bookShelfRequest, Long userId) {
Book book = bookRepository.findByIsbnAndPublishAt(bookShelfRequest.getIsbn(),
bookShelfRequest.getPublishAt())
.orElseGet(() -> bookRepository.save(bookShelfRequest.extractBookEntity()));
User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new);

bookShelfRepository.save(createBookShelfByReadingStatus(bookShelfRequest, book, user));
}

private BookShelf createBookShelfByReadingStatus(BookShelfRequest bookShelfRequest,
Book book, User user) {
if (bookShelfRequest.isCompleteReading()) {
return BookShelf.builder()
.book(book)
.readingStatus(bookShelfRequest.getReadingStatus())
.user(user)
.star(bookShelfRequest.getStar())
.build();
}
return BookShelf.builder()
.book(book)
.readingStatus(bookShelfRequest.getReadingStatus())
.user(user)
.build();
Book book = bookReader.readBook(bookShelfRequest.getIsbn(), bookShelfRequest.getPublishAt(), bookShelfRequest.extractBookEntity());
User user = userReader.readUser(userId);
bookShelfManager.store(bookShelfRequest.createBookShelfByReadingStatus(book, user));
}

@Transactional(readOnly = true)
public SearchBookShelfByReadingStatus takeBooksOutOfBookShelves(ReadingStatus readingStatus,
Pageable pageable, Long userId) {
Page<BookShelf> pagingBookShelves = bookShelfRepository.findSpecificStatusBookByUserId(
readingStatus, pageable,
userId);

public SearchBookShelfByReadingStatus takeBooksOutOfBookShelves(ReadingStatus readingStatus, Pageable pageable, Long userId) {
Page<BookShelf> pagingBookShelves = bookShelfReader.readBookShelf(userId, readingStatus, pageable);
return new SearchBookShelfByReadingStatus(pagingBookShelves);
}

@Transactional(readOnly = true)
public ExistenceBookOnBookShelfResponse getBookIfExisted(String isbn,
LocalDate publishAt, Long userId) {
BookShelf bookShelf = bookShelfRepository.findByUserIdAndIsbnAndPublishAt(userId, isbn,
publishAt)
.orElseThrow(BookNotFoundException::new);

public ExistenceBookOnBookShelfResponse getBookIfExisted(String isbn, LocalDate publishAt, Long userId) {
BookShelf bookShelf = bookShelfReader.readBookShelf(userId, isbn, publishAt);
return ExistenceBookOnBookShelfResponse.from(bookShelf);
}

@Transactional
public void reviseBookShelf(Long bookShelfId, ReviseBookShelfRequest reviseBookShelfRequest,
Long userId) {
BookShelf bookShelf = bookShelfRepository.findByIdAndUserId(bookShelfId, userId)
.orElseThrow(BookNotFoundException::new);

public void reviseBookShelf(Long bookShelfId, ReviseBookShelfRequest reviseBookShelfRequest, Long userId) {
BookShelf bookShelf = bookShelfReader.readBookShelf(bookShelfId, userId);
reviseBookShelfRequest.applyChanges(bookShelf);
}

@Transactional
public void deleteBookShelf(Long bookShelfId, Long userId) {
agonyRecordRepository.deleteByBookShelfIdAndUserId(bookShelfId, userId);
agonyRepository.deleteByBookShelfIdAndUserId(bookShelfId, userId);
bookShelfRepository.deleteBookShelfByIdAndUserId(bookShelfId, userId);
bookShelfManager.vacate(bookShelfId, userId);
}

@Transactional
public void deleteAllUserBookShelves(Long userId) {
bookShelfRepository.deleteAllByUserId(userId);
bookShelfManager.remove(userId);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import toy.bookchat.bookchat.domain.book.Book;
import toy.bookchat.bookchat.domain.bookshelf.BookShelf;
import toy.bookchat.bookchat.domain.bookshelf.ReadingStatus;
import toy.bookchat.bookchat.domain.bookshelf.Star;
import toy.bookchat.bookchat.domain.user.User;

@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
Expand Down Expand Up @@ -61,4 +63,20 @@ public String getIsbn() {
public LocalDate getPublishAt() {
return this.bookRequest.getPublishAt();
}

public BookShelf createBookShelfByReadingStatus(Book book, User user) {
if (this.isCompleteReading()) {
return BookShelf.builder()
.book(book)
.readingStatus(this.getReadingStatus())
.user(user)
.star(this.getStar())
.build();
}
return BookShelf.builder()
.book(book)
.readingStatus(this.getReadingStatus())
.user(user)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ private ExistenceBookOnBookShelfResponse(Long bookShelfId,
}

public static ExistenceBookOnBookShelfResponse from(BookShelf bookShelf) {
return new ExistenceBookOnBookShelfResponse(bookShelf.getId(),
bookShelf.getReadingStatus());
return new ExistenceBookOnBookShelfResponse(bookShelf.getId(), bookShelf.getReadingStatus());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package toy.bookchat.bookchat.domain.user.service;

import org.springframework.stereotype.Component;
import toy.bookchat.bookchat.domain.user.User;
import toy.bookchat.bookchat.domain.user.repository.UserRepository;
import toy.bookchat.bookchat.exception.notfound.user.UserNotFoundException;

@Component
public class UserReader {

private final UserRepository userRepository;

public UserReader(UserRepository userRepository) {
this.userRepository = userRepository;
}

public User readUser(Long userId) {
return userRepository.findById(userId).orElseThrow(UserNotFoundException::new);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package toy.bookchat.bookchat.domain.book.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;

import java.time.LocalDate;
import java.util.Optional;
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 toy.bookchat.bookchat.domain.book.Book;
import toy.bookchat.bookchat.domain.book.repository.BookRepository;

@ExtendWith(MockitoExtension.class)
class BookReaderTest {

@Mock
private BookRepository bookRepository;
@InjectMocks
private BookReader bookReader;

@Test
void isbn_출판일과_일치하는_책이있다면_조회한다() throws Exception {
Book book = Book.builder().build();
given(bookRepository.findByIsbnAndPublishAt(any(), any())).willReturn(Optional.of(book));
Book readBook = bookReader.readBook("G5J5X8U", LocalDate.now(), null);

assertThat(readBook).isEqualTo(book);
}

@Test
void isbn_출판일과_일치하는_책이없다면_신규등록후_반환한다() throws Exception {
Book book = Book.builder().build();
given(bookRepository.save(any())).willReturn(book);
Book readBook = bookReader.readBook("G5J5X8U", LocalDate.now(), null);

assertThat(readBook).isEqualTo(book);
}
}
Loading

0 comments on commit 0475c19

Please sign in to comment.