diff --git a/apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordController.kt b/apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordController.kt index 9d04735d..04111fbd 100644 --- a/apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordController.kt +++ b/apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordController.kt @@ -41,6 +41,18 @@ class ReadingRecordController( return ResponseEntity.status(HttpStatus.CREATED).body(response) } + @GetMapping("/detail/{readingRecordId}") + override fun getReadingRecordDetail( + @AuthenticationPrincipal userId: UUID, + @PathVariable readingRecordId: UUID + ): ResponseEntity { + val response = readingRecordUseCase.getReadingRecordDetail( + userId = userId, + readingRecordId = readingRecordId + ) + return ResponseEntity.ok(response) + } + @GetMapping("/{userBookId}") override fun getReadingRecords( @AuthenticationPrincipal userId: UUID, diff --git a/apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt b/apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt index 4f1644bd..b1766a75 100644 --- a/apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt +++ b/apis/src/main/kotlin/org/yapp/apis/readingrecord/controller/ReadingRecordControllerApi.kt @@ -60,6 +60,30 @@ interface ReadingRecordControllerApi { @Valid @RequestBody @Parameter(description = "독서 기록 생성 요청 객체") request: CreateReadingRecordRequest ): ResponseEntity + @Operation( + summary = "독서 기록 상세 조회", + description = "독서 기록 ID로 독서 기록 상세 정보를 조회합니다." + ) + @ApiResponses( + value = [ + ApiResponse( + responseCode = "200", + description = "독서 기록 상세 조회 성공", + content = [Content(schema = Schema(implementation = ReadingRecordResponse::class))] + ), + ApiResponse( + responseCode = "404", + description = "사용자 또는 독서 기록을 찾을 수 없음", + content = [Content(schema = Schema(implementation = ErrorResponse::class))] + ) + ] + ) + @GetMapping("/detail/{readingRecordId}") + fun getReadingRecordDetail( + @AuthenticationPrincipal @Parameter(description = "인증된 사용자 ID") userId: UUID, + @PathVariable @Parameter(description = "조회할 독서 기록 ID") readingRecordId: UUID + ): ResponseEntity + @Operation( summary = "독서 기록 목록 조회", description = "사용자의 책에 대한 독서 기록을 페이징하여 조회합니다. 정렬은 페이지 번호 또는 최신 등록순으로 가능합니다." diff --git a/apis/src/main/kotlin/org/yapp/apis/readingrecord/exception/ReadingRecordErrorCode.kt b/apis/src/main/kotlin/org/yapp/apis/readingrecord/exception/ReadingRecordErrorCode.kt new file mode 100644 index 00000000..c1181e57 --- /dev/null +++ b/apis/src/main/kotlin/org/yapp/apis/readingrecord/exception/ReadingRecordErrorCode.kt @@ -0,0 +1,16 @@ +package org.yapp.apis.readingrecord.exception + +import org.springframework.http.HttpStatus +import org.yapp.globalutils.exception.BaseErrorCode + +enum class ReadingRecordErrorCode( + private val status: HttpStatus, + private val code: String, + private val message: String +) : BaseErrorCode { + READING_RECORD_NOT_FOUND(HttpStatus.NOT_FOUND, "READING_RECORD_001", "독서 기록을 찾을 수 없습니다."); + + override fun getHttpStatus(): HttpStatus = status + override fun getCode(): String = code + override fun getMessage(): String = message +} diff --git a/apis/src/main/kotlin/org/yapp/apis/readingrecord/exception/ReadingRecordNotFoundException.kt b/apis/src/main/kotlin/org/yapp/apis/readingrecord/exception/ReadingRecordNotFoundException.kt new file mode 100644 index 00000000..91f1f359 --- /dev/null +++ b/apis/src/main/kotlin/org/yapp/apis/readingrecord/exception/ReadingRecordNotFoundException.kt @@ -0,0 +1,8 @@ +package org.yapp.apis.readingrecord.exception + +import org.yapp.globalutils.exception.CommonException + +class ReadingRecordNotFoundException( + errorCode: ReadingRecordErrorCode, + message: String? = null +) : CommonException(errorCode, message) diff --git a/apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt b/apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt index 8d0633d0..f015fd54 100644 --- a/apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt +++ b/apis/src/main/kotlin/org/yapp/apis/readingrecord/service/ReadingRecordService.kt @@ -6,6 +6,9 @@ import org.springframework.stereotype.Service import org.yapp.apis.book.service.UserBookService import org.yapp.apis.readingrecord.dto.request.CreateReadingRecordRequest import org.yapp.apis.readingrecord.dto.response.ReadingRecordResponse +import org.yapp.apis.readingrecord.exception.ReadingRecordErrorCode +import org.yapp.apis.readingrecord.exception.ReadingRecordNotFoundException +import org.yapp.domain.book.BookDomainService import org.yapp.domain.readingrecord.ReadingRecordDomainService import org.yapp.domain.readingrecord.ReadingRecordSortType import java.util.* @@ -35,6 +38,20 @@ class ReadingRecordService( return ReadingRecordResponse.from(readingRecordInfoVO) } + fun getReadingRecordDetail( + userId: UUID, + readingRecordId: UUID + ): ReadingRecordResponse { + val readingRecordInfoVO = readingRecordDomainService.findReadingRecordById(readingRecordId) + ?: throw ReadingRecordNotFoundException( + ReadingRecordErrorCode.READING_RECORD_NOT_FOUND, + "Reading record not found with id: $readingRecordId" + ) + + userBookService.validateUserBookExists(userId, readingRecordInfoVO.userBookId.value) + + return ReadingRecordResponse.from(readingRecordInfoVO) + } fun getReadingRecordsByDynamicCondition( userBookId: UUID, diff --git a/apis/src/main/kotlin/org/yapp/apis/readingrecord/usecase/ReadingRecordUseCase.kt b/apis/src/main/kotlin/org/yapp/apis/readingrecord/usecase/ReadingRecordUseCase.kt index 749f9e75..99271b5b 100644 --- a/apis/src/main/kotlin/org/yapp/apis/readingrecord/usecase/ReadingRecordUseCase.kt +++ b/apis/src/main/kotlin/org/yapp/apis/readingrecord/usecase/ReadingRecordUseCase.kt @@ -35,6 +35,18 @@ class ReadingRecordUseCase( ) } + fun getReadingRecordDetail( + userId: UUID, + readingRecordId: UUID + ): ReadingRecordResponse { + userAuthService.validateUserExists(userId) + + return readingRecordService.getReadingRecordDetail( + userId = userId, + readingRecordId = readingRecordId + ) + } + fun getReadingRecordsByUserBookId( userId: UUID, userBookId: UUID, diff --git a/domain/src/main/kotlin/org/yapp/domain/readingrecord/ReadingRecordDomainService.kt b/domain/src/main/kotlin/org/yapp/domain/readingrecord/ReadingRecordDomainService.kt index 2e892847..fedac437 100644 --- a/domain/src/main/kotlin/org/yapp/domain/readingrecord/ReadingRecordDomainService.kt +++ b/domain/src/main/kotlin/org/yapp/domain/readingrecord/ReadingRecordDomainService.kt @@ -59,6 +59,27 @@ class ReadingRecordDomainService( ) } + fun findReadingRecordById(readingRecordId: UUID): ReadingRecordInfoVO? { + val readingRecord = readingRecordRepository.findById(readingRecordId) ?: return null + + return buildReadingRecordInfoVO(readingRecord) + } + + private fun buildReadingRecordInfoVO(readingRecord: ReadingRecord): ReadingRecordInfoVO { + val readingRecordTags = readingRecordTagRepository.findByReadingRecordId(readingRecord.id.value) + val tagIds = readingRecordTags.map { it.tagId.value } + val tags = tagRepository.findByIds(tagIds) + val userBook = userBookRepository.findById(readingRecord.userBookId.value) + + return ReadingRecordInfoVO.newInstance( + readingRecord = readingRecord, + emotionTags = tags.map { it.name }, + bookTitle = userBook?.title, + bookPublisher = userBook?.publisher, + bookCoverImageUrl = userBook?.coverImageUrl + ) + } + fun findReadingRecordsByDynamicCondition( userBookId: UUID, sort: ReadingRecordSortType?,