Skip to content

Commit

Permalink
Merge pull request #78 from le2sky/develop
Browse files Browse the repository at this point in the history
[๋ฐฐํฌ] v0.5.0(PR#75,PR#76,PR#77)
  • Loading branch information
le2sky committed Sep 27, 2023
2 parents ca5a0dd + 0cad251 commit 96d994d
Show file tree
Hide file tree
Showing 58 changed files with 1,248 additions and 54 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/mealkitary-main-develop-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
./mealkitary-infrastructure/adapter-persistence-spring-data-jpa/build/test-results/**/*.xml
./mealkitary-infrastructure/adapter-paymentgateway-tosspayments/build/test-results/**/*.xml
./mealkitary-infrastructure/adapter-firebase-notification/build/test-results/**/*.xml
./mealkitary-infrastructure/business-registration-number-validator/adapter-simple-brn-validator/build/test-results/**/*.xml
- name: Jacoco Coverage ๋ฆฌํฌํŠธ ์ „์†ก
uses: codecov/codecov-action@v3
Expand All @@ -65,7 +66,8 @@ jobs:
./mealkitary-application/build/reports/jacoco/test/jacocoTestReport.xml,
./mealkitary-infrastructure/adapter-persistence-spring-data-jpa/build/reports/jacoco/test/jacocoTestReport.xml,
./mealkitary-infrastructure/adapter-paymentgateway-tosspayments/build/reports/jacoco/test/jacocoTestReport.xml,
./mealkitary-infrastructure/adapter-firebase-notification/build/reports/jacoco/test/jacocoTestReport.xml
./mealkitary-infrastructure/adapter-firebase-notification/build/reports/jacoco/test/jacocoTestReport.xml,
./mealkitary-infrastructure/business-registration-number-validator/adapter-simple-brn-validator/build/reports/jacoco/test/jacocoTestReport.xml
name: mealkitary-codecov
verbose: true

Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/mealkitary-test-coverage-automation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ jobs:
./mealkitary-infrastructure/adapter-persistence-spring-data-jpa/build/test-results/**/*.xml
./mealkitary-infrastructure/adapter-paymentgateway-tosspayments/build/test-results/**/*.xml
./mealkitary-infrastructure/adapter-firebase-notification/build/test-results/**/*.xml
./mealkitary-infrastructure/business-registration-number-validator/adapter-simple-brn-validator/build/test-results/**/*.xml
- name: Jacoco Coverage ๋ฆฌํฌํŠธ ์ „์†ก
uses: codecov/codecov-action@v3
Expand All @@ -53,6 +54,7 @@ jobs:
./mealkitary-application/build/reports/jacoco/test/jacocoTestReport.xml,
./mealkitary-infrastructure/adapter-persistence-spring-data-jpa/build/reports/jacoco/test/jacocoTestReport.xml,
./mealkitary-infrastructure/adapter-paymentgateway-tosspayments/build/reports/jacoco/test/jacocoTestReport.xml,
./mealkitary-infrastructure/adapter-firebase-notification/build/reports/jacoco/test/jacocoTestReport.xml
./mealkitary-infrastructure/adapter-firebase-notification/build/reports/jacoco/test/jacocoTestReport.xml,
./mealkitary-infrastructure/business-registration-number-validator/adapter-simple-brn-validator/build/reports/jacoco/test/jacocoTestReport.xml
name: mealkitary-codecov
verbose: true
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ktlintVersion=11.0.0
springBootVersion=2.7.11
springDependencyManagementVersion=1.0.15.RELEASE
# project
applicationVersion=0.4.0
applicationVersion=0.5.0
projectGroup=com.mealkitary
# test
kotestVersion=4.4.3
Expand Down
Empty file modified gradlew
100644 โ†’ 100755
Empty file.
10 changes: 10 additions & 0 deletions mealkitary-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ dependencies {
implementation(project(":mealkitary-infrastructure:adapter-persistence-spring-data-jpa"))
implementation(project(":mealkitary-infrastructure:adapter-paymentgateway-tosspayments"))
implementation(project(":mealkitary-infrastructure:adapter-firebase-notification"))
implementation(
project(
":mealkitary-infrastructure:business-registration-number-validator:adapter-open-api-brn-validator",
)
)
implementation(
project(
":mealkitary-infrastructure:business-registration-number-validator:adapter-simple-brn-validator",
)
)
testImplementation("org.springframework.restdocs:spring-restdocs-mockmvc")
asciidoctorExt("org.springframework.restdocs:spring-restdocs-asciidoctor")
}
Expand Down
14 changes: 14 additions & 0 deletions mealkitary-api/src/docs/asciidoc/reservation.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ include::{snippets}/reservation-get/path-parameters.adoc[]

include::{snippets}/reservation-get/http-response.adoc[]

==== ๋Œ€์ƒ ๊ฐ€๊ฒŒ ์˜ˆ์•ฝ ๋ชฉ๋ก ์กฐํšŒ

๊ฐ€๊ฒŒ ์‹๋ณ„์ž๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์˜ˆ์•ฝ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

===== ์š”์ฒญ

include::{snippets}/reservation-get-all/curl-request.adoc[]
include::{snippets}/reservation-get-all/http-request.adoc[]
include::{snippets}/reservation-get-all/request-parameters.adoc[]

===== ์‘๋‹ต

include::{snippets}/reservation-get-all/http-response.adoc[]

==== ์˜ˆ์•ฝ ๊ฒฐ์ œ

๋ฏธ๊ฒฐ์ œ ์ƒํƒœ์˜ ์˜ˆ์•ฝ์— ๋Œ€ํ•ด ๊ฒฐ์ œ๋ฅผ ์ƒ์„ฑ/์Šน์ธํ•ฉ๋‹ˆ๋‹ค.
Expand Down
38 changes: 38 additions & 0 deletions mealkitary-api/src/docs/asciidoc/shop.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@

๊ฐ€๊ฒŒ์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜, ๊ฐ€๊ฒŒ์˜ ์†ํ•œ ์š”์†Œ(์ƒํ’ˆ, ์˜ˆ์•ฝ ๊ฐ€๋Šฅ ์‹œ๊ฐ„)๋“ค์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

==== ์‹ ๊ทœ ๊ฐ€๊ฒŒ ๋“ฑ๋ก

์‹ ๊ทœ ๊ฐ€๊ฒŒ๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

[NOTE]
====
์‹ ๊ทœ ๋ฆฌ์†Œ์Šค ์ƒ์„ฑ ์‹œ, ๋ฐ˜ํ™˜ ํ—ค๋”์˜ Location ๊ฐ’์€ ์‹ ๊ทœ ๋ฆฌ์†Œ์Šค์˜ URI์ž…๋‹ˆ๋‹ค.
====

===== ์š”์ฒญ

include::{snippets}/shop-post/curl-request.adoc[]
include::{snippets}/shop-post/http-request.adoc[]
include::{snippets}/shop-post/request-fields.adoc[]

===== ์‘๋‹ต

include::{snippets}/shop-post/http-response.adoc[]

===== ์‘๋‹ต ํ—ค๋”

include::{snippets}/shop-post/response-headers.adoc[]

==== ๊ฐ€๊ฒŒ ์กฐํšŒ

๊ฐ€๊ฒŒ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
Expand Down Expand Up @@ -61,3 +84,18 @@ include::{snippets}/shop-get-reservable-time/path-parameters.adoc[]

include::{snippets}/shop-get-reservable-time/http-response.adoc[]
include::{snippets}/shop-get-reservable-time/response-fields.adoc[]


==== ๊ฐ€๊ฒŒ ์ƒํƒœ ๋ณ€๊ฒฝ

๊ฐ€๊ฒŒ์˜ ์ƒํƒœ(VALID, INVALID)๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ ๊ฐ€๊ฒŒ์˜ ์ƒํƒœ๊ฐ€ VALID์ธ ๊ฒฝ์šฐ์—๋Š” INVALID๋กœ, INVALID์ธ ๊ฒฝ์šฐ์—๋Š” VALID๋กœ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.

===== ์š”์ฒญ

include::{snippets}/shop-post-update/curl-request.adoc[]
include::{snippets}/shop-post-update/http-request.adoc[]
include::{snippets}/shop-post-update/path-parameters.adoc[]

===== ์‘๋‹ต

include::{snippets}/shop-post-update/http-response.adoc[]
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ class HttpResponseUtils {

companion object {

fun createResourceUri(resourceId: UUID): URI {
fun createResourceUri(resourceId: UUID): URI = URI.create("${createBaseUri()}/$resourceId")

fun createResourceUri(resourceId: Long): URI = URI.create("${createBaseUri()}/$resourceId")

private fun createBaseUri(): String {
val uriComponents = ServletUriComponentsBuilder.fromCurrentRequest().build()
val scheme = removeSlash(uriComponents.scheme)
val host = removeSlash(uriComponents.host)
val path = removeSlash(uriComponents.path)

return URI.create("$scheme://$host/$path/$resourceId")
return "$scheme://$host/$path"
}

fun createResourceUri(path: String, resourceId: UUID): URI {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.mealkitary.reservation.web

import com.mealkitary.common.utils.HttpResponseUtils
import com.mealkitary.common.utils.UUIDUtils
import com.mealkitary.reservation.application.port.input.GetReservationQuery
import com.mealkitary.reservation.application.port.input.ReservationResponse
import org.springframework.http.ResponseEntity
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.RequestParam
import org.springframework.web.bind.annotation.RestController

@RestController
Expand All @@ -16,4 +20,12 @@ class GetReservationController(
@GetMapping("/{reservationId}")
fun getOneReservation(@PathVariable("reservationId") reservationId: String) =
getReservationQuery.loadOneReservationById(UUIDUtils.fromString(reservationId))

@GetMapping
fun getAllReservation(@RequestParam("shopId") shopIdParam: Long?): ResponseEntity<List<ReservationResponse>> {
val shopId = requireNotNull(shopIdParam) { "๊ฐ€๊ฒŒ ์‹๋ณ„์ž๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค." }

return HttpResponseUtils
.mapToResponseEntity(emptiableList = getReservationQuery.loadAllReservationByShopId(shopId))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.mealkitary.shop.web

import com.mealkitary.common.utils.HttpResponseUtils
import com.mealkitary.shop.application.port.input.RegisterShopUseCase
import com.mealkitary.shop.web.request.RegisterShopWebRequest
import org.springframework.http.ResponseEntity
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.RestController
import javax.validation.Valid

@RestController
@RequestMapping("/shops")
class RegisterShopController(
private val registerShopUseCase: RegisterShopUseCase
) {

@PostMapping
fun registerShop(@Valid @RequestBody registerShopWebRequest: RegisterShopWebRequest): ResponseEntity<Unit> {
val resourceId = registerShopUseCase.register(registerShopWebRequest.mapToServiceRequest())
val location = HttpResponseUtils.createResourceUri(resourceId)

return ResponseEntity.created(location).build()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.mealkitary.shop.web

import com.mealkitary.shop.application.port.input.UpdateShopStatusUseCase
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/shops")
class UpdateShopStatusController(
private val updateShopStatusUseCase: UpdateShopStatusUseCase
) {

@PostMapping("/{shopId}/status")
fun updateShopStatus(@PathVariable("shopId") shopId: Long): ResponseEntity<Unit> {
updateShopStatusUseCase.update(shopId)

return ResponseEntity.noContent().build()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.mealkitary.shop.web.request

import com.mealkitary.shop.application.port.input.RegisterShopRequest
import javax.validation.constraints.NotBlank

data class RegisterShopWebRequest(
@field:NotBlank(message = "๋“ฑ๋ก ๋Œ€์ƒ ๊ฐ€๊ฒŒ์˜ ์ด๋ฆ„์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.")
val title: String? = null,

@field:NotBlank(message = "์‚ฌ์—…์ž ๋ฒˆํ˜ธ๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.")
val brn: String? = null
) {

fun mapToServiceRequest() = RegisterShopRequest(title!!, brn!!)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ 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.restdocs.request.RequestDocumentation.requestParameters
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.util.UUID

class GetReservationControllerDocsTest : RestDocsSupport() {
Expand Down Expand Up @@ -84,5 +87,67 @@ class GetReservationControllerDocsTest : RestDocsSupport() {
)
}

@Test
fun `api docs test - getAllReservation`() {
val reservationId = UUID.randomUUID()
val reserveAt = LocalDateTime.of(
LocalDate.of(2023, 6, 23), LocalTime.of(6, 30)
)
every { getReservationQuery.loadAllReservationByShopId(1L) } answers {
listOf(
ReservationResponse(
reservationId,
"์ง‘๋ฐฅ๋š๋”ฑ ์•ˆ์–‘์ ",
"๋ถ€๋Œ€์ฐŒ๊ฐœ ์™ธ 1๊ฑด",
reserveAt,
"PAID",
listOf(
ReservedProduct(
1L,
"๋ถ€๋Œ€์ฐŒ๊ฐœ",
20000,
2
),
ReservedProduct(
2L,
"๊น€์น˜์ฐŒ๊ฐœ",
20000,
1
)
)
)
)
}

mvc.perform(RestDocumentationRequestBuilders.get("/reservations?shopId=1"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andDo(
document(
"reservation-get-all",
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()),
requestParameters(
parameterWithName("shopId").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)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.docs.shop

import com.docs.RestDocsSupport
import com.mealkitary.shop.application.port.input.RegisterShopUseCase
import com.mealkitary.shop.web.RegisterShopController
import com.mealkitary.shop.web.request.RegisterShopWebRequest
import io.mockk.every
import io.mockk.mockk
import org.springframework.http.MediaType
import org.springframework.restdocs.headers.HeaderDocumentation.headerWithName
import org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation
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.requestFields
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.header
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status

class RegisterShopControllerDocsTest : RestDocsSupport() {

private val registerShopUseCase = mockk<RegisterShopUseCase>()

@Test
fun `api docs test - registerShop`() {
every { registerShopUseCase.register(any()) } answers { 1L }

val registerShopWebRequest = RegisterShopWebRequest("์ง‘๋ฐฅ๋š๋”ฑ ์•ˆ์–‘์ ", "123-23-12345")

mvc.perform(
RestDocumentationRequestBuilders.post("/shops")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(registerShopWebRequest))
)
.andExpect(status().isCreated)
.andExpect(header().string("Location", "http://localhost/shops/1"))
.andDo(
MockMvcRestDocumentation.document(
"shop-post",
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()),
requestFields(
fieldWithPath("title").type(JsonFieldType.STRING).description("๋“ฑ๋ก ๋Œ€์ƒ ๊ฐ€๊ฒŒ ์ด๋ฆ„"),
fieldWithPath("brn").type(JsonFieldType.STRING).description("์‚ฌ์—…์ž ๋ฒˆํ˜ธ"),
),
responseHeaders(headerWithName("Location").description("์ƒ์„ฑ๋œ ๊ฐ€๊ฒŒ ๋ฆฌ์†Œ์Šค URI")),
)
)
}

override fun initController() = RegisterShopController(registerShopUseCase)
}
Loading

0 comments on commit 96d994d

Please sign in to comment.