Skip to content

Commit

Permalink
Merge pull request #64 from mash-up-kr/feature/vote
Browse files Browse the repository at this point in the history
feat: 투표하기 API
  • Loading branch information
KimDoubleB authored Jun 29, 2024
2 parents 0ef0121 + 01e1ff5 commit 68341c1
Show file tree
Hide file tree
Showing 30 changed files with 271 additions and 126 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/ci-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: ktlint check
run: ./gradlew ktlintCheck

- name: 프로젝트 빌드
env:
SECRET_MANAGER_TOKEN: ${{ secrets.SECRET_MANAGER_TOKEN }}
SECRET_MANAGER_WORKSPACE: ${{ secrets.SECRET_MANAGER_WORKSPACE }}
run: |
./gradlew build
run: ./gradlew build

- name: Set build status output
id: set_status
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.piikii.application.domain.generic

import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonProperty
import com.piikii.application.consts.THUMBNAIL_LINK_SEPARATOR
import java.io.Serializable

class ThumbnailLinks(
Expand All @@ -14,4 +13,8 @@ class ThumbnailLinks(
@get:JsonProperty("contents")
val convertToList: List<String>
get() = contents?.split(THUMBNAIL_LINK_SEPARATOR) ?: emptyList()

companion object {
const val THUMBNAIL_LINK_SEPARATOR = ","
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.piikii.application.domain.vote

import java.util.UUID

data class Vote(
val userId: UUID,
val roomPlaceId: Long,
val result: VoteResult,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.piikii.application.domain.vote

enum class VoteResult {
O,
X,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.piikii.application.domain.vote

import com.piikii.application.port.input.vote.VoteUseCase
import com.piikii.application.port.output.persistence.RoomQueryPort
import com.piikii.application.port.output.persistence.VoteCommandPort
import com.piikii.common.exception.ExceptionCode
import com.piikii.common.exception.PiikiiException
import org.springframework.stereotype.Service
import java.util.UUID

@Service
class VoteService(
private val voteCommandPort: VoteCommandPort,
private val roomQueryPort: RoomQueryPort,
) : VoteUseCase {
override fun vote(
roomId: UUID,
votes: List<Vote>,
) {
if (roomQueryPort.retrieve(roomId).isUnavailableToVote()) {
throw PiikiiException(
exceptionCode = ExceptionCode.ACCESS_DENIED,
detailMessage = VOTE_ACCESS_DENIED,
)
}
// TODO: votes.map { it.roomPlaceId } 존재여부 검증 필요 -> 도현이 작업 완료되면 붙일 예정
voteCommandPort.vote(votes)
}

companion object {
const val VOTE_ACCESS_DENIED = "투표가 시작되지 않았거나, 마감되었습니다."
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.piikii.application.port.input.vote

import com.piikii.application.domain.vote.Vote
import java.util.UUID

interface VoteUseCase {
fun vote(
roomId: UUID,
votes: List<Vote>,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.piikii.application.port.output.persistence

import com.piikii.application.domain.vote.Vote

interface VoteQueryPort

interface VoteCommandPort {
fun vote(votes: List<Vote>)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.piikii.input.http.advice

import com.piikii.common.exception.PiikiiException
import com.piikii.common.logutil.SystemLogger.logger
import com.piikii.input.http.exception.ExceptionResponse
import com.piikii.input.http.dto.response.ExceptionResponse
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.ExceptionHandler
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.piikii.input.http.config

import com.piikii.input.http.interceptor.LoggingInterceptor
import com.piikii.input.http.web.interceptor.LoggingInterceptor
import org.springframework.context.annotation.Configuration
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import com.piikii.application.port.input.room.dto.request.VoteDeadlineSetRequest
import com.piikii.application.port.input.room.dto.response.RoomGetResponseForm
import com.piikii.application.port.input.room.dto.response.RoomSaveResponseForm
import com.piikii.input.http.docs.RoomApiDocs
import com.piikii.input.http.generic.ResponseForm
import com.piikii.input.http.message.RoomMessage
import com.piikii.input.http.dto.ResponseForm
import com.piikii.input.http.dto.RoomMessage
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
Expand All @@ -27,7 +27,6 @@ import java.util.UUID
class RoomApi(
private val roomUseCase: RoomUseCase,
) : RoomApiDocs {

@ResponseStatus(HttpStatus.CREATED)
@PostMapping
override fun generate(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.piikii.input.http
package com.piikii.input.http.controller

import com.piikii.common.exception.ExceptionCode
import com.piikii.common.exception.PiikiiException
import com.piikii.input.http.generic.ResponseForm
import com.piikii.input.http.dto.ResponseForm
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.piikii.input.http.controller

import com.piikii.application.port.input.vote.VoteUseCase
import com.piikii.input.http.docs.VoteApiDocs
import com.piikii.input.http.dto.ResponseForm
import com.piikii.input.http.dto.request.VoteRequest
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
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/room/votes")
class VoteApi(private val voteUseCase: VoteUseCase) : VoteApiDocs {
@ResponseStatus(HttpStatus.CREATED)
@PostMapping
override fun vote(
@RequestBody voteRequest: VoteRequest,
): ResponseForm<Unit> {
voteUseCase.vote(voteRequest.roomId, voteRequest.toDomains())
return ResponseForm.EMPTY_RESPONSE
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import com.piikii.application.port.input.room.dto.request.RoomUpdateRequestForm
import com.piikii.application.port.input.room.dto.request.VoteDeadlineSetRequest
import com.piikii.application.port.input.room.dto.response.RoomGetResponseForm
import com.piikii.application.port.input.room.dto.response.RoomSaveResponseForm
import com.piikii.input.http.generic.ResponseForm
import com.piikii.input.http.dto.ResponseForm
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter

import io.swagger.v3.oas.annotations.enums.ParameterIn
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.tags.Tag
Expand All @@ -26,13 +28,23 @@ interface RoomApiDocs {
@Operation(summary = "방 삭제 api", description = "방(Room) 정보를 삭제합니다.")
@ApiResponses(value = [ApiResponse(responseCode = "200", description = "DELETED success")])
fun remove(
@Parameter(name = "방 id", description = "삭제하고자 하는 방 id") roomId: UUID,
@Parameter(
name = "roomId",
description = "삭제하고자 하는 방 id",
required = true,
`in` = ParameterIn.PATH,
) roomId: UUID,
): ResponseForm<Unit>

@Operation(summary = "방 조회 api", description = "방(Room) 정보를 조회합니다.")
@ApiResponses(value = [ApiResponse(responseCode = "200", description = "GET success")])
fun search(
@Parameter(name = "방 id", description = "조회하고자 하는 방 id") roomId: UUID,
@Parameter(
name = "roomId",
description = "삭제하고자 하는 방 id",
required = true,
`in` = ParameterIn.PATH,
) roomId: UUID,
): ResponseForm<RoomGetResponseForm>

@Operation(summary = "방 투표 마감일 설정 api", description = "방(Room)의 투표 마감일을 설정합니다.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.piikii.input.http.docs

import com.piikii.input.http.dto.ResponseForm
import com.piikii.input.http.dto.request.VoteRequest
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.Content
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.parameters.RequestBody
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.tags.Tag

@Tag(name = "VoteApi", description = "Vote (투표) API")
interface VoteApiDocs {
@Operation(summary = "투표 API", description = "투표를 진행합니다")
@ApiResponses(value = [ApiResponse(responseCode = "201", description = "Vote succeed")])
fun vote(
@RequestBody(
description = "투표 생성 Request body",
required = true,
content = [Content(schema = Schema(implementation = VoteRequest::class))],
) voteRequest: VoteRequest,
): ResponseForm<Unit>
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.piikii.input.http.generic
package com.piikii.input.http.dto

class ResponseForm<T>(
val data: T? = null,
val message: String? = null,
val timestamp: Long = System.currentTimeMillis(),
)
) {
companion object {
val EMPTY_RESPONSE = ResponseForm<Unit>()
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.piikii.input.http.message
package com.piikii.input.http.dto

object RoomMessage {
const val SUCCESS_CREATE_ROOM = "방 생성 성공"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.piikii.input.http.dto.request

import com.piikii.application.domain.vote.Vote
import com.piikii.application.domain.vote.VoteResult
import java.util.UUID

data class VoteRequest(
val userId: UUID,
val roomId: UUID,
val votes: List<PlaceVoteResult>,
) {
fun toDomains(): List<Vote> {
return this.votes.map { Vote(userId = userId, roomPlaceId = it.roomPlaceId, result = it.voteResult) }
}
}

data class PlaceVoteResult(
val roomPlaceId: Long,
val voteResult: VoteResult,
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.piikii.input.http.exception
package com.piikii.input.http.dto.response

import com.fasterxml.jackson.annotation.JsonInclude

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.piikii.input.http.filter
package com.piikii.input.http.web.filter

import jakarta.servlet.FilterChain
import jakarta.servlet.http.HttpServletRequest
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.piikii.input.http.interceptor
package com.piikii.input.http.web.interceptor

import com.fasterxml.jackson.databind.ObjectMapper
import com.piikii.common.logutil.SlackHookLogger
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ class RoomAdapter(
}

override fun retrieve(roomId: UUID): Room {
val foundRoom = findByRoomId(roomId)
return foundRoom.toDomain()
return findByRoomId(roomId).toDomain()
}

private fun findByRoomId(roomId: UUID): RoomEntity {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.piikii.output.persistence.postgresql.adapter.vote

import com.piikii.application.domain.vote.Vote
import com.piikii.application.port.output.persistence.VoteCommandPort
import com.piikii.application.port.output.persistence.VoteQueryPort
import com.piikii.output.persistence.postgresql.persistence.entity.VoteEntity
import com.piikii.output.persistence.postgresql.persistence.repository.VoteRepository
import org.springframework.stereotype.Repository
import org.springframework.transaction.annotation.Transactional

@Repository
@Transactional(readOnly = true)
class VoteAdapter(
private val voteRepository: VoteRepository,
) : VoteCommandPort, VoteQueryPort {
@Transactional
override fun vote(votes: List<Vote>) {
voteRepository.saveAll(votes.map(VoteEntity::from))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id
import jakarta.persistence.MappedSuperclass
import org.hibernate.annotations.SQLRestriction
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.LastModifiedDate
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.time.LocalDateTime

@EntityListeners(AuditingEntityListener::class)
@SQLRestriction("is_deleted = false")
@MappedSuperclass
abstract class BaseEntity {
@Id
Expand Down
Loading

0 comments on commit 68341c1

Please sign in to comment.