Skip to content

Commit

Permalink
[DPMBE-57] feat : 약속 단계 히스토리 init, 업데이트 , 조회 기능 추가 (#68)
Browse files Browse the repository at this point in the history
* feat : promise progress change usecase

* feat : promise user handler 추가

* feat : handler custom annotaion 추가

* feat : history domain service 추가

* feat : progress history init , delete domainservice

* feat : userProgressResponse 추가

* feat : history usecase 초안

* refactor : after promise progress id to current id

* feat : 히스토리 관련 에러코드 추가

* feat : 변경시 같은 아이디일경우 에러 추가

* style : 필요 없는 메서드 삭제
  • Loading branch information
ImNM authored Jun 7, 2023
1 parent bc1d77f commit c40a2db
Show file tree
Hide file tree
Showing 20 changed files with 296 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.depromeet.whatnow.api.example.controller

import com.depromeet.whatnow.annotation.ApiErrorCodeExample
import com.depromeet.whatnow.api.config.KakaoKauthErrorCode
import com.depromeet.whatnow.domains.progresshistory.exception.PromiseHistoryErrorCode
import com.depromeet.whatnow.domains.user.exception.UserErrorCode
import com.depromeet.whatnow.exception.GlobalErrorCode
import io.swagger.v3.oas.annotations.Operation
Expand Down Expand Up @@ -33,4 +34,9 @@ class ExampleController() {
@Operation(summary = "카카오 auth 관련 에러코드 나열")
@ApiErrorCodeExample(KakaoKauthErrorCode::class)
fun kakaoErrorCode() {}

@GetMapping("/promises/progresses/history")
@Operation(summary = "약속 히스토리 관련 에러코드 나열")
@ApiErrorCodeExample(PromiseHistoryErrorCode::class)
fun progressHistoryErrorCode() {}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,40 @@
package com.depromeet.whatnow.api.promiseprogress.controller

import com.depromeet.whatnow.api.promiseprogress.dto.response.PromiseProgressGroupElement
import com.depromeet.whatnow.api.promiseprogress.dto.response.UserProgressResponse
import com.depromeet.whatnow.api.promiseprogress.usecase.ProgressHistoryChangeUseCase
import com.depromeet.whatnow.api.promiseprogress.usecase.ProgressHistoryReadUseCase
import com.depromeet.whatnow.api.promiseprogress.usecase.PromiseProgressReadUseCase
import io.swagger.v3.oas.annotations.security.SecurityRequirement
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/v1/promise")
@Tag(name = "5(일단 5번으로 잡음 순서). [약속진행상태]")
@RequestMapping("/v1/promises")
@Tag(name = "5. [약속진행상태]")
@SecurityRequirement(name = "access-token")
class PromiseProgressController(
val promiseProgressReadUseCase: PromiseProgressReadUseCase,
val promiseHistoryChangeUseCase: ProgressHistoryChangeUseCase,
val promiseHistoryReadUseCase: ProgressHistoryReadUseCase,
) {

@GetMapping("/progress")
@GetMapping("/progresses")
fun getPromiseProgresses(): List<PromiseProgressGroupElement> {
return promiseProgressReadUseCase.execute()
}
//
// @PostMapping("/{promiseId}/progress/{progressCode}")
// fun changePromiseProgress(): List<PromiseProgressGroupElement> {
// return promiseProgressReadUseCase.execute()
// }

@GetMapping("/{promiseId}/users/{userId}")
fun getUserProgress(@PathVariable promiseId: Long, @PathVariable userId: Long): UserProgressResponse {
return promiseHistoryReadUseCase.execute(promiseId, userId)
}

@PatchMapping("/{promiseId}/progresses/{progressCode}")
fun changePromiseProgress(@PathVariable progressCode: String, @PathVariable promiseId: Long): UserProgressResponse {
return promiseHistoryChangeUseCase.execute(promiseId, progressCode)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.depromeet.whatnow.api.promiseprogress.dto.response

import com.depromeet.whatnow.domains.user.domain.User

data class UserProgressResponse(
val user: User, // 유저 dto 로 치환예정입니당
val currentProgress: PromiseProgressDto,
val beforeProgress: PromiseProgressDto?,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.depromeet.whatnow.api.promiseprogress.usecase

import com.depromeet.whatnow.annotation.UseCase
import com.depromeet.whatnow.api.promiseprogress.dto.response.PromiseProgressDto
import com.depromeet.whatnow.api.promiseprogress.dto.response.UserProgressResponse
import com.depromeet.whatnow.config.security.SecurityUtils
import com.depromeet.whatnow.domains.progresshistory.service.ProgressHistoryDomainService
import com.depromeet.whatnow.domains.promiseprogress.adapter.PromiseProgressAdapter
import com.depromeet.whatnow.domains.user.adapter.UserAdapter

@UseCase
class ProgressHistoryChangeUseCase(
val promiseHistoryDomainService: ProgressHistoryDomainService,
val userAdapter: UserAdapter,
val promiseProgressAdapter: PromiseProgressAdapter,
) {
fun execute(promiseId: Long, progressCode: String): UserProgressResponse {
val userId = SecurityUtils.currentUserId
val user = userAdapter.queryUser(userId)
val newProgress = promiseProgressAdapter.queryByCode(progressCode)
val history = promiseHistoryDomainService.change(promiseId, userId, newProgress.id!!)

val preProgress = promiseProgressAdapter.queryId(history.prePromiseProgressId!!)
return UserProgressResponse(user, PromiseProgressDto.from(newProgress), PromiseProgressDto.from(preProgress))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.depromeet.whatnow.api.promiseprogress.usecase

import com.depromeet.whatnow.annotation.UseCase
import com.depromeet.whatnow.api.promiseprogress.dto.response.PromiseProgressDto
import com.depromeet.whatnow.api.promiseprogress.dto.response.UserProgressResponse
import com.depromeet.whatnow.domains.progresshistory.adapter.ProgressHistoryAdapter
import com.depromeet.whatnow.domains.promiseprogress.adapter.PromiseProgressAdapter
import com.depromeet.whatnow.domains.promiseuser.adaptor.PromiseUserAdaptor
import com.depromeet.whatnow.domains.user.adapter.UserAdapter

@UseCase
class ProgressHistoryReadUseCase(
val progressHistoryAdapter: ProgressHistoryAdapter,
val promiseUserAdapter: PromiseUserAdaptor,
val promiseProgressAdapter: PromiseProgressAdapter,
val userAdapter: UserAdapter,
) {
fun execute(promiseId: Long, userId: Long): UserProgressResponse {
promiseUserAdapter.findByPromiseIdAndUserId(promiseId, userId) // 해당 유저가 있는지 검증을... 함 해야햐긴함!

val history = progressHistoryAdapter.findByPromiseIdAndUserId(promiseId, userId)
val currentProgress = promiseProgressAdapter.queryId(history.currentPromiseProgressId!!)

return history.prePromiseProgressId ?.let {
val preProgress = promiseProgressAdapter.queryId(history.prePromiseProgressId!!)
UserProgressResponse(userAdapter.queryUser(userId), PromiseProgressDto.from(currentProgress), PromiseProgressDto.from(preProgress))
} ?: run {
UserProgressResponse(userAdapter.queryUser(userId), PromiseProgressDto.from(currentProgress), null)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.depromeet.whatnow.annotation

import org.springframework.core.annotation.AliasFor
import org.springframework.stereotype.Component
import kotlin.annotation.Retention

@Target(AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Component
annotation class Handler(@get:AliasFor(annotation = Component::class) val value: String = "")
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const val PROD = "prod"
const val DEV = "dev"
const val LOCAL = "local"
const val WITHDRAW_PREFIX = "withdraw"
const val DEFAULT_PROMISE_PROGRESS: Long = 13

const val IMAGE_DOMAIN = "https://image.whatnow.kr/"

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.depromeet.whatnow.domains.progresshistory.adapter

import com.depromeet.whatnow.annotation.Adapter
import com.depromeet.whatnow.domains.progresshistory.domain.ProgressHistory
import com.depromeet.whatnow.domains.progresshistory.exception.PromiseHistoryNotFoundException
import com.depromeet.whatnow.domains.progresshistory.repository.ProgressHistoryRepository

@Adapter
class ProgressHistoryAdapter(
val promiseHistoryRepository: ProgressHistoryRepository,
) {
fun save(progressHistory: ProgressHistory) {
promiseHistoryRepository.save(progressHistory)
}

fun findByPromiseIdAndUserId(promiseId: Long, userId: Long): ProgressHistory {
return promiseHistoryRepository.findByPromiseIdAndUserId(promiseId, userId)
?: run { throw PromiseHistoryNotFoundException.EXCEPTION }
}
fun delete(progressHistory: ProgressHistory) {
promiseHistoryRepository.delete(progressHistory)
}
// fun findAll(): List<PromiseHistory> {
// return promiseHistoryRepository.findAll()
// }
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.depromeet.whatnow.domains.progresshistory.domain

import com.depromeet.whatnow.consts.DEFAULT_PROMISE_PROGRESS
import com.depromeet.whatnow.domains.progresshistory.exception.PromiseIsSameException
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.GeneratedValue
Expand All @@ -15,12 +17,28 @@ class ProgressHistory(

var userId: Long,

var prePromiseProgressId: Long?,
var currentPromiseProgressId: Long?,

var afterPromiseProgressId: Long?,
var prePromiseProgressId: Long?,

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "progress_history_id")
val id: Long? = null,
)
) {
fun change(progressId: Long) {
if (progressId == currentPromiseProgressId) {
throw PromiseIsSameException.EXCEPTION
}
currentPromiseProgressId?.let { // init default 이지 않을 때
prePromiseProgressId = currentPromiseProgressId
}
currentPromiseProgressId = progressId
}

companion object {
fun of(progressId: Long, userId: Long): ProgressHistory {
return ProgressHistory(progressId, userId, DEFAULT_PROMISE_PROGRESS, null)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.depromeet.whatnow.domains.progresshistory.exception

import com.depromeet.whatnow.annotation.ExplainError
import com.depromeet.whatnow.consts.BAD_REQUEST
import com.depromeet.whatnow.consts.NOT_FOUND
import com.depromeet.whatnow.dto.ErrorReason
import com.depromeet.whatnow.exception.BaseErrorCode
import java.util.*

enum class PromiseHistoryErrorCode(val status: Int, val code: String, val reason: String) : BaseErrorCode {

@ExplainError("약속 히스토리 정보를 찾을 수 없는 경우")
PROMISE_HISTORY_NOT_FOUND(NOT_FOUND, "PROMISE_HISTORY_404_1", "약속 히스토리 정보를 찾을 수 없습니다."),

@ExplainError("변경하려는 약속 단계가 동일할 경우")
PROMISE_PROGRESS_IS_SAME(BAD_REQUEST, "PROMISE_HISTORY_400_1", "변경하려는 약속 단계가 동일합니다."),

;

override val errorReason: ErrorReason
get() { return ErrorReason(status, code, reason) }

override val explainError: String
get() {
val field = this.javaClass.getField(name)
val annotation = field.getAnnotation(ExplainError::class.java)
return if (Objects.nonNull(annotation)) annotation.value else reason
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.depromeet.whatnow.domains.progresshistory.exception

import com.depromeet.whatnow.exception.WhatnowCodeException

class PromiseHistoryNotFoundException : WhatnowCodeException(
PromiseHistoryErrorCode.PROMISE_HISTORY_NOT_FOUND,
) {
companion object {
val EXCEPTION: WhatnowCodeException = PromiseHistoryNotFoundException()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.depromeet.whatnow.domains.progresshistory.exception

import com.depromeet.whatnow.exception.WhatnowCodeException

class PromiseIsSameException : WhatnowCodeException(
PromiseHistoryErrorCode.PROMISE_PROGRESS_IS_SAME,
) {
companion object {
val EXCEPTION: WhatnowCodeException = PromiseIsSameException()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.depromeet.whatnow.domains.progresshistory.handler

import com.depromeet.whatnow.annotation.Handler
import com.depromeet.whatnow.domains.progresshistory.service.ProgressHistoryDomainService
import com.depromeet.whatnow.events.domainEvent.PromiseUserCancelEvent
import mu.KLogger
import mu.KotlinLogging
import org.springframework.transaction.event.TransactionPhase
import org.springframework.transaction.event.TransactionalEventListener

@Handler
class PromiseUserRegisterHistoryCancelHandler(
val progressHistoryDomainService: ProgressHistoryDomainService,
) {
val logger: KLogger = KotlinLogging.logger {}

@TransactionalEventListener(classes = [PromiseUserCancelEvent::class], phase = TransactionPhase.AFTER_COMMIT)
fun handleDoneOrderEvent(event: PromiseUserCancelEvent) {
logger.info { "PromiseUserRegisterHistoryCancelHandler 이벤트 수신 ${event.promiseId} , 유저아이디 ${event.userId}" }

progressHistoryDomainService.deleteHistory(event.promiseId, event.userId)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.depromeet.whatnow.domains.progresshistory.handler

import com.depromeet.whatnow.annotation.Handler
import com.depromeet.whatnow.domains.progresshistory.service.ProgressHistoryDomainService
import com.depromeet.whatnow.events.domainEvent.PromiseUserRegisterEvent
import mu.KLogger
import mu.KotlinLogging
import org.springframework.transaction.event.TransactionPhase
import org.springframework.transaction.event.TransactionalEventListener

@Handler
class PromiseUserRegisterHistoryInitHandler(
val progressHistoryDomainService: ProgressHistoryDomainService,
) {
val logger: KLogger = KotlinLogging.logger {}

@TransactionalEventListener(classes = [PromiseUserRegisterEvent::class], phase = TransactionPhase.AFTER_COMMIT)
fun handleDoneOrderEvent(event: PromiseUserRegisterEvent) {
logger.info { "PromiseUserRegisterHistoryInitHandler 이벤트 수신 ${event.promiseId} , 유저아이디 ${event.userId}" }

progressHistoryDomainService.initHistory(event.promiseId, event.userId)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.depromeet.whatnow.domains.progresshistory.repository

import com.depromeet.whatnow.domains.progresshistory.domain.ProgressHistory
import org.springframework.data.jpa.repository.JpaRepository

interface ProgressHistoryRepository : JpaRepository<ProgressHistory, Long> {
fun findByPromiseIdAndUserId(promiseId: Long, userId: Long): ProgressHistory?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.depromeet.whatnow.domains.progresshistory.service

import com.depromeet.whatnow.annotation.DomainService
import com.depromeet.whatnow.domains.progresshistory.adapter.ProgressHistoryAdapter
import com.depromeet.whatnow.domains.progresshistory.domain.ProgressHistory
import org.springframework.transaction.annotation.Transactional

@DomainService
class ProgressHistoryDomainService(
val progressHistoryAdapter: ProgressHistoryAdapter,
) {

fun initHistory(promiseId: Long, userId: Long) {
progressHistoryAdapter.save(ProgressHistory.of(promiseId, userId))
}

fun deleteHistory(promiseId: Long, userId: Long) {
val history = progressHistoryAdapter.findByPromiseIdAndUserId(promiseId, userId)
progressHistoryAdapter.delete(history)
}

@Transactional
fun change(promiseId: Long, userId: Long, progressCode: Long): ProgressHistory {
val history = progressHistoryAdapter.findByPromiseIdAndUserId(promiseId, userId)
history.change(progressCode)
return history
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.depromeet.whatnow.annotation.Adapter
import com.depromeet.whatnow.domains.promiseprogress.domain.PromiseProgress
import com.depromeet.whatnow.domains.promiseprogress.exception.PromiseProgressNotFoundException
import com.depromeet.whatnow.domains.promiseprogress.repository.PromiseProgressRepository
import org.springframework.data.repository.findByIdOrNull

@Adapter
class PromiseProgressAdapter(
Expand All @@ -17,4 +18,10 @@ class PromiseProgressAdapter(
return promiseProgressRepository.findByCode(code)
?: run { throw PromiseProgressNotFoundException.EXCEPTION }
}

fun queryId(progressId: Long): PromiseProgress {
return promiseProgressRepository.findByIdOrNull(progressId) ?: run {
throw PromiseProgressNotFoundException.EXCEPTION
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class PromiseUser(
@PostUpdate
fun cancelPromiseUser() {
this.promiseUserType = PromiseUserType.CANCEL
Events.raise(PromiseUserCancelEvent(this.id!!))
Events.raise(PromiseUserCancelEvent(this.promiseId, this.userId, this.id!!))
}

@PostPersist
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ package com.depromeet.whatnow.events.domainEvent
import com.depromeet.whatnow.common.aop.event.DomainEvent

class PromiseUserCancelEvent(
promiseUserId: Long,
val promiseId: Long,
val userId: Long,
val promiseUserId: Long,
) : DomainEvent()
Loading

0 comments on commit c40a2db

Please sign in to comment.