Skip to content
This repository has been archived by the owner on May 19, 2024. It is now read-only.

[WEAV-340] 제안하기 API 개발 #256

Merged
merged 2 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all 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,13 @@
package com.studentcenter.weave.application.suggestion.port.inbound

import java.util.*

interface CreateSuggestion {

fun invoke(command: Command)

data class Command(
val userId: UUID,
val contents: String,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.studentcenter.weave.application.suggestion.port.outbound

import com.studentcenter.weave.domain.suggestion.entity.Suggestion

interface SuggestionRepository {

fun save(suggestion: Suggestion)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.studentcenter.weave.application.suggestion.service

import com.studentcenter.weave.application.suggestion.port.inbound.CreateSuggestion
import com.studentcenter.weave.application.suggestion.port.outbound.SuggestionRepository
import com.studentcenter.weave.domain.suggestion.entity.Suggestion
import org.springframework.stereotype.Service

@Service
class CreateSuggestionService(
private val suggestionRepository: SuggestionRepository,
) : CreateSuggestion {

override fun invoke(command: CreateSuggestion.Command) {
Suggestion.create(
userId = command.userId,
contents = command.contents
).also {
suggestionRepository.save(it)
}
dojinyou marked this conversation as resolved.
Show resolved Hide resolved
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.studentcenter.weave.application.suggestion.service

import com.studentcenter.weave.application.suggestion.outbound.SuggestionRepositorySpy
import com.studentcenter.weave.application.suggestion.port.inbound.CreateSuggestion
import com.studentcenter.weave.domain.user.entity.UserFixtureFactory
import io.kotest.core.annotation.DisplayName
import io.kotest.core.spec.style.DescribeSpec
import io.kotest.matchers.shouldBe

@DisplayName("CreateSuggestionService")
class CreateSuggestionServiceTest : DescribeSpec({

val suggestionRepository = SuggestionRepositorySpy()
val sut = CreateSuggestionService(suggestionRepository)

afterEach {
suggestionRepository.clear()
}

describe("제안 생성") {
it("제안을 생성하고 DB에 저장한다") {
// arrange
val userFixture = UserFixtureFactory.create()

val command = CreateSuggestion.Command(
userId = userFixture.id,
contents = "contents"
)

// act
sut.invoke(command)

// assert
suggestionRepository.count() shouldBe 1
}
}


})
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.studentcenter.weave.application.suggestion.outbound

import com.studentcenter.weave.application.suggestion.port.outbound.SuggestionRepository
import com.studentcenter.weave.domain.suggestion.entity.Suggestion
import java.util.*
import java.util.concurrent.ConcurrentHashMap

class SuggestionRepositorySpy : SuggestionRepository {

private val bucket = ConcurrentHashMap<UUID, Suggestion>()

override fun save(suggestion: Suggestion) {
bucket[suggestion.id] = suggestion
}

fun clear() {
bucket.clear()
}

fun count() = bucket.size

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.studentcenter.weave.bootstrap.suggestion.api

import com.studentcenter.weave.bootstrap.common.security.annotation.Secured
import com.studentcenter.weave.bootstrap.suggestion.dto.SuggestionCreateRequest
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.ResponseStatus

@Tag(name = "Suggestion", description = "Suggestion API")
@RequestMapping("/api/suggestions")
interface SuggestionApi {

@Secured
@Operation(summary = "Create new suggestion")
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun createSuggestion(
@RequestBody
request: SuggestionCreateRequest,
)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.studentcenter.weave.bootstrap.suggestion.controller

import com.studentcenter.weave.application.common.security.context.getCurrentUserAuthentication
import com.studentcenter.weave.application.suggestion.port.inbound.CreateSuggestion
import com.studentcenter.weave.bootstrap.suggestion.api.SuggestionApi
import com.studentcenter.weave.bootstrap.suggestion.dto.SuggestionCreateRequest
import org.springframework.web.bind.annotation.RestController

@RestController
class SuggestionRestController(
private val createSuggestion: CreateSuggestion,
) : SuggestionApi {

override fun createSuggestion(request: SuggestionCreateRequest) {
request
.toCommand(getCurrentUserAuthentication())
Copy link
Member Author

@waterfogSW waterfogSW Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추후 getCurrentAuthentication 제거 리펙터링, argument resolver에 의해 controller에 직접 userAuthentication 매핑되도록 변경 예정 (타도메인도 마찬가지)

.also { createSuggestion.invoke(it) }
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.studentcenter.weave.bootstrap.suggestion.dto

import com.studentcenter.weave.application.suggestion.port.inbound.CreateSuggestion
import com.studentcenter.weave.application.user.vo.UserAuthentication

data class SuggestionCreateRequest(
val contents: String?,
) {

fun toCommand(userAuth: UserAuthentication): CreateSuggestion.Command {
require(contents != null) {
"내용을 입력해 주세요!"
}

return CreateSuggestion.Command(
userId = userAuth.userId,
contents = contents
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.studentcenter.weave.domain.suggestion.entity

import com.studentcenter.weave.domain.common.AggregateRoot
import com.studentcenter.weave.support.common.uuid.UuidCreator
import java.util.*

data class Suggestion(
override val id: UUID = UuidCreator.create(),
val userId: UUID,
val contents: String,
) : AggregateRoot {

init {
require(contents.isNotBlank()) {
"내용을 입력해 주세요!"
}

require(contents.length <= MAX_CONTENTS_LENGTH) {
"내용은 ${MAX_CONTENTS_LENGTH}자 이하로 입력해 주세요!"
}
}

companion object {

const val MAX_CONTENTS_LENGTH = 2000

fun create(
userId: UUID,
contents: String,
): Suggestion {
return Suggestion(
userId = userId,
contents = contents
)
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.studentcenter.weave.infrastructure.persistence.suggestion.adapter

import com.studentcenter.weave.application.suggestion.port.outbound.SuggestionRepository
import com.studentcenter.weave.domain.suggestion.entity.Suggestion
import com.studentcenter.weave.infrastructure.persistence.suggestion.entity.SuggestionJpaEntity.Companion.toJpaEntity
import com.studentcenter.weave.infrastructure.persistence.suggestion.repository.SuggestionJpaRepository
import org.springframework.stereotype.Component

@Component
class SuggestionJpaAdapter(
private val suggestionJpaRepository: SuggestionJpaRepository,
) : SuggestionRepository {

override fun save(suggestion: Suggestion) {
suggestionJpaRepository.save(suggestion.toJpaEntity())
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.studentcenter.weave.infrastructure.persistence.suggestion.entity

import com.studentcenter.weave.domain.suggestion.entity.Suggestion
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.Table
import java.util.*

@Entity
@Table(name = "suggestion")
class SuggestionJpaEntity(
id: UUID,
userId: UUID,
contents: String,
) {

@Id
@Column(name = "id", nullable = false, updatable = false, columnDefinition = "BINARY(16)")
var id: UUID = id
private set

@Column(name = "user_id", nullable = false, updatable = false, columnDefinition = "BINARY(16)")
var userId: UUID = userId
private set

@Column(name = "contents", nullable = false, length = 2000, columnDefinition = "TEXT")
var contents: String = contents
private set

fun toDomainEntity() = Suggestion(
id = id,
userId = userId,
contents = contents
)

companion object {

fun Suggestion.toJpaEntity() = SuggestionJpaEntity(
id = id,
userId = userId,
contents = contents
)

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.studentcenter.weave.infrastructure.persistence.suggestion.repository

import com.studentcenter.weave.infrastructure.persistence.suggestion.entity.SuggestionJpaEntity
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
import java.util.*

@Repository
interface SuggestionJpaRepository : JpaRepository<SuggestionJpaEntity, UUID>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
create table suggestion
(
id binary(16) primary key,
user_id binary(16) not null,
contents text not null
) engine = InnoDB,
char set utf8mb4;
Loading