@@ -4,17 +4,18 @@ import org.springframework.data.domain.Page
44import org.springframework.data.domain.Pageable
55import org.springframework.stereotype.Service
66import org.yapp.apis.auth.dto.request.UserBooksByIsbnsRequest
7+ import org.yapp.apis.book.dto.request.UpsertUserBookRequest
78import org.yapp.apis.book.dto.response.UserBookPageResponse
89import org.yapp.apis.book.dto.response.UserBookResponse
9- import org.yapp.apis.book.dto.request.UpsertUserBookRequest
1010import org.yapp.apis.book.exception.UserBookErrorCode
1111import org.yapp.apis.book.exception.UserBookNotFoundException
12+ import org.yapp.apis.home.dto.response.UserHomeResponse
1213import org.yapp.domain.userbook.BookStatus
1314import org.yapp.domain.userbook.UserBook
1415import org.yapp.domain.userbook.UserBookDomainService
1516import org.yapp.domain.userbook.UserBookSortType
16- import java.util.UUID
17-
17+ import org.yapp.domain.userbook.vo.UserBookWithLastRecordVO
18+ import java.util.*
1819
1920@Service
2021class UserBookService (
@@ -42,7 +43,6 @@ class UserBookService(
4243 )
4344 }
4445
45-
4646 fun findAllByUserIdAndBookIsbnIn (userBooksByIsbnsRequest : UserBooksByIsbnsRequest ): List <UserBookResponse > {
4747 val userBooks = userBookDomainService.findAllByUserIdAndBookIsbnIn(
4848 userBooksByIsbnsRequest.validUserId(),
@@ -51,6 +51,55 @@ class UserBookService(
5151 return userBooks.map { UserBookResponse .from(it) }
5252 }
5353
54+ fun findRecentReadingBooksForHome (userId : UUID , limit : Int ): UserHomeResponse {
55+ val fetchLimit = maxOf(limit * 2 , 10 )
56+ val allUserBookVoInfos = userBookDomainService.findRecentReadingBooksWithLastRecord(userId, fetchLimit)
57+ val selectedBooks = selectBooksByPriority(allUserBookVoInfos, limit)
58+
59+ return UserHomeResponse .from(selectedBooks)
60+ }
61+
62+ private fun selectBooksByPriority (
63+ allBooks : List <UserBookWithLastRecordVO >,
64+ targetLimit : Int
65+ ): List <UserBookWithLastRecordVO > {
66+ if (allBooks.isEmpty()) return emptyList()
67+
68+ val result = mutableListOf<UserBookWithLastRecordVO >()
69+ val usedBookIds = mutableSetOf<UUID >()
70+
71+ val readingBooks = allBooks
72+ .filter { it.status == BookStatus .READING }
73+ .sortedByDescending { it.lastRecordedAt }
74+
75+ val readingSelected = readingBooks.take(targetLimit)
76+ result.addAll(readingSelected)
77+ usedBookIds.addAll(readingSelected.map { it.id.value })
78+
79+ if (result.size < targetLimit) {
80+ val remainingSlots = targetLimit - result.size
81+ val completedBooks = allBooks
82+ .filter { it.status == BookStatus .COMPLETED && ! usedBookIds.contains(it.id.value) }
83+ .sortedByDescending { it.lastRecordedAt }
84+
85+ val completedSelected = completedBooks.take(remainingSlots)
86+ result.addAll(completedSelected)
87+ usedBookIds.addAll(completedSelected.map { it.id.value })
88+ }
89+
90+ if (result.size < targetLimit) {
91+ val remainingSlots = targetLimit - result.size
92+ val remainingBooks = allBooks
93+ .filter { ! usedBookIds.contains(it.id.value) }
94+ .sortedByDescending { it.lastRecordedAt }
95+
96+ val remainingSelected = remainingBooks.take(remainingSlots)
97+ result.addAll(remainingSelected)
98+ }
99+
100+ return result
101+ }
102+
54103 private fun findUserBooksByDynamicCondition (
55104 userId : UUID ,
56105 status : BookStatus ? ,
0 commit comments