Skip to content

Commit

Permalink
Merge pull request #73 from KUSITMS-29th-TEAM-B/feat/flight-40
Browse files Browse the repository at this point in the history
feat: 경험 삭제 API 구현(#40)
  • Loading branch information
whereami2048 authored May 18, 2024
2 parents d1851b5 + f52b89c commit d15b49e
Show file tree
Hide file tree
Showing 29 changed files with 327 additions and 153 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/CD-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,4 @@ jobs:
docker compose stop ${{secrets.DOCKER_REPOSITORY}}
docker compose rm -f ${{secrets.DOCKER_REPOSITORY}}
docker compose -f docker-compose-dev.yml up -d
docker image prune -f
docker image prune -f
5 changes: 5 additions & 0 deletions Api-Module/src/docs/asciidoc/Experience.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@ operation::ExperienceControllerTest/createOverTitleLengthTest/[snippets='http-re
=== 역량 키워드 제한(5개) 초과 예외

operation::ExperienceControllerTest/createOverStrongPointCountTest/[snippets='http-request,request-headers,request-body,http-response,response-body,response-fields']

[[DeleteExperienceTest]]
=== 경험 삭제 API

operation::ExperienceControllerTest/deleteExperienceTest/[snippets='http-request,path-parameters,request-headers,request-body,http-response,response-body']
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,23 @@ import org.springframework.transaction.annotation.Transactional
@Service
class ExperienceCreateService(
val experienceAppender: ExperienceAppender,
val experienceContentAppender: ExperienceContentAppender
val experienceContentAppender: ExperienceContentAppender,
) {
@Transactional
fun createExperience(request: CreateExperience.Request):CreateExperience.Response {
val currentUserId = getAuthenticationPrincipal()

return request.contents.map {
experienceContentAppender.appendExperienceContent(it.question, it.answer).id
}.let {
experienceAppender.appendExperience(
title = request.title,
userId = currentUserId,
parentTagId = request.parentTagId,
childTagId = request.childTagId,
strongPointIds = request.strongPointIds,
contentIds = it,
startedAt = request.startedAt,
endedAt = request.endedAt
)
}.let {
CreateExperience.Response(it.id)
}
val newExperience = experienceAppender.appendExperience(
title = request.title,
userId = currentUserId,
startedAt = request.startedAt,
endedAt = request.endedAt
)

request.contents.forEach {
experienceContentAppender.appendExperienceContent(it.question, it.answer, newExperience.id)
}

return CreateExperience.Response(newExperience.id)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.bamyanggang.apimodule.domain.experience.application.service

import com.bamyanggang.domainmodule.domain.experience.service.ExperienceRemover
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.util.*

@Service
class ExperienceDeleteService(
val experienceRemover: ExperienceRemover
) {
@Transactional
fun deleteExperienceById(experienceId: UUID) {
experienceRemover.remove(experienceId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ package com.bamyanggang.apimodule.domain.experience.presentation

object ExperienceApi {
const val BASE_URL = "/api/experiences"
const val EXPERIENCE_PATH_VARIABLE_URL = "$BASE_URL/{experienceId}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@ package com.bamyanggang.apimodule.domain.experience.presentation

import com.bamyanggang.apimodule.domain.experience.application.dto.CreateExperience
import com.bamyanggang.apimodule.domain.experience.application.service.ExperienceCreateService
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import com.bamyanggang.apimodule.domain.experience.application.service.ExperienceDeleteService
import org.springframework.web.bind.annotation.*
import java.util.*

@RestController
class ExperienceController(
private val experienceCreateService: ExperienceCreateService
private val experienceCreateService: ExperienceCreateService,
private val experienceDeleteService: ExperienceDeleteService
) {
@PostMapping(ExperienceApi.BASE_URL)
fun createExperience(@RequestBody request: CreateExperience.Request): CreateExperience.Response {
return experienceCreateService.createExperience(request)
}

@DeleteMapping(ExperienceApi.EXPERIENCE_PATH_VARIABLE_URL)
fun deleteExperience(@PathVariable("experienceId") experienceId: UUID) {
experienceDeleteService.deleteExperienceById(experienceId)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//package com.bamyanggang.apimodule.domain.experience.application
//
//import com.bamyanggang.apimodule.domain.experience.application.dto.CreateExperience
//import com.bamyanggang.apimodule.domain.experience.application.service.ExperienceCreateService
//import com.bamyanggang.commonmodule.fixture.generateFixture
//import com.bamyanggang.domainmodule.domain.experience.service.ExperienceAppender
//import com.bamyanggang.domainmodule.domain.experience.service.ExperienceContentAppender
//import io.kotest.core.spec.style.BehaviorSpec
//import io.mockk.every
//import io.mockk.mockk
//import io.mockk.verify
//import java.util.*
//
//class ExperienceCreateServiceTest : BehaviorSpec({
//
// val experienceAppender: ExperienceAppender = mockk()
// val experienceContentAppender: ExperienceContentAppender = mockk()
// val createExperienceService = ExperienceCreateService(experienceAppender, experienceContentAppender)
//
// Given("등록할 경험 Request과 응답이 주어지면") {
// val request : CreateExperience.Request = generateFixture()
// val response : CreateExperience.Response = generateFixture()
//
// When("ExperienceCreateService.createExperience가 호출 되었을 때" ) {
// every { createExperienceService.createExperience(request) } returns response
//
// Then("experienceAppender.appendExperience가 호출된다.") {
// verify {
// experienceAppender.appendExperience(
// request.title,
// generateFixture<UUID>(),
// request.startedAt,
// request.endedAt
// )
// }
// }
//
// Then("experienceContentAppender.appendExperienceContent가 호출된다.") {
// verify {
// experienceContentAppender.appendExperienceContent(
// generateFixture(),
// generateFixture(),
// generateFixture(),
// )
// }
// }
// }
// }
//})
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.bamyanggang.apimodule.domain.experience.application

import com.bamyanggang.apimodule.domain.experience.application.service.ExperienceDeleteService
import com.bamyanggang.domainmodule.domain.experience.service.ExperienceRemover
import io.kotest.core.spec.style.BehaviorSpec
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import java.util.*

class ExperienceDeleteServiceTest : BehaviorSpec({
val experienceRemover = mockk<ExperienceRemover>()
val experienceDeleteService = ExperienceDeleteService(experienceRemover)

Given("ExperienceDeleteService 테스트") {
When("삭제할 UUID가 주어지면") {
val deleteId = UUID.randomUUID()
every { experienceDeleteService.deleteExperienceById(deleteId) } returns Unit

experienceDeleteService.deleteExperienceById(deleteId)

Then("ExperienceRemover.remove가 호출된다.") {
verify { experienceRemover.remove(deleteId) }
}
}
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.bamyanggang.apimodule.domain.experience.presentation
import com.bamyanggang.apimodule.BaseRestDocsTest
import com.bamyanggang.apimodule.domain.experience.application.dto.CreateExperience
import com.bamyanggang.apimodule.domain.experience.application.service.ExperienceCreateService
import com.bamyanggang.apimodule.domain.experience.application.service.ExperienceDeleteService
import com.bamyanggang.commonmodule.exception.ExceptionHandler
import com.bamyanggang.commonmodule.fixture.generateFixture
import org.junit.jupiter.api.DisplayName
Expand All @@ -17,6 +18,8 @@ import org.springframework.restdocs.headers.HeaderDocumentation.headerWithName
import org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders
import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders
import org.springframework.restdocs.payload.PayloadDocumentation.*
import org.springframework.restdocs.request.RequestDocumentation.parameterWithName
import org.springframework.restdocs.request.RequestDocumentation.pathParameters
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import java.time.LocalDateTime
import java.util.*
Expand All @@ -28,6 +31,9 @@ class ExperienceControllerTest : BaseRestDocsTest() {
@MockBean
private lateinit var experienceCreateService: ExperienceCreateService

@MockBean
private lateinit var experienceDeleteService: ExperienceDeleteService

@Test
@DisplayName("경험을 등록한다.")
fun createExperienceTest() {
Expand Down Expand Up @@ -190,5 +196,29 @@ class ExperienceControllerTest : BaseRestDocsTest() {
)
)
}

@Test
@DisplayName("경험을 삭제한다.")
fun deleteExperienceTest() {
//given
val request = RestDocumentationRequestBuilders.delete(ExperienceApi.EXPERIENCE_PATH_VARIABLE_URL, generateFixture<UUID>())
.header("Authorization", "Bearer Access Token")
.contentType(MediaType.APPLICATION_JSON_VALUE)

//when
val result = mockMvc.perform(request)

//then
result.andExpect(status().isOk).andDo(
resultHandler.document(
requestHeaders(
headerWithName("Authorization").description("엑세스 토큰")
),
pathParameters(
parameterWithName("experienceId").description("경험 id")
)
)
)
}
}

Binary file added Domain-Module/.jqwik-database
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,25 @@ import java.util.*
data class Experience(
override val id: UUID = UuidCreator.create(),
val userId : UUID,
val parentTagId : UUID,
val childTagId : UUID,
val strongPointIds : List<UUID> = emptyList(),
val title : String,
val contentIds : List<UUID> = emptyList(),
val startedAt : LocalDateTime,
val endedAt : LocalDateTime,
val createdAt : LocalDateTime,
val updatedAt : LocalDateTime,
) : AggregateRoot {
init {
require(title.length < 50) { "제목의 글자 수는 50자 제한입니다." }
require(strongPointIds.size <= 5) { "역량 키워드는 최대 5개까지 붙일 수 있습니다."}
}
companion object {
fun create(
title: String,
userId: UUID,
parentTagId: UUID,
childTagId: UUID,
strongPointIds: List<UUID>,
contentIds: List<UUID> = emptyList(),
startedAt: LocalDateTime,
endedAt: LocalDateTime,
): Experience {
return Experience(
userId = userId,
parentTagId = parentTagId,
childTagId = childTagId,
strongPointIds = strongPointIds,
title = title,
contentIds = contentIds,
startedAt = startedAt,
endedAt = endedAt,
createdAt = LocalDateTime.now(),
Expand All @@ -50,11 +37,7 @@ data class Experience(
fun toDomain(
id: UUID,
userId: UUID,
parentTagId: UUID,
childTagId: UUID,
strongPointIds: List<UUID>,
title: String,
contentIds: List<UUID> = emptyList(),
startedAt: LocalDateTime,
endedAt: LocalDateTime,
createdAt: LocalDateTime,
Expand All @@ -63,11 +46,7 @@ data class Experience(
return Experience(
id = id,
userId = userId,
parentTagId = parentTagId,
childTagId = childTagId,
strongPointIds = strongPointIds,
title = title,
contentIds = contentIds,
startedAt = startedAt,
endedAt = endedAt,
createdAt = createdAt,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ data class ExperienceContent(
override val id: UUID = UuidCreator.create(),
val question: String,
val answer: String,
val experienceId: UUID
) : DomainEntity {

companion object {
fun create(question: String, answer: String): ExperienceContent {
return ExperienceContent(question = question, answer = answer)
fun create(question: String, answer: String, experienceId: UUID): ExperienceContent {
return ExperienceContent(question = question, answer = answer, experienceId = experienceId)
}

fun toDomain(id: UUID, question: String, answer: String): ExperienceContent {
return ExperienceContent(id, question, answer)
fun toDomain(id: UUID, question: String, answer: String, experienceId: UUID): ExperienceContent {
return ExperienceContent(id, question, answer, experienceId)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ import java.util.*

interface ExperienceContentRepository {
fun save(experienceContent: ExperienceContent)
fun findByExperienceId(experienceId: UUID) : List<ExperienceContent>
fun deleteAllByIds(experienceContents: List<ExperienceContent>)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ import java.util.*

interface ExperienceRepository {
fun save(experience: Experience)
fun deleteByExperienceId(experienceId: UUID)
fun findByExperienceId(id: UUID): Experience
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,12 @@ class ExperienceAppender(
) {
fun appendExperience(title: String,
userId: UUID,
parentTagId: UUID,
childTagId: UUID,
strongPointIds: List<UUID>,
contentIds: List<UUID>,
startedAt: LocalDateTime,
endedAt: LocalDateTime,
): Experience {
return Experience.create(
title = title,
userId = userId,
parentTagId = parentTagId,
childTagId = childTagId,
strongPointIds = strongPointIds,
contentIds = contentIds,
startedAt = startedAt,
endedAt = endedAt
).also {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package com.bamyanggang.domainmodule.domain.experience.service
import com.bamyanggang.domainmodule.domain.experience.aggregate.ExperienceContent
import com.bamyanggang.domainmodule.domain.experience.repository.ExperienceContentRepository
import org.springframework.stereotype.Service
import java.util.*

@Service
class ExperienceContentAppender(
private val experienceContentRepository: ExperienceContentRepository
) {
fun appendExperienceContent(question: String, answer: String): ExperienceContent {
return ExperienceContent.create(question, answer).also {
fun appendExperienceContent(question: String, answer: String, experienceId: UUID): ExperienceContent {
return ExperienceContent.create(question, answer, experienceId).also {
experienceContentRepository.save(it)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.bamyanggang.domainmodule.domain.experience.service

import com.bamyanggang.domainmodule.domain.experience.aggregate.ExperienceContent
import com.bamyanggang.domainmodule.domain.experience.repository.ExperienceContentRepository
import org.springframework.stereotype.Service
import java.util.*

@Service
class ExperienceContentReader(
private val experienceRepository: ExperienceContentRepository
) {
fun readByExperienceId(experienceId: UUID): List<ExperienceContent> {
return experienceRepository.findByExperienceId(experienceId)
}
}
Loading

0 comments on commit d15b49e

Please sign in to comment.