From 476a61e8df944b1d00970b50a8f692a9d79f9343 Mon Sep 17 00:00:00 2001 From: 12xii Date: Thu, 2 Nov 2023 18:35:36 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EC=97=90=EB=9F=AC=20=ED=95=B4=EA=B2=B0?= =?UTF-8?q?=20&=20response=20=EA=B0=92=20=EB=AA=85=EC=84=B8=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/question/exception/exceptions.kt | 4 ++ .../question/persistence/QuestionSets.kt | 6 +++ .../question/persistence/dto/CategoriesDto.kt | 5 +- .../persistence/dto/QuestionSetDetailDto.kt | 3 +- .../repository/QuestionSetsRepository.kt | 29 ++++++----- .../repository/SetQuestionRepository.kt | 3 +- .../question/presentation/dto/Requests.kt | 1 + .../question/presentation/dto/Responses.kt | 49 +++++++++++-------- .../question/service/QuestionService.kt | 16 +++--- .../kr/hs/dsm/inq/global/error/ErrorCode.kt | 7 +-- 10 files changed, 77 insertions(+), 46 deletions(-) diff --git a/src/main/kotlin/kr/hs/dsm/inq/domain/question/exception/exceptions.kt b/src/main/kotlin/kr/hs/dsm/inq/domain/question/exception/exceptions.kt index 1307c36..ea045e2 100644 --- a/src/main/kotlin/kr/hs/dsm/inq/domain/question/exception/exceptions.kt +++ b/src/main/kotlin/kr/hs/dsm/inq/domain/question/exception/exceptions.kt @@ -8,6 +8,10 @@ object QuestionNotFoundException : CustomException( DomainErrorCode.QUESTION_NOT_FOUND ) +object QuestionSetNotFoundException : CustomException( + DomainErrorCode.QUESTION_SET_NOT_FOUND +) + object AnswerNotFoundException : CustomException( DomainErrorCode.ANSWER_NOT_FOUND ) diff --git a/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/QuestionSets.kt b/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/QuestionSets.kt index 5449abf..9f1dc34 100644 --- a/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/QuestionSets.kt +++ b/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/QuestionSets.kt @@ -18,6 +18,9 @@ class QuestionSets ( @Column(columnDefinition = "DATETIME(6)", nullable = false, updatable = false) var createdAt: LocalDateTime = LocalDateTime.now(), + @Column(columnDefinition = "VARCHAR(1000)", nullable = false) + var description: String, + @Column(columnDefinition = "INT", nullable = false) var answerCount: Int, @@ -27,6 +30,9 @@ class QuestionSets ( @Column(columnDefinition = "INT", nullable = false) var likeCount: Int, + @Column(columnDefinition = "INT", nullable = false) + val dislikeCount: Int, + @Column(columnDefinition = "INT", nullable = false) var viewCount: Int, diff --git a/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/dto/CategoriesDto.kt b/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/dto/CategoriesDto.kt index 312a629..d782b28 100644 --- a/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/dto/CategoriesDto.kt +++ b/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/dto/CategoriesDto.kt @@ -1,8 +1,11 @@ package kr.hs.dsm.inq.domain.question.persistence.dto +import com.querydsl.core.annotations.QueryProjection import kr.hs.dsm.inq.domain.question.persistence.Category +import org.aspectj.weaver.patterns.TypePatternQuestions.Question +import java.util.Objects -class CategoriesDto ( +class CategoriesDto @QueryProjection constructor ( val category: Category, val count: Int ) \ No newline at end of file diff --git a/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/dto/QuestionSetDetailDto.kt b/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/dto/QuestionSetDetailDto.kt index b5dfab6..e766d46 100644 --- a/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/dto/QuestionSetDetailDto.kt +++ b/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/dto/QuestionSetDetailDto.kt @@ -10,11 +10,12 @@ class QuestionSetDetailDto @QueryProjection constructor( val questionSetId: Long, val name: String, val createdAt: LocalDateTime, + val description: String, val username: String, val job: String, val jobDuration: Int, - val category: Category, val likeCount: Int, + val dislikeCount: Int, val viewCount: Int, val isLiked: Boolean, val isDisliked: Boolean, diff --git a/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/repository/QuestionSetsRepository.kt b/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/repository/QuestionSetsRepository.kt index f175045..24b5ac6 100644 --- a/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/repository/QuestionSetsRepository.kt +++ b/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/repository/QuestionSetsRepository.kt @@ -1,22 +1,22 @@ package kr.hs.dsm.inq.domain.question.persistence.repository +import com.querydsl.core.ResultTransformer import com.querydsl.core.group.GroupBy +import com.querydsl.core.types.Expression +import com.querydsl.core.types.Ops +import com.querydsl.core.types.dsl.Expressions import com.querydsl.jpa.impl.JPAQuery import com.querydsl.jpa.impl.JPAQueryFactory import kr.hs.dsm.inq.common.util.PageResponse import kr.hs.dsm.inq.common.util.PageUtil import kr.hs.dsm.inq.domain.question.persistence.* -import kr.hs.dsm.inq.domain.question.persistence.QAnswers.answers import kr.hs.dsm.inq.domain.question.persistence.QComments.comments import kr.hs.dsm.inq.domain.question.persistence.QQuestionSets.questionSets import kr.hs.dsm.inq.domain.question.persistence.QQuestionSolvingHistory.questionSolvingHistory import kr.hs.dsm.inq.domain.question.persistence.QQuestionTags.questionTags +import kr.hs.dsm.inq.domain.question.persistence.QQuestions.questions import kr.hs.dsm.inq.domain.question.persistence.QTags.tags -import kr.hs.dsm.inq.domain.question.persistence.dto.QAnswersDto -import kr.hs.dsm.inq.domain.question.persistence.dto.QQuestionSetDetailDto -import kr.hs.dsm.inq.domain.question.persistence.dto.QQuestionSetDto -import kr.hs.dsm.inq.domain.question.persistence.dto.QuestionSetDetailDto -import kr.hs.dsm.inq.domain.question.persistence.dto.QuestionSetDto +import kr.hs.dsm.inq.domain.question.persistence.dto.* import kr.hs.dsm.inq.domain.user.persistence.QUser import kr.hs.dsm.inq.domain.user.persistence.User import org.springframework.data.repository.CrudRepository @@ -35,7 +35,7 @@ interface CustomQuestionSetsRepository { page: Long ): PageResponse - fun queryQuestionSetDtoById( + fun queryQuestionSetDetailDtoById( user: User, id: Long ): QuestionSetDetailDto? @@ -67,11 +67,12 @@ class CustomQuestionSetsRepositoryImpl( } @Transactional - override fun queryQuestionSetDtoById( + override fun queryQuestionSetDetailDtoById( user: User, id: Long ): QuestionSetDetailDto? { - queryFactory + + queryFactory .update(questionSets) .set(questionSets.viewCount, questionSets.viewCount.add(1)) .where(questionSets.id.eq(id)) @@ -119,12 +120,13 @@ class CustomQuestionSetsRepositoryImpl( val author = QUser("writer") val liked = QLike("liked") val favorite = QFavorite("favorite") + return@run leftJoin(questionTags).on(questionTags.problems.eq(questionSets.problem)) .leftJoin(tags).on(tags.id.eq(questionTags.id.tagId)) .innerJoin(author).on(author.id.eq(questionSets.author.id)) .leftJoin(liked).on(liked.id.userId.eq(user.id)).on(liked.post.eq(questionSets.post)) .leftJoin(favorite).on(favorite.id.userId.eq(user.id)).on(favorite.problemId.eq(questionSets.problem)) - .rightJoin(comments).on(comments.post.eq(questionSets.post)) + .leftJoin(comments).on(comments.post.eq(questionSets.post)) .transform( GroupBy.groupBy(questionSets) .list( @@ -132,19 +134,20 @@ class CustomQuestionSetsRepositoryImpl( /* questionSetId = */ questionSets.id, /* name = */ questionSets.name, /* createdAt = */ questionSets.createdAt, + /* description = */ questionSets.description, /* username = */ author.username, /* job = */ author.job, /* jobDuration = */ author.jobDuration, - /* category = */ questionSets.category, /* likeCount = */ questionSets.likeCount, + /* dislikeCount = */ questionSets.dislikeCount, /* viewCount = */ questionSets.viewCount, /* isLiked = */ liked.isLiked.isTrue, /* isDisliked = */ liked.isLiked.isFalse, /* isFavorite = */ favorite.isNotNull, /* tagList = */ GroupBy.list(tags), - /* comments = */ GroupBy.list(comments) + /* commentList = */ GroupBy.list(comments) ) ) ) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/repository/SetQuestionRepository.kt b/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/repository/SetQuestionRepository.kt index e4e6fc6..715ad18 100644 --- a/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/repository/SetQuestionRepository.kt +++ b/src/main/kotlin/kr/hs/dsm/inq/domain/question/persistence/repository/SetQuestionRepository.kt @@ -4,5 +4,6 @@ import kr.hs.dsm.inq.domain.question.persistence.SetQuestion import kr.hs.dsm.inq.domain.question.persistence.SetQuestionId import org.springframework.data.repository.CrudRepository -interface SetQuestionRepository : CrudRepository { +interface SetQuestionRepository : CrudRepository, CustomQuestionRepository { + fun findAllBySetId(setId: Long): List } \ No newline at end of file diff --git a/src/main/kotlin/kr/hs/dsm/inq/domain/question/presentation/dto/Requests.kt b/src/main/kotlin/kr/hs/dsm/inq/domain/question/presentation/dto/Requests.kt index 945048e..7b8cf29 100644 --- a/src/main/kotlin/kr/hs/dsm/inq/domain/question/presentation/dto/Requests.kt +++ b/src/main/kotlin/kr/hs/dsm/inq/domain/question/presentation/dto/Requests.kt @@ -45,6 +45,7 @@ data class GetPopularQuestionRequest( data class QuestionSetsRequest( val questionSetName: String, + val description: String, val category: Category, val questionId: List, val tag: List, diff --git a/src/main/kotlin/kr/hs/dsm/inq/domain/question/presentation/dto/Responses.kt b/src/main/kotlin/kr/hs/dsm/inq/domain/question/presentation/dto/Responses.kt index 7f73f2c..1d10555 100644 --- a/src/main/kotlin/kr/hs/dsm/inq/domain/question/presentation/dto/Responses.kt +++ b/src/main/kotlin/kr/hs/dsm/inq/domain/question/presentation/dto/Responses.kt @@ -2,10 +2,7 @@ package kr.hs.dsm.inq.domain.question.presentation.dto import kr.hs.dsm.inq.common.util.PageResponse import kr.hs.dsm.inq.common.util.PageUtil -import kr.hs.dsm.inq.domain.question.persistence.Category -import kr.hs.dsm.inq.domain.question.persistence.Comments -import kr.hs.dsm.inq.domain.question.persistence.QuestionSets -import kr.hs.dsm.inq.domain.question.persistence.Tags +import kr.hs.dsm.inq.domain.question.persistence.* import kr.hs.dsm.inq.domain.question.persistence.dto.* import java.time.LocalDateTime import java.util.Date @@ -195,8 +192,8 @@ data class GetQuestionSetResponse( val hasNext: Boolean, val questionSetsList: List, ) { - companion object{ - fun of(pageResponse: PageResponse) = pageResponse.run{ + companion object { + fun of(pageResponse: PageResponse) = pageResponse.run { GetQuestionSetResponse( hasNext = hasNext, questionSetsList = list.map { QuestionSet.of(it) } @@ -205,21 +202,21 @@ data class GetQuestionSetResponse( } } -data class QuestionSet ( - val questionSetId : Long?, - val questionSetName : String?, +data class QuestionSet( + val questionSetId: Long?, + val questionSetName: String?, val createdAt: LocalDateTime, val category: Category?, - val username : String?, - val job : String?, - val jobDuration : Int?, - val tags : List?, - val isAnswered : Boolean?, - val likeCount : Int?, - val viewCount : Int?, + val username: String?, + val job: String?, + val jobDuration: Int?, + val tags: List?, + val isAnswered: Boolean?, + val likeCount: Int?, + val viewCount: Int?, ) { companion object { - fun of (dto: QuestionSetDto) = dto.run { + fun of(dto: QuestionSetDto) = dto.run { QuestionSet( questionSetId = questionSetId, questionSetName = questionSetName, @@ -241,11 +238,13 @@ data class GetQuestionSetDetailResponse( val questionSetId: Long, val name: String, val createdAt: LocalDateTime, + val description: String, val username: String, val job: String, val jobDuration: Int, - val category: Category, + val category: List?, val likeCount: Int, + val dislikeCount: Int, val viewCount: Int, val isLiked: Boolean, val isDisliked: Boolean, @@ -254,16 +253,26 @@ data class GetQuestionSetDetailResponse( val comments: List ) { companion object { - fun of(questionSetDetail: QuestionSetDetailDto) = questionSetDetail.run { + fun of(questionSetDetail: QuestionSetDetailDto, questionList: List) = questionSetDetail.run { GetQuestionSetDetailResponse( questionSetId = questionSetId, name = name, createdAt = createdAt, + description = description, username = username, job = job, jobDuration = jobDuration, - category = category, + category = questionList + .groupingBy { it.category } + .eachCount() + .map { + CategoriesDto( + category = it.key, + count = it.value + ) + }, likeCount = likeCount, + dislikeCount = dislikeCount, viewCount = viewCount, isLiked = isLiked, isDisliked = isDisliked, diff --git a/src/main/kotlin/kr/hs/dsm/inq/domain/question/service/QuestionService.kt b/src/main/kotlin/kr/hs/dsm/inq/domain/question/service/QuestionService.kt index 9f55efc..5539deb 100644 --- a/src/main/kotlin/kr/hs/dsm/inq/domain/question/service/QuestionService.kt +++ b/src/main/kotlin/kr/hs/dsm/inq/domain/question/service/QuestionService.kt @@ -2,10 +2,7 @@ package kr.hs.dsm.inq.domain.question.service import kr.hs.dsm.inq.common.util.SecurityUtil import kr.hs.dsm.inq.common.util.defaultPage -import kr.hs.dsm.inq.domain.question.exception.AlreadyDislikedPostException -import kr.hs.dsm.inq.domain.question.exception.AlreadyLikedPostException -import kr.hs.dsm.inq.domain.question.exception.AnswerNotFoundException -import kr.hs.dsm.inq.domain.question.exception.QuestionNotFoundException +import kr.hs.dsm.inq.domain.question.exception.* import kr.hs.dsm.inq.domain.question.persistence.* import kr.hs.dsm.inq.domain.question.persistence.dto.AnswersDto import kr.hs.dsm.inq.domain.question.persistence.dto.CategoriesDto @@ -295,8 +292,10 @@ class QuestionService( QuestionSets( name = request.questionSetName, answerCount = 0, + description = request.description, category = request.category, likeCount = 0, + dislikeCount = 0, viewCount = 0, post = post, problem = problem, @@ -371,11 +370,14 @@ class QuestionService( val user = SecurityUtil.getCurrentUser() val questionSetDetail = questionSetId.run { - questionSetsRepository.queryQuestionSetDtoById(user, questionSetId) - ?: throw QuestionNotFoundException + questionSetsRepository.queryQuestionSetDetailDtoById(user, questionSetId) + ?: throw QuestionSetNotFoundException } - return GetQuestionSetDetailResponse.of(questionSetDetail) + val setQuestionList = setQuestionRepository.findAllBySetId(questionSetDetail.questionSetId) + val questionList = questionsRepository.findByIdIn(setQuestionList.map { it.question.id }) + + return GetQuestionSetDetailResponse.of(questionSetDetail, questionList) } fun answerQuestionSet(questionSetId: Long){ diff --git a/src/main/kotlin/kr/hs/dsm/inq/global/error/ErrorCode.kt b/src/main/kotlin/kr/hs/dsm/inq/global/error/ErrorCode.kt index 981879c..d01f6b7 100644 --- a/src/main/kotlin/kr/hs/dsm/inq/global/error/ErrorCode.kt +++ b/src/main/kotlin/kr/hs/dsm/inq/global/error/ErrorCode.kt @@ -13,9 +13,10 @@ enum class DomainErrorCode( USER_NOT_FOUND(ErrorStatus.NOT_FOUND, "User Not Found", 1), QUESTION_NOT_FOUND(ErrorStatus.NOT_FOUND, "Question Not Found", 2), - ANSWER_NOT_FOUND(ErrorStatus.NOT_FOUND, "Answer Not Found", 3), - TAG_NOT_FOUND(ErrorStatus.NOT_FOUND, "Tag Not Found", 4), - ATTENDANCE_NOT_FOUND(ErrorStatus.NOT_FOUND, "Attendance Not Found", 5), + QUESTION_SET_NOT_FOUND(ErrorStatus.NOT_FOUND, "Question Set Not Found", 3), + ANSWER_NOT_FOUND(ErrorStatus.NOT_FOUND, "Answer Not Found", 4), + TAG_NOT_FOUND(ErrorStatus.NOT_FOUND, "Tag Not Found", 5), + ATTENDANCE_NOT_FOUND(ErrorStatus.NOT_FOUND, "Attendance Not Found", 6), ALREADY_LIKED_POST(ErrorStatus.CONFLICT, "Already liked post", 1), ALREADY_DISLIKED_POST(ErrorStatus.CONFLICT, "Already disliked post", 2),