Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] : 전체 Gallery 조회 기능 추가 #381

Merged
merged 6 commits into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE INDEX gallery_idx_bookmark ON gallery(bookmarked_count)
CREATE INDEX gallery_idx_update_order ON gallery(update_order)
CREATE UNIQUE INDEX gallery_idx_survey_id ON gallery(survey_id)
CREATE INDEX gallery_idx_job ON gallery(job)
CREATE INDEX gallery_idx_created_at ON gallery(created_at)
CREATE INDEX gallery_idx_updated_at ON gallery(updated_at)
34 changes: 34 additions & 0 deletions gallery/src/main/kotlin/me/nalab/gallery/app/GalleryGetApp.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package me.nalab.gallery.app

import me.nalab.gallery.domain.Gallery
import me.nalab.gallery.domain.GalleryService
import me.nalab.gallery.domain.response.GalleriesDto
import me.nalab.gallery.domain.response.GalleryDto
import me.nalab.survey.application.port.`in`.web.findfeedback.FeedbackFindUseCase
import me.nalab.survey.application.port.`in`.web.survey.find.SurveyFindUseCase
import me.nalab.survey.application.port.`in`.web.target.find.TargetFindUseCase
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Sort
import org.springframework.stereotype.Service

@Service
Expand All @@ -23,4 +29,32 @@ class GalleryGetApp(

return toGalleryDto(gallery, target, survey, feedbacks)
}

fun getGalleries(job: String, page: Int, count: Int, orderType: String): GalleriesDto {
val pageable = getPage(page, count, orderType)
val galleries = galleryService.getGalleries(job, pageable)

val galleryDtos = toGalleryDtos(galleries)

return GalleriesDto(galleries.totalPages, galleryDtos)
}

private fun toGalleryDtos(galleries: Page<Gallery>): List<GalleryDto> {
return galleries.asSequence()
.map { gallery ->
val target = targetFindUseCase.findTarget(gallery.getTargetId())
val survey = surveyFindUseCase.getSurveyByTargetId(gallery.getTargetId())
val feedbacks = feedbackFindUseCase.findAllFeedbackDtoBySurveyId(survey.id)

toGalleryDto(gallery, target, survey, feedbacks)
}.toList()
}

private fun getPage(page: Int, count: Int, orderType: String): Pageable {
return when (orderType.lowercase()) {
"update" -> PageRequest.of(page, count, Sort.by("updateOrder").descending())
"job" -> PageRequest.of(page, count, Sort.by("survey.bookmarkedCount").descending())
else -> throw IllegalArgumentException("orderType 은 update와 bookmark중 하나여야 합니다. 현재 orderType \"$orderType\"")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import me.nalab.gallery.app.GalleryGetApp
import me.nalab.gallery.app.GalleryPreviewApp
import me.nalab.gallery.app.GalleryRegisterApp
import me.nalab.gallery.controller.request.GalleryRegisterRequest
import me.nalab.gallery.domain.response.GalleriesDto
import me.nalab.gallery.domain.response.GalleryDto
import me.nalab.gallery.domain.response.GalleryPreviewDto
import org.springframework.http.HttpStatus
Expand Down Expand Up @@ -36,4 +37,15 @@ class GalleryController(
fun getGallery(@RequestAttribute("logined") targetId: Long): GalleryDto =
galleryGetApp.getGalleryByTargetId(targetId)

@GetMapping
@ResponseStatus(HttpStatus.OK)
fun getGalleries(
@RequestParam(name = "job", defaultValue = "all") job: String,
@RequestParam(name = "page", defaultValue = "0") page: Int,
@RequestParam(name = "count", defaultValue = "5") count: Int,
@RequestParam(name = "order-type", defaultValue = "update") orderType: String
): GalleriesDto {
return galleryGetApp.getGalleries(job, page, count, orderType)
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package me.nalab.gallery.domain

import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Lock
import org.springframework.data.jpa.repository.Query
Expand All @@ -11,4 +13,8 @@ interface GalleryRepository : JpaRepository<Gallery, Long> {
@Lock(LockModeType.OPTIMISTIC)
@Query("select g from Gallery as g where g.target.targetId = :targetId")
fun findByTargetIdOrNull(@Param("targetId") targetId: Long): Gallery?

@Query("select g from Gallery g where g.target.job in :job")
fun findGalleries(@Param("job") job: List<Job>, pageable: Pageable): Page<Gallery>

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package me.nalab.gallery.domain

import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

Expand Down Expand Up @@ -27,4 +29,13 @@ class GalleryService(
fun increaseBookmarkCount(targetId: Long) {
galleryRepository.findByTargetIdOrNull(targetId)?.increaseBookmarkedCount()
}

fun getGalleries(job: String, pageable: Pageable): Page<Gallery> {
val jobs = when (job) {
"all" -> Job.entries.toList()
else -> listOf(Job.valueOf(job.uppercase()))
}

return galleryRepository.findGalleries(jobs, pageable)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package me.nalab.gallery.domain.response

data class GalleriesDto(
val totalPage: Int,
val galleries: List<GalleryDto>
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@ package me.nalab.gallery.domain
import io.kotest.assertions.throwables.shouldThrowMessage
import io.kotest.core.annotation.DisplayName
import io.kotest.core.spec.style.DescribeSpec
import io.kotest.matchers.equality.shouldBeEqualToComparingFields
import io.kotest.matchers.equality.shouldBeEqualUsingFields
import io.kotest.matchers.equals.shouldBeEqual
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import org.springframework.test.context.ContextConfiguration
import java.time.Instant
import java.time.temporal.ChronoUnit

@DataJpaTest
@EnableJpaRepositories
Expand All @@ -16,13 +22,24 @@ import org.springframework.test.context.ContextConfiguration
@ContextConfiguration(classes = [GalleryService::class])
internal class GalleryServiceTest(
private val galleryService: GalleryService,
private val galleryRepository: GalleryRepository,
) : DescribeSpec({

beforeSpec {
galleryService.registerGallery(gallery(id = EXIST_GALLERY_ID, targetId = EXIST_TARGET_ID, surveyId = EXIST_SURVEY_ID))
afterEach {
galleryRepository.deleteAll()
}

describe("registerGallery 메소드는") {
beforeEach {
galleryService.registerGallery(
gallery(
id = EXIST_GALLERY_ID,
targetId = EXIST_TARGET_ID,
surveyId = EXIST_SURVEY_ID
)
)
}

context("Gallery에 등록되지 않은 target의 Gallery를 입력받으면,") {
val gallery = gallery(targetId = NOT_EXIST_TARGET_ID)

Expand All @@ -43,12 +60,137 @@ internal class GalleryServiceTest(
}
}
}

describe("getGalleries 메소드는") {
beforeEach {
galleryService.registerGallery(oldDesignerGallery)
galleryService.registerGallery(midDeveloperGallery)
galleryService.registerGallery(latestPmGallery)
}

context("job으로 all과 update순으로 정렬된 Pageable을 입력받으면,") {
val expected = listOf(latestPmGallery, midDeveloperGallery, oldDesignerGallery)

it("update순으로 정렬된 Gallery를 반환한다.") {
val result = galleryService.getGalleries("all", updatePage).content

result.shouldBeExactlyEqualToComparingFields(expected)
}
}

context("job으로 designer와 update순으로 정렬된 Pageable을 입력받으면,") {
val expected = listOf(oldDesignerGallery)

it("update순으로 정렬된 designer Gallery를 반환한다.") {
val result = galleryService.getGalleries("designer", updatePage).content

result.shouldBeExactlyEqualToComparingFields(expected)
}
}

context("job으로 pm과 update순으로 정렬된 Pageable을 입력받으면,") {
val expected = listOf(latestPmGallery)

it("update순으로 정렬된 pm Gallery를 반환한다.") {
val result = galleryService.getGalleries("pm", updatePage).content

result.shouldBeExactlyEqualToComparingFields(expected)
}
}

context("job으로 developer와 update순으로 정렬된 Pageable을 입력받으면,") {
val expected = listOf(midDeveloperGallery)

it("update순으로 정렬된 pm Gallery를 반환한다.") {
val result = galleryService.getGalleries("developer", updatePage).content

result.shouldBeExactlyEqualToComparingFields(expected)
}
}

context("job으로 all과 bookmark순으로 정렬된 Pageable을 받으면,") {
val expected = listOf(oldDesignerGallery, midDeveloperGallery, latestPmGallery)

it("bookmark순으로 정렬된 Gallery를 반환한다") {
val result = galleryService.getGalleries("all", bookmarkPage).content

result.shouldBeExactlyEqualToComparingFields(expected)
}
}

context("job으로 designer와 bookmark순으로 정렬된 Pageable을 입력받으면,") {
val expected = listOf(oldDesignerGallery)

it("update순으로 정렬된 designer Gallery를 반환한다.") {
val result = galleryService.getGalleries("designer", bookmarkPage).content

result.shouldBeExactlyEqualToComparingFields(expected)
}
}

context("job으로 pm과 bookmark순으로 정렬된 Pageable을 입력받으면,") {
val expected = listOf(latestPmGallery)

it("update순으로 정렬된 pm Gallery를 반환한다.") {
val result = galleryService.getGalleries("pm", bookmarkPage).content

result.shouldBeExactlyEqualToComparingFields(expected)
}
}

context("job으로 developer와 bookmark순으로 정렬된 Pageable을 입력받으면,") {
val expected = listOf(midDeveloperGallery)

it("update순으로 정렬된 pm Gallery를 반환한다.") {
val result = galleryService.getGalleries("developer", bookmarkPage).content

result.shouldBeExactlyEqualToComparingFields(expected)
}
}
}
}) {

companion object {
private const val NOT_EXIST_TARGET_ID = 1L
private const val EXIST_GALLERY_ID = 100L
private const val EXIST_TARGET_ID = 100L
private const val EXIST_SURVEY_ID = 100L

val updatePage: PageRequest = PageRequest.of(0, 5, Sort.by("updateOrder").descending())
val bookmarkPage: PageRequest = PageRequest.of(0, 5, Sort.by("survey.bookmarkedCount").descending())

val oldDesignerGallery = gallery(
id = 1,
targetId = 101,
surveyId = 101,
job = Job.DESIGNER,
updateOrder = Instant.now().minus(1, ChronoUnit.DAYS),
bookmarkedCount = 3
)

val midDeveloperGallery = gallery(
id = 2,
targetId = 102,
surveyId = 102,
job = Job.DEVELOPER,
updateOrder = Instant.now(),
bookmarkedCount = 2
)

val latestPmGallery = gallery(
id = 3,
targetId = 103,
surveyId = 103,
job = Job.PM,
updateOrder = Instant.now().plus(1, ChronoUnit.DAYS),
bookmarkedCount = 1
)

private fun List<Gallery>.shouldBeExactlyEqualToComparingFields(galleries: List<Gallery>) {
this.size shouldBeEqual galleries.size
for (i in galleries.indices) {
this[i] shouldBeEqualToComparingFields galleries[i]
}
}
}
}
Loading