Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 상위 & 하위 태그 전체 조회 API 구현 #126

Merged
merged 3 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions Api-Module/src/docs/asciidoc/Tag.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,21 @@ operation::TagControllerTest/createParentTagTest/[snippets='http-request,request

operation::TagControllerTest/createChildTagTest/[snippets='http-request,path-parameters,request-fields,http-response,response-fields']

[[GetAllTagTest]]
=== 상위 & 하위 태그 전체 조회 API

operation::TagControllerTest/getAllTagsTest/[snippets='http-request,http-response,response-fields']

[[GetParentTagTest]]
=== 상위 태그 조회 API

operation::TagControllerTest/getAllParentTagByUserTest/[snippets='http-request,request-headers,http-response,response-fields']

[[GetChildTagTest]]
=== 하위 태그 전체 조회 API

operation::TagControllerTest/getAllChildTagTest/[snippets='http-request,path-parameters,http-response,response-fields']

[[GetTopRankTagTest]]
=== 연도 내 경험 최근 추가 순 태그 조회 API

Expand All @@ -24,12 +34,7 @@ operation::TagControllerTest/getTopRankParentTagTest/[snippets='http-request,req
[[GetParentTagsByFilter]]
=== 연도 내 상위 태그 조회 API

operation::TagControllerTest/getParentTagsByFilter/[snippets='http-request,http-response,response-fields']

[[GetChildTagTest]]
=== 하위 태그 전체 조회 API

operation::TagControllerTest/getAllChildTagTest/[snippets='http-request,path-parameters,http-response,response-fields']
operation::TagControllerTest/getParentTagsByYear/[snippets='http-request,http-response,response-fields']

[[GetChildTagsByFilter]]
=== 상위 태그 내 하위 태그 조회 API
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.bamyanggang.apimodule.domain.tag.application.dto

import java.util.*

class GetTag {
data class Response(
val tags: List<ParentTagDetail>
)

data class ParentTagDetail(
val id: UUID,
val name: String,
val childTags: List<ChildTagDetail>
)

data class ChildTagDetail(
val id: UUID,
val name: String,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.bamyanggang.apimodule.domain.tag.application.service
import com.bamyanggang.apimodule.common.getAuthenticationPrincipal
import com.bamyanggang.apimodule.domain.tag.application.dto.GetChildTag
import com.bamyanggang.apimodule.domain.tag.application.dto.GetParentTag
import com.bamyanggang.apimodule.domain.tag.application.dto.GetTag
import com.bamyanggang.domainmodule.domain.experience.service.ExperienceReader
import com.bamyanggang.domainmodule.domain.tag.service.TagReader
import org.springframework.stereotype.Service
Expand Down Expand Up @@ -104,6 +105,7 @@ class TagGetService(
)
}

@Transactional(readOnly = true)
fun getAllYearsByParentTagId(parentTagId: UUID): GetParentTag.Years {
val experiences = getAuthenticationPrincipal().let {
experienceReader.readByUserIdAndParentTagId(it, parentTagId)
Expand All @@ -116,4 +118,28 @@ class TagGetService(

return GetParentTag.Years(years)
}

@Transactional(readOnly = true)
fun getAllTags(): GetTag.Response {
val parentTags = getAuthenticationPrincipal().let {
tagReader.readAllParentTagsByUserId(it)
}

val parentTagDetails = parentTags.map {
val childTagDetails = tagReader.readChildTagsByParentTagId(it.id).map {
GetTag.ChildTagDetail(
it.id,
it.name
)
}

GetTag.ParentTagDetail(
it.id,
it.name,
childTagDetails
)
}

return GetTag.Response(parentTagDetails)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.bamyanggang.apimodule.domain.tag.presentation

object TagApi {
const val BASE_URL = "/api/tags"
const val ALL_TAGS = "${BASE_URL}/all-tags"
const val MY_PARENT_TAG_URL = "$BASE_URL/my"
const val TOP_RANK_TAG_URL = "$BASE_URL/top-rank"
const val TAG_PATH_VARIABLE_URL = "$BASE_URL/{tagId}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.bamyanggang.apimodule.domain.tag.presentation
import com.bamyanggang.apimodule.domain.tag.application.dto.CreateTag
import com.bamyanggang.apimodule.domain.tag.application.dto.GetChildTag
import com.bamyanggang.apimodule.domain.tag.application.dto.GetParentTag
import com.bamyanggang.apimodule.domain.tag.application.dto.GetTag
import com.bamyanggang.apimodule.domain.tag.application.service.TagCreateService
import com.bamyanggang.apimodule.domain.tag.application.service.TagDeleteService
import com.bamyanggang.apimodule.domain.tag.application.service.TagGetService
Expand Down Expand Up @@ -38,6 +39,11 @@ class TagController(
return tagGetService.getAllChildTagsByParentTagId(parentTagId)
}

@GetMapping(TagApi.ALL_TAGS)
fun getAllTags(): GetTag.Response {
return tagGetService.getAllTags()
}

@GetMapping(TagApi.BASE_URL)
fun getParentTagsByYear(@RequestParam("year") year: Int): GetParentTag.TotalTagInfo {
return tagGetService.getAllParentTagsByYear(year)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.bamyanggang.apimodule.BaseRestDocsTest
import com.bamyanggang.apimodule.domain.tag.application.dto.CreateTag
import com.bamyanggang.apimodule.domain.tag.application.dto.GetChildTag
import com.bamyanggang.apimodule.domain.tag.application.dto.GetParentTag
import com.bamyanggang.apimodule.domain.tag.application.dto.GetTag
import com.bamyanggang.commonmodule.exception.ExceptionHandler
import com.bamyanggang.commonmodule.fixture.generateFixture
import com.bamyanggang.domainmodule.domain.tag.exception.TagException
Expand Down Expand Up @@ -209,6 +210,54 @@ class TagControllerTest : BaseRestDocsTest() {
)
}

@Test
@DisplayName("상위 태그와 하위 태그 전체를 조회한다.")
fun getAllTagsTest() {
//given
val childTagDetails = arrayListOf(
GetTag.ChildTagDetail(UUID.randomUUID(), "하위 태그 이름 1"),
GetTag.ChildTagDetail(UUID.randomUUID(), "하위 태그 이름 2")
)

val parentTagDetails = arrayListOf(
GetTag.ParentTagDetail(UUID.randomUUID(),
"상위, 태그 이름 1",
childTagDetails
),
GetTag.ParentTagDetail(UUID.randomUUID(),
"상위, 태그 이름 1",
childTagDetails
),
)

val tagResponse = GetTag.Response(parentTagDetails)

given(tagController.getAllTags()).willReturn(tagResponse)

val request = RestDocumentationRequestBuilders.get(TagApi.ALL_TAGS)
.header("Authorization", "Bearer Access Token")

//when
val result = mockMvc.perform(request)

//then
result.andExpect(status().isOk)
.andDo(resultHandler.document(
requestHeaders(
headerWithName("Authorization").description("엑세스 토큰")
),
responseFields(
fieldWithPath("tags").description("태그 리스트"),
fieldWithPath("tags[].id").description("상위 태그 id"),
fieldWithPath("tags[].name").description("상위 태그 이름"),
fieldWithPath("tags[].childTags").description("하위 태그 리스트"),
fieldWithPath("tags[].childTags[].id").description("하위 태그 id"),
fieldWithPath("tags[].childTags[].name").description("하위 태그 이름"),
)
)
)
}

@Test
@DisplayName("하위 태그를 전체 조회한다.")
fun getAllChildTagTest() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ interface TagRepository {
fun deleteByTagId(tagId: UUID)
fun isExistById(tagId: UUID): Boolean
fun findByParentTagIds(tagParentTagIds: List<UUID>): List<Tag>
fun findAllChildTagsByParentTagId(parentTagId: UUID) : List<Tag>
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@ class TagReader(
fun readByIds(parentTagIds: List<UUID>): List<Tag> {
return tagRepository.findByParentTagIds(parentTagIds)
}

fun readChildTagsByParentTagId(parentTagId: UUID) : List<Tag> {
return tagRepository.findAllChildTagsByParentTagId(parentTagId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.bamyanggang.domainmodule.domain.tag.aggregate.Tag;
import com.bamyanggang.domainmodule.domain.tag.exception.TagException.NotFoundTag;
import com.bamyanggang.domainmodule.domain.tag.repository.TagRepository;
import com.bamyanggang.persistence.common.exception.PersistenceException.NotFound;
import com.bamyanggang.persistence.tag.jpa.entity.TagJpaEntity;
import com.bamyanggang.persistence.tag.jpa.repository.TagJpaRepository;
import com.bamyanggang.persistence.tag.mapper.TagMapper;
Expand Down Expand Up @@ -57,4 +56,10 @@ public Tag findById(UUID tagId) {
TagJpaEntity tagJpaEntity = tagJpaRepository.findById(tagId).orElseThrow(NotFoundTag::new);
return tagMapper.toDomainEntity(tagJpaEntity);
}

@Override
public List<Tag> findAllChildTagsByParentTagId(UUID parentTagId) {
List<TagJpaEntity> tagJpaEntities = tagJpaRepository.findAllByParentTagId(parentTagId);
return tagJpaEntities.stream().map(tagMapper::toDomainEntity).toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@

public interface TagJpaRepository extends JpaRepository<TagJpaEntity, UUID> {
List<TagJpaEntity> findAllByUserIdAndParentTagIdIsNull(UUID userId);

List<TagJpaEntity> findAllByUserIdAndParentTagId(UUID parentTagId, UUID parentId);
List<TagJpaEntity> findAllByUserIdAndParentTagId(UUID userId, UUID parentId);
List<TagJpaEntity> findAllByParentTagId(UUID parentTagId);
}
Loading