diff --git a/Api-Module/src/docs/asciidoc/Tag.adoc b/Api-Module/src/docs/asciidoc/Tag.adoc index 56317819..088305da 100644 --- a/Api-Module/src/docs/asciidoc/Tag.adoc +++ b/Api-Module/src/docs/asciidoc/Tag.adoc @@ -14,7 +14,7 @@ operation::TagControllerTest/createChildTagTest/[snippets='http-request,path-par [[GetParentTagTest]] === 상위 태그 조회 API -operation::TagControllerTest/getAllParentTagByUserRegisterTest/[snippets='http-request,request-headers,http-response,response-fields'] +operation::TagControllerTest/getAllParentTagByUserTest/[snippets='http-request,request-headers,http-response,response-fields'] [[GetTopRankTagTest]] === 연도 내 경험 최근 추가 순 태그 조회 API @@ -36,6 +36,11 @@ operation::TagControllerTest/getAllChildTagTest/[snippets='http-request,path-par operation::TagControllerTest/getChildTagsByYear/[snippets='http-request,path-parameters,http-response,response-fields'] +[[GetYearsByParentTagId]] +=== 상위 태그 내 존재 연도 조회 API + +operation::TagControllerTest/getYearsByParentTagId/[snippets='http-request,path-parameters,http-response,response-fields'] + [[duplicatedParentTagTest]] ==== 상위 태그 이름 중복 예외 diff --git a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/experience/application/service/ExperienceGetService.kt b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/experience/application/service/ExperienceGetService.kt index 2b0559df..f2f2e544 100644 --- a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/experience/application/service/ExperienceGetService.kt +++ b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/experience/application/service/ExperienceGetService.kt @@ -29,7 +29,7 @@ class ExperienceGetService( } fun getExperienceByYearAndParentTag(year: Int, parentTagId: UUID): GetExperience.Response { - val experiences = experienceReader.readByYearAndParentTagId(year, parentTagId).map { + val experiences = experienceReader.readByYearAndTagId(year, parentTagId).map { createExperienceDetailResponse(it) } @@ -37,7 +37,7 @@ class ExperienceGetService( } fun getExperienceByYearAndChildTag(year: Int, childTagId: UUID): GetExperience.Response { - val experiences = experienceReader.readByYearAndParentTagId(year, childTagId).map { + val experiences = experienceReader.readByYearAndTagId(year, childTagId).map { createExperienceDetailResponse(it) } diff --git a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/application/dto/GetParentTag.kt b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/application/dto/GetParentTag.kt index 8e15289c..851e0356 100644 --- a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/application/dto/GetParentTag.kt +++ b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/application/dto/GetParentTag.kt @@ -23,4 +23,8 @@ class GetParentTag { val strongPointCount: Int, val experienceCount: Int ) + + data class Years( + val years: List + ) } diff --git a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/application/service/TagGetService.kt b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/application/service/TagGetService.kt index 7914f695..73fe8425 100644 --- a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/application/service/TagGetService.kt +++ b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/application/service/TagGetService.kt @@ -39,7 +39,7 @@ class TagGetService( @Transactional(readOnly = true) fun getParentTagsByYearAndLimit(year: Int, limit: Int): GetParentTag.Response { val currentUserId = getAuthenticationPrincipal() - val topParentTagIds = experienceReader.readByYearDesc(year, currentUserId) + val topParentTagIds = experienceReader.readByUserIDAndYearDesc(year, currentUserId) .distinctBy { it.parentTagId } .take(limit) .map { it.parentTagId } @@ -54,7 +54,7 @@ class TagGetService( @Transactional(readOnly = true) fun getAllParentTagsByYear(year: Int): GetParentTag.TotalTagInfo { val currentUserId = getAuthenticationPrincipal() - val experiences = experienceReader.readByYearDesc(year, currentUserId) + val experiences = experienceReader.readByUserIDAndYearDesc(year, currentUserId) val experienceGroup = experiences.groupBy { it.parentTagId } @@ -85,7 +85,7 @@ class TagGetService( @Transactional(readOnly = true) fun getAllChildTagsByYearAndParentTagId(year: Int, parentTagId: UUID): GetChildTag.TotalTagInfo { val currentUserId = getAuthenticationPrincipal() - val experiences = experienceReader.readByYearDesc(year, currentUserId) + val experiences = experienceReader.readByUserIDAndYearDesc(year, currentUserId) val experienceGroup = experiences.groupBy { it.childTagId } val tagSummaries = experienceGroup.map { @@ -103,4 +103,17 @@ class TagGetService( tagSummaries ) } + + fun getAllYearsByParentTagId(parentTagId: UUID): GetParentTag.Years { + val experiences = getAuthenticationPrincipal().let { + experienceReader.readByUserIdAndParentTagId(it, parentTagId) + } + + val years = experiences + .distinctBy { it.createdAt.year } + .map { it.createdAt.year } + .sorted().reversed() + + return GetParentTag.Years(years) + } } diff --git a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagApi.kt b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagApi.kt index a76f6af7..b165e9a3 100644 --- a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagApi.kt +++ b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagApi.kt @@ -6,4 +6,5 @@ object TagApi { const val TOP_RANK_TAG_URL = "$BASE_URL/top-rank" const val TAG_PATH_VARIABLE_URL = "$BASE_URL/{tagId}" const val MY_CHILD_TAG_URL = "$BASE_URL/{tagId}/my" + const val ALL_YEARS = "$BASE_URL/{parentTagId}/all-years" } diff --git a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagController.kt b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagController.kt index 27f29ae4..dbe9a2b9 100644 --- a/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagController.kt +++ b/Api-Module/src/main/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagController.kt @@ -15,6 +15,11 @@ class TagController( private val tagDeleteService: TagDeleteService, private val tagGetService: TagGetService ) { + @GetMapping(TagApi.ALL_YEARS) + fun getAllYearsByParentTag(@PathVariable("parentTagId") parentTagId: UUID): GetParentTag.Years{ + return tagGetService.getAllYearsByParentTagId(parentTagId) + } + @GetMapping(TagApi.TOP_RANK_TAG_URL) fun getTopRankTagsByLimit( @RequestParam("year") year: Int, diff --git a/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagControllerTest.kt b/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagControllerTest.kt index 15e55e8f..e4554a00 100644 --- a/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagControllerTest.kt +++ b/Api-Module/src/test/kotlin/com/bamyanggang/apimodule/domain/tag/presentation/TagControllerTest.kt @@ -282,6 +282,40 @@ class TagControllerTest : BaseRestDocsTest() { ) } + @Test + @DisplayName("상위 태그 내 존재하는 경험들의 연도를 반환한다.") + fun getYearsByParentTagId() { + //given + + val yearResponse = GetParentTag.Years( + arrayListOf(2024, 2023, 2022) + ) + + val parentTagId = UUID.randomUUID() + given(tagController.getAllYearsByParentTag(parentTagId)).willReturn(yearResponse) + + val request = RestDocumentationRequestBuilders.get(TagApi.ALL_YEARS, parentTagId) + .header("Authorization", "Bearer Access Token") + + //when + val result = mockMvc.perform(request) + + //then + result.andExpect(status().isOk) + .andDo(resultHandler.document( + requestHeaders( + headerWithName("Authorization").description("엑세스 토큰") + ), + pathParameters( + parameterWithName("parentTagId").description("상위 태그 id") + ), + responseFields( + fieldWithPath("years").description("상위 태그 리스트"), + ) + ) + ) + } + @Test @DisplayName("최근에 추가된 경험이 있는 순으로 상위 태그 정보를 반환한다.") fun getTopRankParentTagTest() { diff --git a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/experience/repository/ExperienceRepository.kt b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/experience/repository/ExperienceRepository.kt index f2679125..81b01398 100644 --- a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/experience/repository/ExperienceRepository.kt +++ b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/experience/repository/ExperienceRepository.kt @@ -11,4 +11,5 @@ interface ExperienceRepository { fun findByUserIdAndYearDesc(year: Int, userId: UUID): List fun findByYearAndParentTagId(year: Int, parentTagId: UUID): List fun findByYearAndChildTagId(year: Int, childTagId: UUID): List + fun findByUserIdAndParentTagId(userId: UUID, parentTagId: UUID): List } diff --git a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/experience/service/ExperienceReader.kt b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/experience/service/ExperienceReader.kt index 29849643..130407e1 100644 --- a/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/experience/service/ExperienceReader.kt +++ b/Domain-Module/src/main/kotlin/com/bamyanggang/domainmodule/domain/experience/service/ExperienceReader.kt @@ -26,15 +26,15 @@ class ExperienceReader( return experienceRepository.findAllByUserId(userId) } - fun readByYearDesc(year: Int, userId: UUID): List { + fun readByUserIDAndYearDesc(year: Int, userId: UUID): List { return experienceRepository.findByUserIdAndYearDesc(year, userId) } - fun readByYearAndParentTagId(year: Int, parentTagId: UUID) : List { + fun readByYearAndTagId(year: Int, parentTagId: UUID) : List { return experienceRepository.findByYearAndParentTagId(year, parentTagId) } - fun readByYearAndChildTagId(year: Int, childTagId: UUID): List { - return experienceRepository.findByYearAndChildTagId(year, childTagId) + fun readByUserIdAndParentTagId(userId: UUID, parentTagId: UUID): List { + return experienceRepository.findByUserIdAndParentTagId(userId, parentTagId) } } diff --git a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/experience/ExperienceRepositoryImpl.java b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/experience/ExperienceRepositoryImpl.java index 28119760..c81b57bb 100644 --- a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/experience/ExperienceRepositoryImpl.java +++ b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/experience/ExperienceRepositoryImpl.java @@ -75,4 +75,12 @@ public List findByYearAndChildTagId(int year, UUID childTagId) { return experienceJpaEntities.stream().map(experienceMapper::toExperienceDomainEntity).toList(); } + + @Override + public List findByUserIdAndParentTagId(UUID userId, UUID parentTagId) { + List experienceJpaEntities = experienceJpaRepository.findByUserIdAndParentTagId(userId, + parentTagId); + + return experienceJpaEntities.stream().map(experienceMapper::toExperienceDomainEntity).toList(); + } } diff --git a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/experience/jpa/repository/ExperienceJpaRepository.java b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/experience/jpa/repository/ExperienceJpaRepository.java index a8ad4f05..6029fec0 100644 --- a/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/experience/jpa/repository/ExperienceJpaRepository.java +++ b/Infrastructure-Module/persistence/src/main/java/com/bamyanggang/persistence/experience/jpa/repository/ExperienceJpaRepository.java @@ -11,4 +11,5 @@ public interface ExperienceJpaRepository extends JpaRepository findByUserIdAndCreatedAtBetweenOrderByCreatedAtDesc(UUID userId, LocalDateTime startYear, LocalDateTime endYear); List findByParentTagIdAndCreatedAtBetweenOrderByCreatedAtDesc(UUID parentTagId, LocalDateTime startYear, LocalDateTime endYear); List findByChildTagIdAndCreatedAtBetweenOrderByCreatedAtDesc(UUID childTagId, LocalDateTime startYear, LocalDateTime endYear); + List findByUserIdAndParentTagId(UUID userId, UUID parentTagId); }