diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index db5784b..5fb40cd 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -678,10 +678,6 @@ http-request include::{snippets}/get-proceeding-fit-off-by-group-id/http-request.adoc[] -request-fields - -include::{snippets}/get-proceeding-fit-off-by-group-id/request-fields.adoc[] - request-body include::{snippets}/get-proceeding-fit-off-by-group-id/request-body.adoc[] @@ -700,4 +696,34 @@ include::{snippets}/get-proceeding-fit-off-by-group-id/response-body.adoc[] http-response -include::{snippets}/get-proceeding-fit-off-by-group-id/http-response.adoc[] \ No newline at end of file +include::{snippets}/get-proceeding-fit-off-by-group-id/http-response.adoc[] + +=== Get Proceeding Fit Off List by user id ( user id로 현재 진행중인 fit off 조회 ) + +path-parameters + +include::{snippets}/get-proceeding-fit-off-by-user-id/path-parameters.adoc[] + +http-request + +include::{snippets}/get-proceeding-fit-off-by-user-id/http-request.adoc[] + +request-body + +include::{snippets}/get-proceeding-fit-off-by-user-id/request-body.adoc[] + +curl-request + +include::{snippets}/get-proceeding-fit-off-by-user-id/curl-request.adoc[] + +response-fields + +include::{snippets}/get-proceeding-fit-off-by-user-id/response-fields.adoc[] + +response-body + +include::{snippets}/get-proceeding-fit-off-by-user-id/response-body.adoc[] + +http-response + +include::{snippets}/get-proceeding-fit-off-by-user-id/http-response.adoc[] \ No newline at end of file diff --git a/src/main/kotlin/com/fitmate/myfit/adapter/in/web/common/GlobalURI.kt b/src/main/kotlin/com/fitmate/myfit/adapter/in/web/common/GlobalURI.kt index 6efef25..07a730a 100644 --- a/src/main/kotlin/com/fitmate/myfit/adapter/in/web/common/GlobalURI.kt +++ b/src/main/kotlin/com/fitmate/myfit/adapter/in/web/common/GlobalURI.kt @@ -47,6 +47,7 @@ class GlobalURI { const val PATH_VARIABLE_FIT_PENALTY_ID_WITH_BRACE = "/{$PATH_VARIABLE_FIT_PENALTY_ID}" const val FIT_OFF_ROOT = "$ROOT_URI/fit-offs" + const val FIT_OFF_USER = "$FIT_OFF_ROOT/users" const val PATH_VARIABLE_FIT_OFF_ID = "fit-off-id" const val PATH_VARIABLE_FIT_OFF_ID_WITH_BRACE = "/{$PATH_VARIABLE_FIT_OFF_ID}" diff --git a/src/main/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/api/FitOffController.kt b/src/main/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/api/FitOffController.kt index 99865fe..3c86569 100644 --- a/src/main/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/api/FitOffController.kt +++ b/src/main/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/api/FitOffController.kt @@ -81,4 +81,10 @@ class FitOffController( val command = FitOffDtoMapper.proceedingFitOffRequestToCommand(fitGroupId) return ResponseEntity.ok().body(readFitOffUseCase.getProceedingFitOffByGroupId(command)) } + + @GetMapping(GlobalURI.FIT_OFF_USER + GlobalURI.PATH_VARIABLE_USER_ID_WITH_BRACE) + fun getProceedingFitOffByUser(@PathVariable(GlobalURI.PATH_VARIABLE_USER_ID) userId: Int): ResponseEntity { + val command = FitOffDtoMapper.proceedingFitOffRequestUserToCommand(userId) + return ResponseEntity.ok().body(readFitOffUseCase.getProceedingFitOffByUser(command)) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/mapper/FitOffDtoMapper.kt b/src/main/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/mapper/FitOffDtoMapper.kt index 0f08041..a38a4d3 100644 --- a/src/main/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/mapper/FitOffDtoMapper.kt +++ b/src/main/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/mapper/FitOffDtoMapper.kt @@ -7,10 +7,7 @@ import com.fitmate.myfit.adapter.`in`.web.fit.off.response.DeleteFitOffResponse import com.fitmate.myfit.adapter.`in`.web.fit.off.response.RegisterFitOffResponse import com.fitmate.myfit.adapter.`in`.web.fit.off.response.UpdateFitOffResponse import com.fitmate.myfit.adapter.out.api.DateParseUtils -import com.fitmate.myfit.application.port.`in`.fit.off.command.DeleteFitOffCommand -import com.fitmate.myfit.application.port.`in`.fit.off.command.GetProceedingFitOffCommand -import com.fitmate.myfit.application.port.`in`.fit.off.command.RegisterFitOffCommand -import com.fitmate.myfit.application.port.`in`.fit.off.command.UpdateFitOffCommand +import com.fitmate.myfit.application.port.`in`.fit.off.command.* import com.fitmate.myfit.application.port.`in`.fit.off.response.DeleteFitOffResponseDto import com.fitmate.myfit.application.port.`in`.fit.off.response.RegisterFitOffResponseDto import com.fitmate.myfit.application.port.`in`.fit.off.response.UpdateFitOffResponseDto @@ -59,5 +56,9 @@ class FitOffDtoMapper { fun proceedingFitOffRequestToCommand(fitGroupId: Long): GetProceedingFitOffCommand { return GetProceedingFitOffCommand(fitGroupId) } + + fun proceedingFitOffRequestUserToCommand(userId: Int): GetProceedingFitOffUserCommand { + return GetProceedingFitOffUserCommand(userId) + } } } \ No newline at end of file diff --git a/src/main/kotlin/com/fitmate/myfit/adapter/out/persistence/repository/FitOffRepository.kt b/src/main/kotlin/com/fitmate/myfit/adapter/out/persistence/repository/FitOffRepository.kt index dbddc06..566253d 100644 --- a/src/main/kotlin/com/fitmate/myfit/adapter/out/persistence/repository/FitOffRepository.kt +++ b/src/main/kotlin/com/fitmate/myfit/adapter/out/persistence/repository/FitOffRepository.kt @@ -22,4 +22,11 @@ interface FitOffRepository : JpaRepository { startDate: Instant, endDate: Instant ): List + + fun findByUserIdAndStateAndFitOffStartDateLessThanEqualAndFitOffEndDateGreaterThanEqual( + userId: Int, + state: Boolean, + fitOffStartDate: Instant, + fitOffEndDate: Instant + ): List } \ No newline at end of file diff --git a/src/main/kotlin/com/fitmate/myfit/application/port/in/fit/off/command/GetProceedingFitOffUserCommand.kt b/src/main/kotlin/com/fitmate/myfit/application/port/in/fit/off/command/GetProceedingFitOffUserCommand.kt new file mode 100644 index 0000000..5ed1d99 --- /dev/null +++ b/src/main/kotlin/com/fitmate/myfit/application/port/in/fit/off/command/GetProceedingFitOffUserCommand.kt @@ -0,0 +1,11 @@ +package com.fitmate.myfit.application.port.`in`.fit.off.command + +import com.fitmate.myfit.common.SelfValidating + +data class GetProceedingFitOffUserCommand( + val userId: Int +) : SelfValidating() { + init { + this.validateSelf() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/fitmate/myfit/application/port/in/fit/off/usecase/ReadFitOffUseCase.kt b/src/main/kotlin/com/fitmate/myfit/application/port/in/fit/off/usecase/ReadFitOffUseCase.kt index 2dc7342..51882af 100644 --- a/src/main/kotlin/com/fitmate/myfit/application/port/in/fit/off/usecase/ReadFitOffUseCase.kt +++ b/src/main/kotlin/com/fitmate/myfit/application/port/in/fit/off/usecase/ReadFitOffUseCase.kt @@ -2,8 +2,10 @@ package com.fitmate.myfit.application.port.`in`.fit.off.usecase import com.fitmate.myfit.adapter.`in`.web.fit.off.response.ProceedingFitOffResponse import com.fitmate.myfit.application.port.`in`.fit.off.command.GetProceedingFitOffCommand +import com.fitmate.myfit.application.port.`in`.fit.off.command.GetProceedingFitOffUserCommand interface ReadFitOffUseCase { fun getProceedingFitOffByGroupId(command: GetProceedingFitOffCommand): ProceedingFitOffResponse + fun getProceedingFitOffByUser(command: GetProceedingFitOffUserCommand): ProceedingFitOffResponse } \ No newline at end of file diff --git a/src/main/kotlin/com/fitmate/myfit/application/port/out/fit/off/ReadFitOffPort.kt b/src/main/kotlin/com/fitmate/myfit/application/port/out/fit/off/ReadFitOffPort.kt index 915af14..cefdd7f 100644 --- a/src/main/kotlin/com/fitmate/myfit/application/port/out/fit/off/ReadFitOffPort.kt +++ b/src/main/kotlin/com/fitmate/myfit/application/port/out/fit/off/ReadFitOffPort.kt @@ -9,4 +9,5 @@ interface ReadFitOffPort { fun countByUserIdAndFitOffDate(userId: Int, fitOffStartDate: Instant, fitOffEndDate: Instant): Int fun findById(fitOffId: Long): Optional fun findProceedingFitOffByUserIds(userIdList: List): List + fun findProceedingFitOffByUserId(userId: Int): List } \ No newline at end of file diff --git a/src/main/kotlin/com/fitmate/myfit/application/service/adapter/FitOffPersistenceAdapter.kt b/src/main/kotlin/com/fitmate/myfit/application/service/adapter/FitOffPersistenceAdapter.kt index a21f9c7..ce2231f 100644 --- a/src/main/kotlin/com/fitmate/myfit/application/service/adapter/FitOffPersistenceAdapter.kt +++ b/src/main/kotlin/com/fitmate/myfit/application/service/adapter/FitOffPersistenceAdapter.kt @@ -50,6 +50,21 @@ class FitOffPersistenceAdapter( return fitOffEntityList.map { FitOff.entityToDomain(it) }.toList() } + @Transactional(readOnly = true) + override fun findProceedingFitOffByUserId(userId: Int): List { + val now = Instant.now() + + val fitOffEntityList = + fitOffRepository.findByUserIdAndStateAndFitOffStartDateLessThanEqualAndFitOffEndDateGreaterThanEqual( + userId, + GlobalStatus.PERSISTENCE_NOT_DELETED, + now, + now + ) + + return fitOffEntityList.map { FitOff.entityToDomain(it) }.toList() + } + @Transactional override fun updateFitOff(fitOff: FitOff) { val fitOffEntity = FitOffEntity.domainToEntity(fitOff) diff --git a/src/main/kotlin/com/fitmate/myfit/application/service/service/FitOffService.kt b/src/main/kotlin/com/fitmate/myfit/application/service/service/FitOffService.kt index c101478..3b7e3aa 100644 --- a/src/main/kotlin/com/fitmate/myfit/application/service/service/FitOffService.kt +++ b/src/main/kotlin/com/fitmate/myfit/application/service/service/FitOffService.kt @@ -2,10 +2,7 @@ package com.fitmate.myfit.application.service.service import com.fitmate.myfit.adapter.`in`.web.fit.off.response.FitOffDetail import com.fitmate.myfit.adapter.`in`.web.fit.off.response.ProceedingFitOffResponse -import com.fitmate.myfit.application.port.`in`.fit.off.command.DeleteFitOffCommand -import com.fitmate.myfit.application.port.`in`.fit.off.command.GetProceedingFitOffCommand -import com.fitmate.myfit.application.port.`in`.fit.off.command.RegisterFitOffCommand -import com.fitmate.myfit.application.port.`in`.fit.off.command.UpdateFitOffCommand +import com.fitmate.myfit.application.port.`in`.fit.off.command.* import com.fitmate.myfit.application.port.`in`.fit.off.response.DeleteFitOffResponseDto import com.fitmate.myfit.application.port.`in`.fit.off.response.RegisterFitOffResponseDto import com.fitmate.myfit.application.port.`in`.fit.off.response.UpdateFitOffResponseDto @@ -136,4 +133,13 @@ class FitOffService( return ProceedingFitOffResponse(fitOffDetailList) } + + @Transactional(readOnly = true) + override fun getProceedingFitOffByUser(command: GetProceedingFitOffUserCommand): ProceedingFitOffResponse { + val fitOffDetailList = readFitOffPort.findProceedingFitOffByUserId(command.userId) + .map { FitOffDetail(it.id!!, it.userId, it.fitOffStartDate, it.fitOffEndDate, it.fitOffReason) } + .toList() + + return ProceedingFitOffResponse(fitOffDetailList) + } } \ No newline at end of file diff --git a/src/test/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/api/FitOffControllerTest.kt b/src/test/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/api/FitOffControllerTest.kt index ad655e3..ef9997c 100644 --- a/src/test/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/api/FitOffControllerTest.kt +++ b/src/test/kotlin/com/fitmate/myfit/adapter/in/web/fit/off/api/FitOffControllerTest.kt @@ -9,10 +9,7 @@ import com.fitmate.myfit.adapter.`in`.web.fit.off.response.FitOffDetail import com.fitmate.myfit.adapter.`in`.web.fit.off.response.ProceedingFitOffResponse import com.fitmate.myfit.adapter.out.api.DateParseUtils import com.fitmate.myfit.adapter.out.api.SenderUtils -import com.fitmate.myfit.application.port.`in`.fit.off.command.DeleteFitOffCommand -import com.fitmate.myfit.application.port.`in`.fit.off.command.GetProceedingFitOffCommand -import com.fitmate.myfit.application.port.`in`.fit.off.command.RegisterFitOffCommand -import com.fitmate.myfit.application.port.`in`.fit.off.command.UpdateFitOffCommand +import com.fitmate.myfit.application.port.`in`.fit.off.command.* import com.fitmate.myfit.application.port.`in`.fit.off.response.DeleteFitOffResponseDto import com.fitmate.myfit.application.port.`in`.fit.off.response.RegisterFitOffResponseDto import com.fitmate.myfit.application.port.`in`.fit.off.response.UpdateFitOffResponseDto @@ -248,4 +245,47 @@ class FitOffControllerTest { ) ) } + + @Test + @DisplayName("[단위][Web Adapter] 진행중인 Fit off user id로 조회 - 성공 테스트") + @Throws(Exception::class) + fun `get proceeding fit off by user id controller success test`() { + //given + val responseDto = listOf(FitOffDetail(51L, 16, Instant.now(), Instant.now(), "test")) + val response = ProceedingFitOffResponse(responseDto) + + whenever(readFitOffUseCase.getProceedingFitOffByUser(any())) + .thenReturn(response) + //when + val resultActions = mockMvc.perform( + get( + GlobalURI.FIT_OFF_USER + GlobalURI.PATH_VARIABLE_USER_ID_WITH_BRACE, requestUserId + ).contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + ) + //then + resultActions.andExpect(status().isOk()) + .andDo(print()) + .andDo( + document( + "get-proceeding-fit-off-by-user-id", + pathParameters( + parameterWithName(GlobalURI.PATH_VARIABLE_USER_ID) + .description("조회할 fit user id") + ), + responseFields( + fieldWithPath("content[]").type(JsonFieldType.ARRAY).description("현재 진행중인 fit off 목록"), + fieldWithPath("content[].fitOffId").type(JsonFieldType.NUMBER).description("fit off id"), + fieldWithPath("content[].userId").type(JsonFieldType.NUMBER) + .description("fit off를 등록한 user id"), + fieldWithPath("content[].fitOffStartDate").type(JsonFieldType.STRING) + .description("fit off 시작일"), + fieldWithPath("content[].fitOffEndDate").type(JsonFieldType.STRING) + .description("fit off 종료일"), + fieldWithPath("content[].fitOffReason").type(JsonFieldType.STRING) + .description("fit off 사유") + ) + ) + ) + } } \ No newline at end of file