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

[FIX] Answer, Question 관련 오류 수정 #39

Merged
merged 11 commits into from
Apr 15, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import com.th.plu.api.controller.answer.dto.response.AnswerInfoResponse
import com.th.plu.api.controller.answer.dto.response.EveryAnswerInfoResponse
import com.th.plu.api.controller.answer.dto.toAnswerWriting
import com.th.plu.api.controller.answer.dto.toWritingAnswerResponse
import com.th.plu.common.dto.response.ApiResponse
import com.th.plu.api.service.answer.AnswerService
import com.th.plu.common.dto.response.ApiResponse
import com.th.plu.domain.domain.answer.dto.EveryAnswerRetrieveResponses
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
Expand Down Expand Up @@ -62,7 +62,7 @@ class AnswerController(
@GetMapping("/v1/answers/info")
fun findEveryAnswerInfo(
): ApiResponse<EveryAnswerInfoResponse> {
return ApiResponse.success(answerService.findEveryAnswerInfo())
return ApiResponse.success(answerService.findAllAnswerInfo())
}

@Auth
Expand All @@ -72,7 +72,7 @@ class AnswerController(
@RequestParam(defaultValue = Long.MAX_VALUE.toString()) lastAnswerId: Long,
@RequestParam(defaultValue = "10") pageSize: Long,
): ApiResponse<EveryAnswerRetrieveResponses> {
return ApiResponse.success(answerService.findEveryAnswersWithCursor(lastAnswerId, pageSize))
return ApiResponse.success(answerService.findAllAnswersWithCursor(lastAnswerId, pageSize))
}

@Auth
Expand All @@ -81,6 +81,6 @@ class AnswerController(
fun getAnswersAboutLikeTopN(
@RequestParam(defaultValue = "10") getCount: Long,
): ApiResponse<EveryAnswerRetrieveResponses> {
return ApiResponse.success(answerService.findEveryAnswersLikeTopN(getCount))
return ApiResponse.success(answerService.findAllAnswersLikeTopN(getCount))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import com.th.plu.domain.domain.like.Like
import com.th.plu.domain.domain.like.explorer.LikeExplorer
import com.th.plu.domain.domain.like.repository.LikeRepository
import com.th.plu.domain.domain.member.explorer.MemberExplorer
import com.th.plu.domain.domain.question.QuestionExplorer
import com.th.plu.domain.domain.question.explorer.QuestionExplorer
import com.th.plu.domain.isUniqueError
import org.springframework.dao.DataIntegrityViolationException
import org.springframework.stereotype.Service
Expand Down Expand Up @@ -63,21 +63,21 @@ class AnswerService(
}

@Transactional(readOnly = true)
fun findEveryAnswersWithCursor(lastAnswerId: Long, pageSize: Long): EveryAnswerRetrieveResponses {
fun findAllAnswersWithCursor(lastAnswerId: Long, pageSize: Long): EveryAnswerRetrieveResponses {
val todayQuestionId = questionExplorer.findTodayQuestion().id
val answers = answerRepository.findEveryAnswersWithCursorAndPageSize(todayQuestionId, lastAnswerId, pageSize)
return EveryAnswerRetrieveResponses(answers)
}

@Transactional(readOnly = true)
fun findEveryAnswerInfo(): EveryAnswerInfoResponse {
fun findAllAnswerInfo(): EveryAnswerInfoResponse {
val todayQuestion = questionExplorer.findTodayQuestion()
val answerCount = answerRepository.findPublicAnswersCountByQuestionId(todayQuestion.id)

return EveryAnswerInfoResponse.of(todayQuestion, answerCount)
}

fun findEveryAnswersLikeTopN(getCount: Long): EveryAnswerRetrieveResponses {
fun findAllAnswersLikeTopN(getCount: Long): EveryAnswerRetrieveResponses {
val todayQuestion = questionExplorer.findTodayQuestion()
sookyungg marked this conversation as resolved.
Show resolved Hide resolved
val answers = answerRepository.findPublicAnswersLikeTopN(todayQuestion.id, getCount)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.th.plu.api.service.question

import com.th.plu.domain.domain.answer.AnswerExplorer
import com.th.plu.domain.domain.question.QuestionExplorer
import com.th.plu.domain.domain.answer.explorer.AnswerExplorer
import com.th.plu.domain.domain.question.QuestionResultDto
import com.th.plu.domain.domain.question.explorer.QuestionExplorer
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDateTime
Expand All @@ -17,7 +17,7 @@ class QuestionService(
fun getQuestionToday(memberId: Long): QuestionResultDto {
val today = LocalDateTime.now()

return questionExplorer.findQuestion(today).let { todayQuestion ->
return questionExplorer.findQuestionByDateTime(today).let { todayQuestion ->
val answered = answerExplorer.hasAnswered(memberId, todayQuestion.id)

QuestionResultDto(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ class Answer(
private var _id: Long? = null,

@ManyToOne(fetch = FetchType.LAZY, cascade = [CascadeType.ALL])
@JoinColumn(name = "member_id", nullable = false)
private var member: Member,
@JoinColumn(name = "member_id", nullable = false) var member: Member,

@ManyToOne(fetch = FetchType.LAZY, cascade = [CascadeType.ALL])
@JoinColumn(name = "question_id", nullable = false)
Expand All @@ -53,6 +52,10 @@ class Answer(
private set

val questionId: Long = question.id

fun getLikeCount(): Int {
return likes.size
}
sookyungg marked this conversation as resolved.
Show resolved Hide resolved
}

fun newAnswerInstance(member: Member, question: Question, content: String, isPublic: Boolean) = Answer(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ import org.springframework.stereotype.Component

@Component
class AnswerExplorer(
private val answerRepository: AnswerRepository
private val answerRepository: AnswerRepository
) {
fun findAnswerById(id: Long): Answer {
return answerRepository.findAnswerById(id)
?: throw NotFoundException(ErrorCode.NOT_FOUND_ANSWER_EXCEPTION, "존재하지 않는 답변(ID: $id) 입니다")
?: throw NotFoundException(ErrorCode.NOT_FOUND_ANSWER_EXCEPTION, "존재하지 않는 답변(ID: $id) 입니다")
}

fun hasAnswered(memberId: Long, questionId: Long): Boolean {
return answerRepository.existsByMemberIdAndQuestionId(memberId, questionId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,48 @@ import org.springframework.stereotype.Repository
class AnswerRepositoryImpl(private val queryFactory: JPAQueryFactory) : AnswerRepositoryCustom {
override fun findAnswerById(id: Long): Answer? {
return queryFactory
.selectFrom(answer)
.where(answer.id.eq(id))
.fetchOne()
.selectFrom(answer)
.where(answer._id.eq(id))
.fetchOne()
}

override fun findEveryAnswersWithCursorAndPageSize(questionId: Long, lastAnswerId: Long, pageSize: Long): List<EveryAnswerRetrieveResponse> {
return queryFactory
.select(QEveryAnswerRetrieveResponse(answer.id, like.answer.id.count(), answer.content))
.from(answer)
.leftJoin(like).on(like.answer.id.eq(answer.id))
.where(
answer.isPublic.eq(true),
answer.question.id.eq(questionId),
answer.id.lt(lastAnswerId),
)
.groupBy(answer.id)
.orderBy(answer.id.desc())
.limit(pageSize)
.fetch()
.select(QEveryAnswerRetrieveResponse(answer._id, like.answer._id.count(), answer.content))
.from(answer)
.leftJoin(like).on(like.answer._id.eq(answer._id))
.where(
answer.isPublic.eq(true),
answer.question._id.eq(questionId),
answer._id.lt(lastAnswerId),
)
.groupBy(answer._id)
.orderBy(answer._id.desc())
.limit(pageSize)
.fetch()
}

override fun findPublicAnswersCountByQuestionId(questionId: Long): Long {
return queryFactory
.select(answer.id.count())
.from(answer)
.where(answer.question.id.eq(questionId))
.fetchOne()!!
.select(answer._id.count())
.from(answer)
.where(answer.question._id.eq(questionId))
.fetchOne()!!
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!! 는 빼야할것같은데요
fun findPublicAnswersCountByQuestionId(questionId: Long): Long? 이렇게 바꿔야할듯

}

override fun findPublicAnswersLikeTopN(questionId: Long, getCount: Long): List<EveryAnswerRetrieveResponse> {
return queryFactory
.select(QEveryAnswerRetrieveResponse(answer.id, like.answer.id.count(), answer.content))
.from(answer)
.leftJoin(like).on(like.answer.id.eq(answer.id))
.where(
answer.isPublic.eq(true),
answer.question.id.eq(questionId)
)
.groupBy(answer.id)
.orderBy(like.answer.id.count().desc())
.limit(getCount)
.fetch()
.select(QEveryAnswerRetrieveResponse(answer._id, like.answer._id.count(), answer.content))
.from(answer)
.leftJoin(like).on(like.answer._id.eq(answer._id))
.where(
answer.isPublic.eq(true),
answer.question._id.eq(questionId)
)
.groupBy(answer._id)
.orderBy(like.answer._id.count().desc())
.limit(getCount)
.fetch()
}

override fun existsByMemberIdAndQuestionId(memberId: Long, questionId: Long): Boolean {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,22 +1,55 @@
package com.th.plu.domain.domain.answer.explorer
package com.th.plu.domain.domain.question.explorer

import com.th.plu.common.exception.code.ErrorCode
import com.th.plu.common.exception.model.InternalServerException
import com.th.plu.common.exception.model.NotFoundException
import com.th.plu.domain.domain.question.Question
import com.th.plu.domain.domain.question.repository.QuestionRepository
import org.springframework.stereotype.Component
import java.time.LocalDateTime
import java.time.YearMonth

@Component
class QuestionExplorer(
private val questionRepository: QuestionRepository
private val questionRepository: QuestionRepository,
) {
fun findQuestionById(id: Long): Question {
return questionRepository.findQuestionById(id)
?: throw NotFoundException(ErrorCode.NOT_FOUND_QUESTION_EXCEPTION, "존재하지 않는 질문(ID: $id) 입니다")
fun findQuestion(id: Long): Question =
questionRepository.findById(id).orElse(null)
?: throw NotFoundException(ErrorCode.NOT_FOUND_QUESTION_EXCEPTION, "존재하지 않는 질문 $id 입니다")
sookyungg marked this conversation as resolved.
Show resolved Hide resolved

fun findQuestionByDateTime(dateTime: LocalDateTime): Question {
// 입력된 dateTime이 밤 10시 이후인지 확인
val isAfterTenPM = dateTime.hour >= 22

// 밤 10시 이후인 경우, startOfQuestionPeriod를 그 날의 밤 10시로 설정
// 그렇지 않으면, startOfQuestionPeriod를 전날의 밤 10시로 설정
val startOfQuestionPeriod = if (isAfterTenPM) {
dateTime.toLocalDate().atTime(22, 0)
} else {
dateTime.toLocalDate().minusDays(1).atTime(22, 0)
}

// endOfQuestionPeriod는 startOfQuestionPeriod에서 하루를 더한 후, 밤 9시 59분 59초로 설정
val endOfQuestionPeriod = startOfQuestionPeriod.plusDays(1).withHour(21).withMinute(59).withSecond(59)

// 해당 기간 내의 첫 번째 질문을 조회
return questionRepository.findByExposedAtOrNull(startOfQuestionPeriod, endOfQuestionPeriod)
?: throw InternalServerException(
ErrorCode.DATA_NOT_READY_EXCEPTION,
"($dateTime) 날짜의 질문데이터가 준비되지 않았습니다."
)
}

fun findMyQuestionsMonthly(memberId: Long, yearMonth: YearMonth): List<Question> =
questionRepository.findAllByExposedMonthIn(memberId, yearMonth)

fun findAnsweredYearMonth(memberId: Long): Set<YearMonth> =
questionRepository.findAllExposedAtInAnsweredMonth(memberId)
.map { YearMonth.of(it.year, it.monthValue) }
.toSet() // application 에서 중복 처리중, 500 넘는 warn log 발생시 월별 1건 조회하도록 쿼리 개선 필요!

fun findTodayQuestion(): Question {
return questionRepository.findTodayQuestion()
?: throw NotFoundException(ErrorCode.NOT_FOUND_QUESTION_EXCEPTION, "오늘의 질문이 존재하지 않습니다")
return findQuestionByDateTime(LocalDateTime.now())
}

}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package com.th.plu.domain.domain.question.repository

import com.th.plu.domain.domain.question.Question
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.YearMonth


interface QuestionRepositoryCustom {
fun findQuestionById(id: Long): Question?

fun findByExposedAtOrNull(exposedAt: LocalDateTime): Question?
fun findByExposedAtOrNull(startOfPeriod: LocalDateTime, endOfPeriod: LocalDateTime): Question?

fun findAllByExposedMonthIn(memberId: Long, yearMonth: YearMonth): List<Question>

fun findAllExposedAtInAnsweredMonth(memberId: Long): List<LocalDateTime>

fun findTodayQuestion(): Question?
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import com.th.plu.domain.domain.member.QMember.member
import com.th.plu.domain.domain.question.QQuestion.question
import com.th.plu.domain.domain.question.Question
import org.springframework.stereotype.Repository
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.YearMonth

Expand All @@ -21,11 +20,12 @@ class QuestionRepositoryImpl(private val queryFactory: JPAQueryFactory) : Questi
.fetchOne()
}

override fun findByExposedAtOrNull(exposedAt: LocalDateTime): Question? {

override fun findByExposedAtOrNull(startOfPeriod: LocalDateTime, endOfPeriod: LocalDateTime): Question? {
return queryFactory
.selectFrom(question)
.where(question.exposedAt.eq(exposedAt))
.fetchOne()
.where(question.exposedAt.between(startOfPeriod, endOfPeriod))
.fetchFirst()
}

override fun findAllByExposedMonthIn(memberId: Long, yearMonth: YearMonth): List<Question> {
Expand Down Expand Up @@ -72,12 +72,4 @@ class QuestionRepositoryImpl(private val queryFactory: JPAQueryFactory) : Questi
}
}

override fun findTodayQuestion(): Question? {
val today = LocalDate.now()

return queryFactory
.selectFrom(question)
.where(question.questionDate.eq(today))
.fetchOne()
}
}
}
Loading