From 201cdd796ad12051eda2639fcb6a31fab68db8c5 Mon Sep 17 00:00:00 2001 From: le2sky Date: Sun, 27 Aug 2023 19:52:11 +0900 Subject: [PATCH 1/9] =?UTF-8?q?refactor=20:=20getter=20=EC=98=A4=ED=94=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reservation/domain/reservation/Reservation.kt | 9 ++++++--- .../domain/reservation/ReservationLineItem.kt | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/mealkitary-domain/src/main/kotlin/com/mealkitary/reservation/domain/reservation/Reservation.kt b/mealkitary-domain/src/main/kotlin/com/mealkitary/reservation/domain/reservation/Reservation.kt index 5188199..cd04037 100644 --- a/mealkitary-domain/src/main/kotlin/com/mealkitary/reservation/domain/reservation/Reservation.kt +++ b/mealkitary-domain/src/main/kotlin/com/mealkitary/reservation/domain/reservation/Reservation.kt @@ -40,14 +40,17 @@ class Reservation private constructor( @CollectionTable( name = "reservation_line_item", joinColumns = [JoinColumn(name = "reservation_id")] ) - private val lineItems: MutableList = lineItems + var lineItems: MutableList = lineItems + protected set @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "shop_id", nullable = false) - private val shop: Shop = shop + var shop: Shop = shop + protected set @Column(nullable = false) - private val reserveAt: LocalDateTime = reserveAt + var reserveAt: LocalDateTime = reserveAt + protected set @Column(nullable = false) @Enumerated(EnumType.STRING) diff --git a/mealkitary-domain/src/main/kotlin/com/mealkitary/reservation/domain/reservation/ReservationLineItem.kt b/mealkitary-domain/src/main/kotlin/com/mealkitary/reservation/domain/reservation/ReservationLineItem.kt index 5a2995c..2b4bc69 100644 --- a/mealkitary-domain/src/main/kotlin/com/mealkitary/reservation/domain/reservation/ReservationLineItem.kt +++ b/mealkitary-domain/src/main/kotlin/com/mealkitary/reservation/domain/reservation/ReservationLineItem.kt @@ -17,17 +17,20 @@ class ReservationLineItem private constructor( ) { @Embedded - private val itemId: ProductId = itemId + var itemId: ProductId = itemId + protected set @Column(nullable = false) var name: String = name protected set @Embedded - private val price: Money = price + var price: Money = price + protected set @Column(nullable = false) - private val count: Int = count + var count: Int = count + protected set fun mapToProduct(): Product { return Product( From 4e4180c63fa95f500cb027a33a20935120745043 Mon Sep 17 00:00:00 2001 From: le2sky Date: Sun, 27 Aug 2023 19:53:13 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat=20:=20=EC=98=88=EC=95=BD=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=EC=98=81=EC=86=8D=EC=84=B1=20?= =?UTF-8?q?=EC=96=B4=EB=8C=91=ED=84=B0=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../persistence/ReservationRepository.kt | 8 +++++- ...ingDataJpaReservationPersistenceAdapter.kt | 23 ++++++++++++++++ ...ataJpaReservationPersistenceAdapterTest.kt | 26 +++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/adapter/output/persistence/ReservationRepository.kt b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/adapter/output/persistence/ReservationRepository.kt index ef31784..f46b295 100644 --- a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/adapter/output/persistence/ReservationRepository.kt +++ b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/adapter/output/persistence/ReservationRepository.kt @@ -1,7 +1,13 @@ package com.mealkitary.reservation.adapter.output.persistence import com.mealkitary.reservation.domain.reservation.Reservation +import org.springframework.data.jpa.repository.EntityGraph import org.springframework.data.jpa.repository.JpaRepository +import java.util.Optional import java.util.UUID -interface ReservationRepository : JpaRepository +interface ReservationRepository : JpaRepository { + + @EntityGraph(attributePaths = ["shop"]) + fun findOneWithShopById(reservationId: UUID): Optional +} diff --git a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/adapter/output/persistence/SpringDataJpaReservationPersistenceAdapter.kt b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/adapter/output/persistence/SpringDataJpaReservationPersistenceAdapter.kt index 0dea076..fe59ad1 100644 --- a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/adapter/output/persistence/SpringDataJpaReservationPersistenceAdapter.kt +++ b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/adapter/output/persistence/SpringDataJpaReservationPersistenceAdapter.kt @@ -1,6 +1,8 @@ package com.mealkitary.reservation.adapter.output.persistence import com.mealkitary.common.exception.EntityNotFoundException +import com.mealkitary.reservation.application.port.input.ReservationResponse +import com.mealkitary.reservation.application.port.input.ReservedProduct import com.mealkitary.reservation.application.port.output.LoadReservationPort import com.mealkitary.reservation.application.port.output.SavePaymentPort import com.mealkitary.reservation.application.port.output.SaveReservationPort @@ -33,4 +35,25 @@ class SpringDataJpaReservationPersistenceAdapter( return reservationRepository.findById(reservationId) .orElseThrow { throw EntityNotFoundException(NOT_FOUND_RESERVATION_MESSAGE) } } + + override fun queryOneReservationById(reservationId: UUID): ReservationResponse { + val reservation = reservationRepository.findOneWithShopById(reservationId) + .orElseThrow { throw EntityNotFoundException(NOT_FOUND_RESERVATION_MESSAGE) } + + return ReservationResponse( + reservation.id, + reservation.shop.title, + reservation.buildDescription(), + reservation.reserveAt, + reservation.reservationStatus.name, + reservation.lineItems.map { + ReservedProduct( + it.itemId.id, + it.name, + it.price.value, + it.count + ) + } + ) + } } diff --git a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/reservation/adapter/output/persistence/SpringDataJpaReservationPersistenceAdapterTest.kt b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/reservation/adapter/output/persistence/SpringDataJpaReservationPersistenceAdapterTest.kt index 266f9a1..fd0fc2b 100644 --- a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/reservation/adapter/output/persistence/SpringDataJpaReservationPersistenceAdapterTest.kt +++ b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/reservation/adapter/output/persistence/SpringDataJpaReservationPersistenceAdapterTest.kt @@ -71,10 +71,36 @@ class SpringDataJpaReservationPersistenceAdapterTest( result.reservationStatus shouldBe ReservationStatus.NOTPAID } + @Test + fun `db integration test - 예약의 상세 정보를 조회한다`() { + val reservation = ReservationTestData.defaultReservation() + .withReservationStatus(ReservationStatus.NOTPAID) + .withShop(shopRepository.findOneWithProductsById(1L).orElseThrow()) + .build() + val saved = adapterUnderTest.saveOne(reservation) + em.flush() + em.clear() + + val result = adapterUnderTest.queryOneReservationById(saved) + + result.reservationId shouldBe saved + result.status shouldBe "NOTPAID" + result.shopName shouldBe "집밥뚝딱 철산점" + result.reservedProduct.size shouldBe 2 + result.description shouldBe "부대찌개 외 1건" + } + @Test fun `db integration test - 예약 ID에 해당하는 예약을 조회할 때, 해당 예약이 존재하지 않으면 예외를 발생한다`() { shouldThrow { adapterUnderTest.loadOneReservationById(UUID.randomUUID()) } shouldHaveMessage "존재하지 않는 예약입니다." } + + @Test + fun `db integration test - 예약 ID를 이용해 예약의 상세 정보를 조회할 때, 해당 예약이 존재하지 않으면 예외를 발생한다`() { + shouldThrow { + adapterUnderTest.queryOneReservationById(UUID.randomUUID()) + } shouldHaveMessage "존재하지 않는 예약입니다." + } } From 68b4e5edf828d555f568a1f186f593aa12e0cab5 Mon Sep 17 00:00:00 2001 From: le2sky Date: Sun, 27 Aug 2023 19:54:06 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat=20:=20=EC=98=88=EC=95=BD=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/input/GetReservationQuery.kt | 8 ++++ .../port/input/ReservationResponse.kt | 13 +++++++ .../port/output/LoadReservationPort.kt | 3 ++ .../service/GetReservationService.kt | 17 ++++++++ .../service/GetReservationServiceTest.kt | 39 +++++++++++++++++++ 5 files changed, 80 insertions(+) create mode 100644 mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/GetReservationQuery.kt create mode 100644 mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/ReservationResponse.kt create mode 100644 mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/service/GetReservationService.kt create mode 100644 mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/GetReservationServiceTest.kt diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/GetReservationQuery.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/GetReservationQuery.kt new file mode 100644 index 0000000..12bd50a --- /dev/null +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/GetReservationQuery.kt @@ -0,0 +1,8 @@ +package com.mealkitary.reservation.application.port.input + +import java.util.UUID + +interface GetReservationQuery { + + fun loadOneReservationById(reservationId: UUID): ReservationResponse +} diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/ReservationResponse.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/ReservationResponse.kt new file mode 100644 index 0000000..06cdb65 --- /dev/null +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/ReservationResponse.kt @@ -0,0 +1,13 @@ +package com.mealkitary.reservation.application.port.input + +import java.time.LocalDateTime +import java.util.UUID + +data class ReservationResponse( + val reservationId: UUID, + val shopName: String, + val description: String, + val reserveAt: LocalDateTime, + val status: String, + val reservedProduct: List +) diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/output/LoadReservationPort.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/output/LoadReservationPort.kt index 932d925..61eb16c 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/output/LoadReservationPort.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/output/LoadReservationPort.kt @@ -1,9 +1,12 @@ package com.mealkitary.reservation.application.port.output +import com.mealkitary.reservation.application.port.input.ReservationResponse import com.mealkitary.reservation.domain.reservation.Reservation import java.util.UUID interface LoadReservationPort { fun loadOneReservationById(reservationId: UUID): Reservation + + fun queryOneReservationById(reservationId: UUID): ReservationResponse } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/service/GetReservationService.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/service/GetReservationService.kt new file mode 100644 index 0000000..5e39ba3 --- /dev/null +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/service/GetReservationService.kt @@ -0,0 +1,17 @@ +package com.mealkitary.reservation.application.service + +import com.mealkitary.reservation.application.port.input.GetReservationQuery +import com.mealkitary.reservation.application.port.output.LoadReservationPort +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.util.UUID + +@Service +@Transactional(readOnly = true) +class GetReservationService( + private val loadReservationPort: LoadReservationPort +) : GetReservationQuery { + + override fun loadOneReservationById(reservationId: UUID) = + loadReservationPort.queryOneReservationById(reservationId) +} diff --git a/mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/GetReservationServiceTest.kt b/mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/GetReservationServiceTest.kt new file mode 100644 index 0000000..8fbf2c5 --- /dev/null +++ b/mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/GetReservationServiceTest.kt @@ -0,0 +1,39 @@ +package com.mealkitary.reservation.application.service + +import com.mealkitary.reservation.application.port.input.ReservationResponse +import com.mealkitary.reservation.application.port.output.LoadReservationPort +import io.kotest.core.spec.style.AnnotationSpec +import io.kotest.matchers.booleans.shouldBeTrue +import io.kotest.matchers.shouldBe +import io.mockk.every +import io.mockk.mockk +import java.time.LocalDateTime +import java.util.UUID + +class GetReservationServiceTest : AnnotationSpec() { + + private val loadReservationPort = mockk() + private val getReservationService = GetReservationService(loadReservationPort) + + @Test + fun `service unit test - 예약의 상세 정보를 조회한다`() { + val reservationId = UUID.randomUUID() + every { loadReservationPort.queryOneReservationById(any()) } answers { + ReservationResponse( + reservationId, + "집밥뚝딱 안양점", + "부대찌개 외 1건", + LocalDateTime.now(), + "PAID", + emptyList() + ) + } + + val result = getReservationService.loadOneReservationById(reservationId) + + result.reservationId shouldBe reservationId + result.shopName shouldBe "집밥뚝딱 안양점" + result.status shouldBe "PAID" + result.reservedProduct.isEmpty().shouldBeTrue() + } +} From a05080f8db9273fdc977661edb576e1eb557558b Mon Sep 17 00:00:00 2001 From: le2sky Date: Sun, 27 Aug 2023 20:35:28 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat=20:=20=EC=98=88=EC=95=BD=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../input/web/GetReservationController.kt | 19 +++++ .../mealkitary/WebIntegrationTestSupport.kt | 6 ++ .../input/web/GetReservationControllerTest.kt | 84 +++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 mealkitary-api/src/main/kotlin/com/mealkitary/reservation/adapter/input/web/GetReservationController.kt create mode 100644 mealkitary-api/src/test/kotlin/com/mealkitary/reservation/adapter/input/web/GetReservationControllerTest.kt diff --git a/mealkitary-api/src/main/kotlin/com/mealkitary/reservation/adapter/input/web/GetReservationController.kt b/mealkitary-api/src/main/kotlin/com/mealkitary/reservation/adapter/input/web/GetReservationController.kt new file mode 100644 index 0000000..d86c7a5 --- /dev/null +++ b/mealkitary-api/src/main/kotlin/com/mealkitary/reservation/adapter/input/web/GetReservationController.kt @@ -0,0 +1,19 @@ +package com.mealkitary.reservation.adapter.input.web + +import com.mealkitary.common.utils.UUIDUtils +import com.mealkitary.reservation.application.port.input.GetReservationQuery +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/reservations") +class GetReservationController( + private val getReservationQuery: GetReservationQuery +) { + + @GetMapping("/{reservationId}") + fun getOneReservation(@PathVariable("reservationId") reservationId: String) = + getReservationQuery.loadOneReservationById(UUIDUtils.fromString(reservationId)) +} diff --git a/mealkitary-api/src/test/kotlin/com/mealkitary/WebIntegrationTestSupport.kt b/mealkitary-api/src/test/kotlin/com/mealkitary/WebIntegrationTestSupport.kt index e552f5e..2d4aaba 100644 --- a/mealkitary-api/src/test/kotlin/com/mealkitary/WebIntegrationTestSupport.kt +++ b/mealkitary-api/src/test/kotlin/com/mealkitary/WebIntegrationTestSupport.kt @@ -2,9 +2,11 @@ package com.mealkitary import com.fasterxml.jackson.databind.ObjectMapper import com.mealkitary.reservation.adapter.input.web.AcceptReservationController +import com.mealkitary.reservation.adapter.input.web.GetReservationController import com.mealkitary.reservation.adapter.input.web.PayReservationController import com.mealkitary.reservation.adapter.input.web.ReserveProductController import com.mealkitary.reservation.application.port.input.AcceptReservationUseCase +import com.mealkitary.reservation.application.port.input.GetReservationQuery import com.mealkitary.reservation.application.port.input.PayReservationUseCase import com.mealkitary.reservation.application.port.input.ReserveProductUseCase import com.mealkitary.shop.adapter.input.web.GetProductController @@ -25,6 +27,7 @@ import org.springframework.test.web.servlet.MockMvc ReserveProductController::class, PayReservationController::class, AcceptReservationController::class, + GetReservationController::class, GetShopController::class, GetReservableTimeController::class, GetProductController::class @@ -49,6 +52,9 @@ abstract class WebIntegrationTestSupport : AnnotationSpec() { @MockkBean protected lateinit var acceptReservationUseCase: AcceptReservationUseCase + @MockkBean + protected lateinit var getReservationQuery: GetReservationQuery + @MockkBean protected lateinit var getShopQuery: GetShopQuery diff --git a/mealkitary-api/src/test/kotlin/com/mealkitary/reservation/adapter/input/web/GetReservationControllerTest.kt b/mealkitary-api/src/test/kotlin/com/mealkitary/reservation/adapter/input/web/GetReservationControllerTest.kt new file mode 100644 index 0000000..2cedc7b --- /dev/null +++ b/mealkitary-api/src/test/kotlin/com/mealkitary/reservation/adapter/input/web/GetReservationControllerTest.kt @@ -0,0 +1,84 @@ +package com.mealkitary.reservation.adapter.input.web + +import com.mealkitary.WebIntegrationTestSupport +import com.mealkitary.common.exception.EntityNotFoundException +import com.mealkitary.reservation.application.port.input.ReservationResponse +import com.mealkitary.reservation.application.port.input.ReservedProduct +import io.mockk.every +import org.springframework.http.MediaType +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import java.time.LocalDateTime +import java.util.UUID + +class GetReservationControllerTest : WebIntegrationTestSupport() { + + @Test + fun `api integration test - getOneReservation`() { + val reservationId = UUID.randomUUID() + val reserveAt = LocalDateTime.now() + every { getReservationQuery.loadOneReservationById(reservationId) } answers { + ReservationResponse( + reservationId, + "집밥뚝딱 안양점", + "부대찌개 외 1건", + reserveAt, + "PAID", + listOf( + ReservedProduct( + 1L, + "부대찌개", + 20000, + 2 + ), + ReservedProduct( + 2L, + "김치찌개", + 20000, + 1 + ) + ) + ) + } + + mvc.perform(get("/reservations/{reservationId}", reservationId)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$.reservationId").value(reservationId.toString())) + .andExpect(jsonPath("$.shopName").value("집밥뚝딱 안양점")) + .andExpect(jsonPath("$.reserveAt").value(reserveAt.toString())) + .andExpect(jsonPath("$.status").value("PAID")) + .andExpect(jsonPath("$.reservedProduct[0].productId").value(1L)) + .andExpect(jsonPath("$.reservedProduct[0].name").value("부대찌개")) + .andExpect(jsonPath("$.reservedProduct[0].price").value(20000)) + .andExpect(jsonPath("$.reservedProduct[0].count").value(2)) + .andExpect(jsonPath("$.reservedProduct[1].productId").value(2L)) + .andExpect(jsonPath("$.reservedProduct[1].name").value("김치찌개")) + .andExpect(jsonPath("$.reservedProduct[1].price").value(20000)) + .andExpect(jsonPath("$.reservedProduct[1].count").value(1)) + } + + @Test + fun `api integration test - 예약 식별자가 UUID 형태가 아니라면 400 에러를 발생한다`() { + mvc.perform( + get("/reservations/{reservationId}", "invalid-uuid-test") + ) + .andExpect(status().isBadRequest) + .andExpect(jsonPath("$.status").value("400")) + .andExpect(jsonPath("$.message").value("잘못된 UUID 형식입니다.")) + } + + @Test + fun `api integration test - 내부에서 EntityNotFound 에러가 발생하면 404 에러를 발생한다`() { + every { getReservationQuery.loadOneReservationById(any()) } + .throws(EntityNotFoundException("존재하지 않는 예약입니다.")) + + mvc.perform(get("/reservations/{reservationId}", UUID.randomUUID())) + .andExpect(status().isNotFound()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$.status").value(404)) + .andExpect(jsonPath("$.message").value("존재하지 않는 예약입니다.")) + } +} From 59a8cb6b0b0d053a0b75ba81aad3f9a591968227 Mon Sep 17 00:00:00 2001 From: le2sky Date: Sun, 27 Aug 2023 22:20:01 +0900 Subject: [PATCH 5/9] =?UTF-8?q?test=20:=20=EC=98=88=EC=95=BD=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GetReservationControllerDocsTest.kt | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 mealkitary-api/src/test/kotlin/com/docs/reservation/GetReservationControllerDocsTest.kt diff --git a/mealkitary-api/src/test/kotlin/com/docs/reservation/GetReservationControllerDocsTest.kt b/mealkitary-api/src/test/kotlin/com/docs/reservation/GetReservationControllerDocsTest.kt new file mode 100644 index 0000000..8b7db99 --- /dev/null +++ b/mealkitary-api/src/test/kotlin/com/docs/reservation/GetReservationControllerDocsTest.kt @@ -0,0 +1,88 @@ +package com.docs.reservation + +import com.docs.RestDocsSupport +import com.mealkitary.reservation.adapter.input.web.GetReservationController +import com.mealkitary.reservation.application.port.input.GetReservationQuery +import com.mealkitary.reservation.application.port.input.ReservationResponse +import com.mealkitary.reservation.application.port.input.ReservedProduct +import io.mockk.every +import io.mockk.mockk +import org.springframework.http.MediaType +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders +import org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest +import org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse +import org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint +import org.springframework.restdocs.payload.JsonFieldType +import org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath +import org.springframework.restdocs.payload.PayloadDocumentation.responseFields +import org.springframework.restdocs.request.RequestDocumentation.parameterWithName +import org.springframework.restdocs.request.RequestDocumentation.pathParameters +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import java.time.LocalDateTime +import java.util.UUID + +class GetReservationControllerDocsTest : RestDocsSupport() { + + private val getReservationQuery = mockk() + + @Test + fun `api docs test - getOneReservation`() { + val reservationId = UUID.randomUUID() + val reserveAt = LocalDateTime.now() + every { getReservationQuery.loadOneReservationById(reservationId) } answers { + ReservationResponse( + reservationId, + "집밥뚝딱 안양점", + "부대찌개 외 1건", + reserveAt, + "PAID", + listOf( + ReservedProduct( + 1L, + "부대찌개", + 20000, + 2 + ), + ReservedProduct( + 2L, + "김치찌개", + 20000, + 1 + ) + ) + ) + } + + mvc.perform(RestDocumentationRequestBuilders.get("/reservations/{reservationId}", reservationId)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andDo( + document( + "reservation-get", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("reservationId").description("조회 대상 예약의 식별자") + ), + responseFields( + fieldWithPath("reservationId").type(JsonFieldType.STRING).description("예약 식별자"), + fieldWithPath("shopName").type(JsonFieldType.STRING).description("예약 대상 가게의 이름"), + fieldWithPath("description").type(JsonFieldType.STRING).description("예약 개요"), + fieldWithPath("reserveAt").type(JsonFieldType.STRING).description("예약 시간(yyyy-mm-ddThh:mm:ss)"), + fieldWithPath("status").type(JsonFieldType.STRING).description("예약 상태"), + fieldWithPath("reservedProduct.[].productId").type(JsonFieldType.NUMBER) + .description("예약 상품 식별자"), + fieldWithPath("reservedProduct.[].name").type(JsonFieldType.STRING) + .description("예약 상품명"), + fieldWithPath("reservedProduct.[].price").type(JsonFieldType.NUMBER) + .description("예약 상품 가격"), + fieldWithPath("reservedProduct.[].count").type(JsonFieldType.NUMBER).description("예약 수량") + ) + ) + ) + } + + override fun initController() = GetReservationController(getReservationQuery) +} From c36ea7c553ddc5e1ecf3f460024c8957577e3774 Mon Sep 17 00:00:00 2001 From: le2sky Date: Sun, 27 Aug 2023 22:25:29 +0900 Subject: [PATCH 6/9] =?UTF-8?q?docs=20:=20=EC=98=88=EC=95=BD=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/docs/asciidoc/reservation.adoc | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/mealkitary-api/src/docs/asciidoc/reservation.adoc b/mealkitary-api/src/docs/asciidoc/reservation.adoc index 3fa8005..f12fb67 100644 --- a/mealkitary-api/src/docs/asciidoc/reservation.adoc +++ b/mealkitary-api/src/docs/asciidoc/reservation.adoc @@ -26,6 +26,20 @@ include::{snippets}/reservation-post/http-response.adoc[] include::{snippets}/reservation-post/response-headers.adoc[] +==== 예약 상세 조회 + +예약에 대한 상세 정보를 조회합니다. + +===== 요청 + +include::{snippets}/reservation-get/curl-request.adoc[] +include::{snippets}/reservation-get/http-request.adoc[] +include::{snippets}/reservation-get/path-parameters.adoc[] + +===== 응답 + +include::{snippets}/reservation-get/http-response.adoc[] + ==== 예약 결제 미결제 상태의 예약에 대해 결제를 생성/승인합니다. @@ -52,7 +66,8 @@ include::{snippets}/reservation-post-pay/response-headers.adoc[] ==== 예약 승인 -결제된 예약에 대해서 예약 승인 처리합니다. 결제된 예약이 아닌 경우, 승인 처리할 수 없습니다. +결제된 예약에 대해서 예약 승인 처리합니다. +결제된 예약이 아닌 경우, 승인 처리할 수 없습니다. ===== 요청 From 8f21e9b1b317f72f29a86b2b774003a11fe26632 Mon Sep 17 00:00:00 2001 From: le2sky Date: Sun, 27 Aug 2023 22:37:28 +0900 Subject: [PATCH 7/9] =?UTF-8?q?fix=20:=20codecov=20github=20status=20patch?= =?UTF-8?q?=20=EB=B9=84=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- codecov.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/codecov.yml b/codecov.yml index 2cefe2d..f625053 100644 --- a/codecov.yml +++ b/codecov.yml @@ -7,10 +7,7 @@ comment: coverage: status: - patch: - default: - target: auto - threshold: 0.1% + patch: off project: default: target: auto From 16199dc86b5629aa55349fb155a4d2cf1319d0c3 Mon Sep 17 00:00:00 2001 From: le2sky Date: Sun, 27 Aug 2023 23:42:44 +0900 Subject: [PATCH 8/9] =?UTF-8?q?chore=20:=20location=20=ED=97=A4=EB=8D=94?= =?UTF-8?q?=20=EB=85=B8=EC=B6=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/com/mealkitary/common/config/WebConfig.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mealkitary-api/src/main/kotlin/com/mealkitary/common/config/WebConfig.kt b/mealkitary-api/src/main/kotlin/com/mealkitary/common/config/WebConfig.kt index 4c24c6a..81c6e16 100644 --- a/mealkitary-api/src/main/kotlin/com/mealkitary/common/config/WebConfig.kt +++ b/mealkitary-api/src/main/kotlin/com/mealkitary/common/config/WebConfig.kt @@ -1,6 +1,7 @@ package com.mealkitary.common.config import org.springframework.context.annotation.Configuration +import org.springframework.http.HttpHeaders import org.springframework.web.servlet.config.annotation.CorsRegistry import org.springframework.web.servlet.config.annotation.WebMvcConfigurer @@ -10,5 +11,6 @@ class WebConfig : WebMvcConfigurer { override fun addCorsMappings(registry: CorsRegistry) { registry.addMapping("/**") .allowedOrigins("*") + .exposedHeaders(HttpHeaders.LOCATION) } } From 2113fc3d144dfe73eae50892162f01790ee5fa88 Mon Sep 17 00:00:00 2001 From: le2sky Date: Sun, 27 Aug 2023 23:44:32 +0900 Subject: [PATCH 9/9] =?UTF-8?q?fix=20:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=B2=84=EC=A0=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index af130a6..d8822f1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ ktlintVersion=11.0.0 springBootVersion=2.7.11 springDependencyManagementVersion=1.0.15.RELEASE # project -applicationVersion=0.2.0 +applicationVersion=0.3.0 projectGroup=com.mealkitary # test kotestVersion=4.4.3