Skip to content

Commit

Permalink
Merge pull request #26 from Leets-Official/feat/#25
Browse files Browse the repository at this point in the history
feat: 초대장 정보 조회 기능 구현
  • Loading branch information
yechan-kim authored Jan 28, 2025
2 parents c09a728 + f234d62 commit 43da6e6
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import site.yourevents.guest.domain.GuestVO
import site.yourevents.guest.exception.GuestNotFoundException
import site.yourevents.guest.port.`in`.GuestUseCase
import site.yourevents.guest.port.out.GuestPersistencePort
import site.yourevents.invitation.exception.InvitationNotFoundException
import site.yourevents.invitation.port.`in`.InvitationUseCase
import site.yourevents.member.domain.Member
import site.yourevents.member.exception.MemberNotFountException
Expand Down Expand Up @@ -36,7 +35,6 @@ class GuestService(
?: throw MemberNotFountException()

val invitation = invitationUseCase.findById(invitationId)
?: throw InvitationNotFoundException()

return guestPersistencePort.save(
GuestVO(
Expand All @@ -59,7 +57,6 @@ class GuestService(
?: throw MemberNotFountException()

val invitation = invitationUseCase.findById(invitationId)
?: throw InvitationNotFoundException()

if (guestId == null) {
guestPersistencePort.save(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface InvitationUseCase {

fun updateQrCode(invitationId: UUID): Invitation

fun findById(id: UUID): Invitation?
fun findById(id: UUID): Invitation

fun getQrCodeUrl(id: UUID): String

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class InvitationService(

override fun updateQrCode(invitationId: UUID): Invitation {
val invitation = findById(invitationId)
?: throw InvitationNotFoundException()

val qrCode = qrCodeUseCase.generateQrCode(invitationId)

Expand All @@ -49,20 +48,18 @@ class InvitationService(
return invitationPersistencePort.save(invitation)
}

override fun findById(id: UUID): Invitation? {
return invitationPersistencePort.findById(id)
}
override fun findById(id: UUID): Invitation =
invitationPersistencePort.findById(id)
?: throw InvitationNotFoundException()

override fun getQrCodeUrl(id: UUID): String {
val invitation = findById(id)
?: throw InvitationNotFoundException()

return invitation.qrUrl
}

override fun markInvitationAsDeleted(invitationId: UUID) {
val invitation = findById(invitationId)
?: throw InvitationNotFoundException()

invitation.markAsDeleted()
invitationPersistencePort.save(invitation)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package site.yourevents.invitation.service

import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.DescribeSpec
import io.kotest.matchers.shouldBe
import io.mockk.*
import site.yourevents.invitation.domain.Invitation
import site.yourevents.invitation.domain.InvitationVO
import site.yourevents.invitation.exception.InvitationNotFoundException
import site.yourevents.invitation.port.out.InvitationPersistencePort
import site.yourevents.member.domain.Member
import site.yourevents.member.port.`in`.MemberUseCase
Expand Down Expand Up @@ -144,8 +146,9 @@ class InvitationServiceTest : DescribeSpec({
it("존재하지 않는 InvitationId면 null을 반환해야 한다") {
every { invitationPersistencePort.findById(invitationId) } returns null

val result = invitationService.findById(invitationId)
result shouldBe null
shouldThrow<InvitationNotFoundException> {
invitationService.findById(invitationId)
}

verify(exactly = 1) {
invitationPersistencePort.findById(invitationId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ interface GuestJPARepository : JpaRepository<GuestEntity, UUID> {
@Query(
"SELECT COUNT(g) " +
"FROM guest g " +
"WHERE g.member = :member " +
"AND g.invitation.member <> :member " +
"WHERE g.member = :memberEntity " +
"AND g.invitation.member <> :memberEntity " +
"AND g.invitation.deleted = false"
)
fun getReceivedInvitationCount(memberEntity: MemberEntity): Int
Expand All @@ -21,8 +21,8 @@ interface GuestJPARepository : JpaRepository<GuestEntity, UUID> {
"SELECT DISTINCT i " +
"FROM guest g " +
"JOIN g.invitation i " +
"WHERE g.member = :member " +
"AND i.member <> :member " +
"WHERE g.member = :memberEntity " +
"AND i.member <> :memberEntity " +
"AND i.deleted = false"
)
fun getReceivedInvitations(memberEntity: MemberEntity): List<InvitationEntity>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package site.yourevents.common

import org.slf4j.LoggerFactory
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.ExceptionHandler
Expand All @@ -10,12 +11,16 @@ import site.yourevents.type.ErrorCode

@RestControllerAdvice
class GlobalExceptionHandler {
private val log = LoggerFactory.getLogger(this.javaClass)!!

@ExceptionHandler(ServiceException::class)
fun handleCustomException(
e: ServiceException
): ResponseEntity<ApiResponse<Unit>> {
val errorCode: ErrorCode = e.errorCode

log.warn("Exception occurred. HTTP Status: {}, Code: {}, Message: {}", errorCode.httpStatus, errorCode.code, errorCode.message)

return ResponseEntity(
ApiResponse.error(errorCode), HttpStatus.valueOf(errorCode.httpStatus)
)
Expand All @@ -27,6 +32,9 @@ class GlobalExceptionHandler {
): ResponseEntity<ApiResponse<Unit>> {
val errorCode = ErrorCode.INTERNAL_SERVER_ERROR

log.error("{}", e.message)
e.printStackTrace()

return ResponseEntity(
ApiResponse.error(errorCode), HttpStatus.valueOf(errorCode.httpStatus)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import site.yourevents.invitation.dto.request.CreateInvitationRequest
import site.yourevents.invitation.dto.response.CreateInvitationResponse
import site.yourevents.invitation.dto.response.InvitationInfoResponse
import site.yourevents.invitation.dto.response.InvitationQrResponse
import site.yourevents.principal.AuthDetails
import site.yourevents.response.ApiResponse
Expand All @@ -37,4 +38,10 @@ interface InvitationApi {
@PathVariable invitationId: UUID,
@AuthenticationPrincipal authDetails: AuthDetails
): ApiResponse<Unit>

@Operation(summary = "초대장 조회")
@GetMapping("/{invitationId}")
fun getInvitation(
@PathVariable invitationId: UUID
): ApiResponse<InvitationInfoResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import site.yourevents.invitation.dto.request.CreateInvitationRequest
import site.yourevents.invitation.dto.response.CreateInvitationResponse
import site.yourevents.invitation.dto.response.InvitationInfoResponse
import site.yourevents.invitation.dto.response.InvitationQrResponse
import site.yourevents.invitation.facade.InvitationFacade
import site.yourevents.principal.AuthDetails
Expand Down Expand Up @@ -39,4 +40,10 @@ class InvitationController(
invitationFacade.deleteInvitation(invitationId, authDetails)
return ApiResponse.success(SuccessCode.REQUEST_OK)
}

override fun getInvitation(
@PathVariable invitationId: UUID
): ApiResponse<InvitationInfoResponse> = ApiResponse.success(
SuccessCode.REQUEST_OK, invitationFacade.getInvitation(invitationId)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import java.util.UUID

data class InvitationInfoResponse(
val invitationId: UUID,
var createDate: LocalDateTime?,
var title: String,
var schedule: LocalDateTime,
var location: String,
var thumbnailUrl: String,
val createDate: LocalDateTime?,
val title: String,
val schedule: LocalDateTime,
val location: String,
val thumbnailUrl: String,
val remark: String,

) {
companion object {
fun of(
Expand All @@ -26,6 +28,7 @@ data class InvitationInfoResponse(
invitationInformation.schedule,
invitationInformation.location,
invitationThumbnail.url,
invitationInformation.remark,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import org.springframework.stereotype.Service
import site.yourevents.guest.port.`in`.GuestUseCase
import site.yourevents.invitation.dto.request.CreateInvitationRequest
import site.yourevents.invitation.dto.response.CreateInvitationResponse
import site.yourevents.invitation.dto.response.InvitationInfoResponse
import site.yourevents.invitation.dto.response.InvitationQrResponse
import site.yourevents.invitation.exception.InvitationNotFoundException
import site.yourevents.invitation.exception.UnauthorizedException
import site.yourevents.invitation.port.`in`.InvitationUseCase
import site.yourevents.invitationinformation.port.`in`.InvitationInformationUseCase
Expand All @@ -26,7 +26,7 @@ class InvitationFacade(

fun createInvitation(
createInvitationRequest: CreateInvitationRequest,
authDetails: AuthDetails
authDetails: AuthDetails,
): CreateInvitationResponse {
val memberId = authDetails.uuid

Expand All @@ -43,18 +43,31 @@ class InvitationFacade(

fun deleteInvitation(
invitationId: UUID,
authDetails: AuthDetails
authDetails: AuthDetails,
) {
val invitation = invitationUseCase.findById(invitationId)
?: throw InvitationNotFoundException()

if(invitation.member.getId() != authDetails.uuid){
if (invitation.member.getId() != authDetails.uuid) {
throw UnauthorizedException()
}

invitationUseCase.markInvitationAsDeleted(invitationId)
}

fun getInvitation(invitationId: UUID): InvitationInfoResponse {
val invitation = invitationUseCase.findById(invitationId)

val invitationInformation = invitationInformationUseCase.findByInvitation(invitation)

val invitationThumbnail = invitationThumbnailUseCase.findByInvitation(invitation)

return InvitationInfoResponse.of(
invitation,
invitationInformation,
invitationThumbnail
)
}

private fun generateInvitation(memberId: UUID) =
invitationUseCase.createInvitation(memberId, null.toString())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import site.yourevents.guest.port.`in`.GuestUseCase
import site.yourevents.invitation.domain.Invitation
import site.yourevents.invitation.dto.request.CreateInvitationRequest
import site.yourevents.invitation.dto.response.CreateInvitationResponse
import site.yourevents.invitation.dto.response.InvitationInfoResponse
import site.yourevents.invitation.port.`in`.InvitationUseCase
import site.yourevents.invitationinformation.domain.InvitationInformation
import site.yourevents.invitationinformation.port.`in`.InvitationInformationUseCase
Expand Down Expand Up @@ -138,6 +139,7 @@ class InvitationFacadeTest : DescribeSpec({
)
}
}

context("deleteInvitation 메서드가 호출되었을 때") {
it("존재하는 초대장 삭제(soft delete)를 완료해야 한다") {
every { invitationUseCase.findById(invitationId) } returns invitation
Expand All @@ -151,5 +153,23 @@ class InvitationFacadeTest : DescribeSpec({
confirmVerified(invitationUseCase)
}
}

context("getInvitation 메서드가 호출되었을 때") {
it("존재하는 초대장 정보를 반환해야 한다") {
every { invitationUseCase.findById(invitationId) } returns invitation
every { invitationInformationUseCase.findByInvitation(invitation) } returns invitationInformation
every { invitationThumbnailUseCase.findByInvitation(invitation) } returns invitationThumbnail

val response = invitationFacade.getInvitation(invitationId)

response.shouldBe(
InvitationInfoResponse.of(
invitation = invitation,
invitationInformation = invitationInformation,
invitationThumbnail = invitationThumbnail
)
)
}
}
}
})

0 comments on commit 43da6e6

Please sign in to comment.