Skip to content

Commit

Permalink
Merge pull request #32 from ASAP-Lettering/ASAP-122
Browse files Browse the repository at this point in the history
ASAP-122 feat: 궤도 편지 전체 조회 api 구현 및 테스트 추가
  • Loading branch information
tlarbals824 authored Sep 13, 2024
2 parents 0630e27 + 1b33ab7 commit 78d9644
Show file tree
Hide file tree
Showing 16 changed files with 406 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.asap.application.letter.port.`in`

interface GetIndependentLettersUsecase {

fun get(query: Query): Response

data class Query(
val userId: String
)

data class Response(
val letters: List<LetterInfo>
)

data class LetterInfo(
val letterId: String,
val senderName: String,
val isNew: Boolean
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import java.time.LocalDate

interface GetVerifiedLetterUsecase {

fun receive(
fun get(
query: Query
): Response

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.asap.application.letter.port.out

import com.asap.domain.common.DomainId
import com.asap.domain.letter.entity.IndependentLetter

interface IndependentLetterManagementPort {

fun save(letter: IndependentLetter)

fun getAllByReceiverId(receiverId: DomainId): List<IndependentLetter>
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,65 @@
package com.asap.application.letter.port.out.memory

import com.asap.application.letter.port.out.IndependentLetterManagementPort
import com.asap.domain.common.DomainId
import com.asap.domain.letter.entity.IndependentLetter
import org.springframework.stereotype.Component
import java.time.LocalDate
import java.time.LocalDateTime

@Component
class MemoryIndependentLetterManagementAdapter(

): IndependentLetterManagementPort {

private val independentLetters = mutableListOf<IndependentLetter>()
private val independentLetters = mutableListOf<IndependentLetterEntity>()

override fun save(letter: IndependentLetter) {
independentLetters.add(letter)
independentLetters.add(IndependentLetterEntity.fromDomain(letter))
}

override fun getAllByReceiverId(receiverId: DomainId): List<IndependentLetter> {
return independentLetters.filter { it.receiverId == receiverId.value }.map { it.toDomain() }
}


data class IndependentLetterEntity(
val id: String,
val senderId: String,
val receiverId: String,
val content: String,
val createdDate: LocalDate,
val templateType: Int,
val images: List<String>,
val isNew: Boolean,
val createdAt: LocalDateTime = LocalDateTime.now()
){
fun toDomain(): IndependentLetter {
return IndependentLetter(
id = DomainId(id),
senderId = DomainId(senderId),
receiverId = DomainId(receiverId),
content = content,
receiveDate = createdDate,
templateType = templateType,
images = images,
isNew = isNew
)
}

companion object{
fun fromDomain(letter: IndependentLetter): IndependentLetterEntity {
return IndependentLetterEntity(
id = letter.id.value,
senderId = letter.senderId.value,
receiverId = letter.receiverId.value,
content = letter.content,
createdDate = letter.receiveDate,
templateType = letter.templateType,
images = letter.images,
isNew = letter.isNew
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.asap.application.letter.service

import com.asap.application.letter.port.`in`.GetIndependentLettersUsecase
import com.asap.application.letter.port.`in`.GetVerifiedLetterUsecase
import com.asap.application.letter.port.out.IndependentLetterManagementPort
import com.asap.application.letter.port.out.SendLetterManagementPort
import com.asap.application.user.port.out.UserManagementPort
import com.asap.domain.common.DomainId
Expand All @@ -9,10 +11,11 @@ import org.springframework.stereotype.Service
@Service
class LetterQueryService(
private val sendLetterManagementPort: SendLetterManagementPort,
private val userManagementPort: UserManagementPort
) : GetVerifiedLetterUsecase {
private val userManagementPort: UserManagementPort,
private val independentLetterManagementPort: IndependentLetterManagementPort
) : GetVerifiedLetterUsecase, GetIndependentLettersUsecase {

override fun receive(query: GetVerifiedLetterUsecase.Query): GetVerifiedLetterUsecase.Response {
override fun get(query: GetVerifiedLetterUsecase.Query): GetVerifiedLetterUsecase.Response {
sendLetterManagementPort.getExpiredLetterNotNull(
receiverId = DomainId(query.userId),
letterId = DomainId(query.letterId)
Expand All @@ -27,4 +30,17 @@ class LetterQueryService(
)
}
}

override fun get(query: GetIndependentLettersUsecase.Query): GetIndependentLettersUsecase.Response {
val letters = independentLetterManagementPort.getAllByReceiverId(DomainId(query.userId))
return GetIndependentLettersUsecase.Response(
letters = letters.map {
GetIndependentLettersUsecase.LetterInfo(
letterId = it.id.value,
senderName = userManagementPort.getUserNotNull(it.senderId).username, // TODO: N+1 문제발생함(해결 필요)
isNew = it.isNew
)
}
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.asap.application.letter.service

import com.asap.application.letter.port.`in`.GetIndependentLettersUsecase
import com.asap.application.letter.port.`in`.GetVerifiedLetterUsecase
import com.asap.application.letter.port.out.IndependentLetterManagementPort
import com.asap.application.letter.port.out.SendLetterManagementPort
import com.asap.application.user.port.out.UserManagementPort
import com.asap.domain.common.DomainId
import com.asap.domain.letter.entity.IndependentLetter
import com.asap.domain.letter.entity.SendLetter
import com.asap.domain.user.entity.User
import com.asap.domain.user.vo.UserPermission
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.shouldBe
import io.mockk.every
import io.mockk.mockk
import java.time.LocalDate

class LetterQueryServiceTest:BehaviorSpec({

val mockSendLetterManagementPort = mockk<SendLetterManagementPort>(relaxed = true)
val mockUserManagementPort = mockk<UserManagementPort>(relaxed = true)
val mockIndependentLetterManagementPort = mockk<IndependentLetterManagementPort>(relaxed = true)

val letterQueryService = LetterQueryService(
mockSendLetterManagementPort,
mockUserManagementPort,
mockIndependentLetterManagementPort
)


given("검증된 편지를 가져올 때") {
val query = GetVerifiedLetterUsecase.Query(
letterId = "letter-id",
userId = "user-id"
)
val mockSendLetter = SendLetter(
id = DomainId(query.letterId),
receiverName = "receiver-name",
content = "content",
images = listOf("image1", "image2"),
templateType = 1,
senderId = DomainId.generate(),
letterCode = "letter-code"
)
val mockSender = User(
id = mockSendLetter.senderId,
username = "sender-name",
profileImage = "profile-image",
permission = UserPermission(true, true, true),
birthday = null
)
every {
mockSendLetterManagementPort.getExpiredLetterNotNull(
receiverId = DomainId(query.userId),
letterId = DomainId(query.letterId)
)
} returns mockSendLetter
every {
mockUserManagementPort.getUserNotNull(mockSender.id)
} returns mockSender
`when`("편지가 존재하면") {
val response = letterQueryService.get(query)
then("편지 정보를 가져와야 한다") {
response.senderName shouldBe mockSender.username
response.content shouldBe mockSendLetter.content
response.sendDate shouldBe mockSendLetter.createdDate
response.templateType shouldBe mockSendLetter.templateType
response.images shouldBe mockSendLetter.images
}
}
}


given("모든 무소속 편지를 조회할 떄"){
val query = GetIndependentLettersUsecase.Query(
userId = "user-id"
)
val mockLetters = listOf(
IndependentLetter(
id = DomainId.generate(),
senderId = DomainId.generate(),
receiverId = DomainId(query.userId),
isNew = true,
content = "content",
receiveDate = LocalDate.now(),
images = listOf("image1", "image2"),
templateType = 1
)
)
val mockSenders = listOf(
User(
id = mockLetters[0].senderId,
username = "sender-name",
profileImage = "profile-image",
permission = UserPermission(true, true, true),
birthday = null
)
)
every {
mockIndependentLetterManagementPort.getAllByReceiverId(DomainId(query.userId))
} returns mockLetters
every {
mockUserManagementPort.getUserNotNull(mockSenders[0].id)
} returns mockSenders[0]
`when`("편지가 존재하면"){
val response = letterQueryService.get(query)
then("편지 정보를 가져와야 한다"){
response.letters[0].letterId shouldBe mockLetters[0].id.value
response.letters[0].senderName shouldBe mockSenders[0].username
response.letters[0].isNew shouldBe mockLetters[0].isNew
}
}
}
}) {
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package com.asap.application.letter

import com.asap.application.letter.port.out.IndependentLetterManagementPort
import com.asap.application.letter.port.out.SendLetterManagementPort
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean

@TestConfiguration
class LetterApplicationConfig(
private val sendLetterManagementPort: SendLetterManagementPort
private val sendLetterManagementPort: SendLetterManagementPort,
private val independentLetterManagementPort: IndependentLetterManagementPort
) {

@Bean
fun letterMockManager(): LetterMockManager {
return LetterMockManager(sendLetterManagementPort)
return LetterMockManager(sendLetterManagementPort,independentLetterManagementPort)
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.asap.application.letter

import com.asap.application.letter.port.out.IndependentLetterManagementPort
import com.asap.application.letter.port.out.SendLetterManagementPort
import com.asap.domain.common.DomainId
import com.asap.domain.letter.entity.IndependentLetter
import com.asap.domain.letter.entity.SendLetter
import com.asap.domain.letter.service.LetterCodeGenerator
import java.time.LocalDate

class LetterMockManager(
private val sendLetterManagementPort: SendLetterManagementPort
private val sendLetterManagementPort: SendLetterManagementPort,
private val independentLetterManagementPort: IndependentLetterManagementPort
) {

private val letterCodeGenerator = LetterCodeGenerator()
Expand Down Expand Up @@ -64,4 +68,23 @@ class LetterMockManager(
return false
}
}

fun generateMockIndependentLetter(
senderId: String,
receiverId: String
): Map<String, Any>{
val independentLetter = IndependentLetter(
senderId = DomainId(senderId),
receiverId = DomainId(receiverId),
content = "content",
receiveDate = LocalDate.now(),
templateType = 1,
images = listOf("image1", "image2"),
isNew = true
)
independentLetterManagementPort.save(independentLetter)
return mapOf(
"letterId" to independentLetter.id.value,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.asap.bootstrap.letter.api
import com.asap.bootstrap.common.exception.ExceptionResponse
import com.asap.bootstrap.common.security.annotation.AccessUser
import com.asap.bootstrap.letter.dto.*
import com.asap.common.page.SliceResponse
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.Content
import io.swagger.v3.oas.annotations.media.Schema
Expand Down Expand Up @@ -127,17 +128,31 @@ interface LetterApi {
)

@Operation(summary = "실물 편지 내용 추가")
@PostMapping("/receive/direct")
@PostMapping("/physical/receive")
fun addAnonymousLetter(
@RequestBody request: AddDirectLetterRequest
@RequestBody request: AddPhysicalLetterRequest
)


@Operation(summary = "궤도 편지 목록 조회")
@GetMapping("/independent")
fun getIndependentLetters(
@RequestParam page: Int,
@RequestParam size: Int
@ApiResponses(
value = [
ApiResponse(
responseCode = "200",
description = "궤도 편지 목록 조회 성공",
content = [
Content(
mediaType = "application/json",
schema = Schema(implementation = SliceResponse::class)
)
]
)
]
)
fun getIndependentLetters(
@AccessUser userId: String,
): SliceResponse<GetIndependentLetterSimpleInfo>


@GetMapping("/{letterId}")
Expand Down
Loading

0 comments on commit 78d9644

Please sign in to comment.