From 82075e8f74ac14f27ac0b09d4862a135cc8353dc Mon Sep 17 00:00:00 2001
From: Kijun Kwon <kkjsw17@naver.com>
Date: Sat, 24 Feb 2024 16:22:03 +0900
Subject: [PATCH] =?UTF-8?q?feat:=20thumbnail=20=EA=B4=80=EB=A0=A8=20?=
 =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../security/jwt/JwtAuthFilter.kt             |  3 ---
 .../pregen/presentation/file/domain/File.kt   |  2 +-
 .../file/infrastructure/FileProperties.kt     |  1 -
 .../file/infrastructure/FileRepositoryImpl.kt |  5 +++++
 .../file/service/FileRepository.kt            |  2 ++
 .../presentation/PresentationListResponse.kt  | 11 ++++++++--
 .../presentation/PresentationResponse.kt      |  2 +-
 .../service/PresentationService.kt            |  4 +++-
 .../service/PresentationThumbnailResolver.kt  | 21 +++++++++++++++++++
 .../pregen/presentation/slide/domain/Slide.kt |  7 +++----
 .../infrastructure/SlideJpaRepository.kt      |  2 ++
 .../infrastructure/SlideRepositoryImpl.kt     |  4 ++++
 .../slide/service/SlideRepository.kt          |  2 ++
 .../slide/service/SlideService.kt             | 12 ++++++++++-
 14 files changed, 64 insertions(+), 14 deletions(-)
 create mode 100644 presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/service/PresentationThumbnailResolver.kt

diff --git a/account-api/src/main/kotlin/org/kkeunkkeun/pregen/account/infrastructure/security/jwt/JwtAuthFilter.kt b/account-api/src/main/kotlin/org/kkeunkkeun/pregen/account/infrastructure/security/jwt/JwtAuthFilter.kt
index 6d54fe4..9a49ffa 100644
--- a/account-api/src/main/kotlin/org/kkeunkkeun/pregen/account/infrastructure/security/jwt/JwtAuthFilter.kt
+++ b/account-api/src/main/kotlin/org/kkeunkkeun/pregen/account/infrastructure/security/jwt/JwtAuthFilter.kt
@@ -74,9 +74,6 @@ class JwtAuthFilter(
         } catch (e: PregenException) {
             log.error("Filter error: ${e.message}")
             handleException(request, response, e)
-        } catch (e: Exception) {
-            log.error("Filter error: ${e.message}")
-            handleException(request, response, e, "인증 과정에서 예외가 발생했습니다.")
         }
     }
 
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/domain/File.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/domain/File.kt
index d43a428..46b6c73 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/domain/File.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/domain/File.kt
@@ -36,7 +36,7 @@ class File(
             return File(
                 null,
                 fileType = IMAGE,
-                path = path,
+                path = path.replace(".", ""),
                 originalName = originalName,
                 generatedName = generatedName,
             )
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/infrastructure/FileProperties.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/infrastructure/FileProperties.kt
index a90bc1a..da0c5e5 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/infrastructure/FileProperties.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/infrastructure/FileProperties.kt
@@ -10,5 +10,4 @@ data class FileProperties(
     val fullThumbnailPath: String
         get() = "$basePath/$thumbnailPath"
             .replace("//", "/")
-            .replace(".", "")
 }
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/infrastructure/FileRepositoryImpl.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/infrastructure/FileRepositoryImpl.kt
index 07242c3..68cbaeb 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/infrastructure/FileRepositoryImpl.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/infrastructure/FileRepositoryImpl.kt
@@ -2,6 +2,7 @@ package org.kkeunkkeun.pregen.presentation.file.infrastructure
 
 import org.kkeunkkeun.pregen.presentation.file.domain.File
 import org.kkeunkkeun.pregen.presentation.file.service.FileRepository
+import org.springframework.data.repository.findByIdOrNull
 import org.springframework.stereotype.Repository
 
 @Repository
@@ -12,4 +13,8 @@ class FileRepositoryImpl(
     override fun save(file: File) {
         fileJpaRepository.save(file)
     }
+
+    override fun findById(fileId: Long?): File? = fileId?.let {
+        fileJpaRepository.findByIdOrNull(it)
+    }
 }
\ No newline at end of file
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/service/FileRepository.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/service/FileRepository.kt
index ec25c24..abdcee5 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/service/FileRepository.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/file/service/FileRepository.kt
@@ -5,4 +5,6 @@ import org.kkeunkkeun.pregen.presentation.file.domain.File
 interface FileRepository {
 
     fun save(file: File)
+
+    fun findById(fileId: Long?): File?
 }
\ No newline at end of file
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/presentation/PresentationListResponse.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/presentation/PresentationListResponse.kt
index 1caaf1a..ae70228 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/presentation/PresentationListResponse.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/presentation/PresentationListResponse.kt
@@ -21,20 +21,27 @@ data class PresentationListResponse(
 
         val timeLimit: PresentationTime,
 
+        val thumbnailPath: String?,
+
         val createdAt: LocalDateTime,
+
+        val modifiedAt: LocalDateTime,
     ) {
 
         companion object {
-            fun from(presentation: Presentation): ListItem {
+            fun from(presentation: Presentation, thumbnailPath: String?): ListItem {
                 val id = presentation.id ?: throw RuntimeException()
                 val createdAt = presentation.createdAt ?: throw RuntimeException()
+                val modifiedAt = presentation.modifiedAt ?: throw RuntimeException()
 
                 return ListItem(
                     id,
                     presentation.title,
                     presentation.getDDay(),
                     PresentationTime.from(presentation.timeLimit),
-                    createdAt
+                    thumbnailPath,
+                    createdAt,
+                    modifiedAt,
                 )
             }
         }
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/presentation/PresentationResponse.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/presentation/PresentationResponse.kt
index 9c313bc..3ae38e5 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/presentation/PresentationResponse.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/presentation/PresentationResponse.kt
@@ -65,7 +65,7 @@ class PresentationResponse {
     ) {
         companion object {
             fun from(slides: List<Slide>): List<SlideDetail> {
-                return slides.map { slide -> SlideDetail(slide.id!!, slide.imageFilePath(), slide.script, slide.memo) }
+                return slides.map { slide -> SlideDetail(slide.id!!, slide.imageFilePath, slide.script, slide.memo) }
             }
         }
     }
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/service/PresentationService.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/service/PresentationService.kt
index 4e8c375..8143531 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/service/PresentationService.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/service/PresentationService.kt
@@ -15,6 +15,7 @@ class PresentationService(
     private val presentationRepository: PresentationRepository,
     private val accountRepository: AccountRepository,
     private val presentationAccessChecker: PresentationAccessChecker,
+    private val thumbnailResolver: PresentationThumbnailResolver
 ) {
 
     fun findListByAccountId(email: String, pageable: Pageable): Page<PresentationListResponse.ListItem> {
@@ -63,6 +64,7 @@ class PresentationService(
     }
 
     private fun generateListItem(presentation: Presentation): PresentationListResponse.ListItem {
-        return PresentationListResponse.ListItem.from(presentation)
+        val thumbnailPath = thumbnailResolver.findThumbnail(presentation.id!!)
+        return PresentationListResponse.ListItem.from(presentation, thumbnailPath)
     }
 }
\ No newline at end of file
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/service/PresentationThumbnailResolver.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/service/PresentationThumbnailResolver.kt
new file mode 100644
index 0000000..796b571
--- /dev/null
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/presentation/service/PresentationThumbnailResolver.kt
@@ -0,0 +1,21 @@
+package org.kkeunkkeun.pregen.presentation.presentation.service
+
+import org.kkeunkkeun.pregen.presentation.practice.service.PracticeRepository
+import org.kkeunkkeun.pregen.presentation.slide.service.SlideRepository
+import org.springframework.stereotype.Service
+import org.springframework.transaction.annotation.Transactional
+
+@Service
+@Transactional(readOnly = true)
+class PresentationThumbnailResolver(
+    private val practiceRepository: PracticeRepository,
+    private val slideRepository: SlideRepository,
+) {
+
+    fun findThumbnail(presentationId: Long): String? {
+        return practiceRepository.findLatestByPresentationId(presentationId)
+            .let { practice ->
+                slideRepository.findFirstByPracticeId(practice.id!!)
+            }?.imageFilePath
+    }
+}
\ No newline at end of file
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/domain/Slide.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/domain/Slide.kt
index 488e7f5..b3d7d28 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/domain/Slide.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/domain/Slide.kt
@@ -29,16 +29,15 @@ class Slide(
     var practiceId: Long? = practiceId
         protected set
 
+    val imageFilePath: String?
+        get() = imageFile?.absolutePath
+
     companion object {
         fun from(practiceId: Long, imageFile: File?, request: PresentationRequest.SlideRequest): Slide {
             return Slide(practiceId, imageFile, request.script, request.memo)
         }
     }
 
-    fun imageFilePath(): String? {
-        return imageFile?.absolutePath
-    }
-
     fun unmap() {
         this.practiceId = null
     }
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/infrastructure/SlideJpaRepository.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/infrastructure/SlideJpaRepository.kt
index ec6dfd8..79de863 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/infrastructure/SlideJpaRepository.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/infrastructure/SlideJpaRepository.kt
@@ -6,4 +6,6 @@ import org.springframework.data.jpa.repository.JpaRepository
 interface SlideJpaRepository: JpaRepository<Slide, Long> {
 
     fun findByPracticeId(practiceId: Long): List<Slide>
+
+    fun findFirstByPracticeId(practiceId: Long): Slide?
 }
\ No newline at end of file
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/infrastructure/SlideRepositoryImpl.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/infrastructure/SlideRepositoryImpl.kt
index 2a2b163..2f98673 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/infrastructure/SlideRepositoryImpl.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/infrastructure/SlideRepositoryImpl.kt
@@ -13,6 +13,10 @@ class SlideRepositoryImpl(
         return slideJpaRepository.findByPracticeId(practiceId)
     }
 
+    override fun findFirstByPracticeId(practiceId: Long): Slide? {
+        return slideJpaRepository.findFirstByPracticeId(practiceId)
+    }
+
     override fun saveAll(slides: List<Slide>) {
         slideJpaRepository.saveAll(slides)
     }
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/service/SlideRepository.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/service/SlideRepository.kt
index 22d13c6..a69e6c3 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/service/SlideRepository.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/service/SlideRepository.kt
@@ -6,5 +6,7 @@ interface SlideRepository {
 
     fun findByPracticeId(practiceId: Long): List<Slide>
 
+    fun findFirstByPracticeId(practiceId: Long): Slide?
+
     fun saveAll(slides: List<Slide>)
 }
\ No newline at end of file
diff --git a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/service/SlideService.kt b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/service/SlideService.kt
index 7b211c0..507cf23 100644
--- a/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/service/SlideService.kt
+++ b/presentation-api/src/main/kotlin/org/kkeunkkeun/pregen/presentation/slide/service/SlideService.kt
@@ -1,5 +1,6 @@
 package org.kkeunkkeun.pregen.presentation.slide.service
 
+import org.kkeunkkeun.pregen.presentation.file.service.FileRepository
 import org.kkeunkkeun.pregen.presentation.presentation.presentation.PresentationRequest
 import org.kkeunkkeun.pregen.presentation.slide.domain.Slide
 import org.springframework.stereotype.Service
@@ -9,6 +10,7 @@ import org.springframework.transaction.annotation.Transactional
 @Transactional(readOnly = true)
 class SlideService(
     private val slideRepository: SlideRepository,
+    private val fileRepository: FileRepository,
 ) {
 
     fun findByPracticeId(practiceId: Long): List<Slide> {
@@ -17,11 +19,19 @@ class SlideService(
 
     @Transactional
     fun saveAll(practiceId: Long, slideRequests: List<PresentationRequest.SlideRequest>) {
-        val slides = slideRequests.map { request -> Slide.from(practiceId, null, request) } // TODO: add file
+        val slides = slideRequests.map { request -> mapToSlideEntity(practiceId, request) }
 
         slideRepository.saveAll(slides)
     }
 
+    private fun mapToSlideEntity(practiceId: Long, slideRequest: PresentationRequest.SlideRequest): Slide {
+        return Slide.from(
+            practiceId = practiceId,
+            imageFile = fileRepository.findById(slideRequest.imageFileId),
+            request = slideRequest
+        )
+    }
+
     @Transactional
     fun overwrite(practiceId: Long, slideRequests: List<PresentationRequest.SlideRequest>) {
         this.findByPracticeId(practiceId)