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

Commit

Permalink
[WEAV-340] 제안하기 API 개발 (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
waterfogSW authored Apr 22, 2024
1 parent 20108ec commit f0a3fbd
Show file tree
Hide file tree
Showing 13 changed files with 292 additions and 0 deletions.
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)
}
}

}
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())
.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;

0 comments on commit f0a3fbd

Please sign in to comment.