From 982321bbb1cc97380723bf34f5c70759d178062a Mon Sep 17 00:00:00 2001 From: adorableco Date: Sat, 19 Oct 2024 08:35:26 +0900 Subject: [PATCH] Feat:readAllSharedExams --- .../phote/controller/ExamController.kt | 17 +++-- .../com/swm_standard/phote/dto/ExamDtos.kt | 16 +++++ .../com/swm_standard/phote/entity/Exam.kt | 2 +- .../swm_standard/phote/entity/ExamStatus.kt | 7 ++ .../phote/entity/ParticipationType.kt | 6 ++ .../phote/repository/ExamResultRepository.kt | 9 ++- .../phote/repository/SharedExamRepository.kt | 9 +++ .../swm_standard/phote/service/ExamService.kt | 67 +++++++++++++++++-- 8 files changed, 123 insertions(+), 10 deletions(-) create mode 100644 src/main/kotlin/com/swm_standard/phote/entity/ExamStatus.kt create mode 100644 src/main/kotlin/com/swm_standard/phote/entity/ParticipationType.kt create mode 100644 src/main/kotlin/com/swm_standard/phote/repository/SharedExamRepository.kt diff --git a/src/main/kotlin/com/swm_standard/phote/controller/ExamController.kt b/src/main/kotlin/com/swm_standard/phote/controller/ExamController.kt index 9c7a2d0..71633da 100644 --- a/src/main/kotlin/com/swm_standard/phote/controller/ExamController.kt +++ b/src/main/kotlin/com/swm_standard/phote/controller/ExamController.kt @@ -6,12 +6,13 @@ import com.swm_standard.phote.dto.CreateSharedExamRequest import com.swm_standard.phote.dto.CreateSharedExamResponse import com.swm_standard.phote.dto.GradeExamRequest import com.swm_standard.phote.dto.GradeExamResponse -import com.swm_standard.phote.dto.RegradeExamRequest -import com.swm_standard.phote.dto.RegradeExamResponse +import com.swm_standard.phote.dto.ReadAllSharedExamsResponse import com.swm_standard.phote.dto.ReadExamHistoryDetailResponse import com.swm_standard.phote.dto.ReadExamHistoryListResponse -import com.swm_standard.phote.dto.ReadExamResultsResponse import com.swm_standard.phote.dto.ReadExamResultDetailResponse +import com.swm_standard.phote.dto.ReadExamResultsResponse +import com.swm_standard.phote.dto.RegradeExamRequest +import com.swm_standard.phote.dto.RegradeExamResponse import com.swm_standard.phote.service.ExamService import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.Parameter @@ -19,9 +20,9 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PatchMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.PatchMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @@ -112,4 +113,12 @@ class ExamController( return BaseResponse(data = CreateSharedExamResponse(sharedExamId), msg = "공유용 시험 생성 성공") } + + @Operation(summary = "readAllSharedExams", description = "공유용 시험 목록 조회") + @SecurityRequirement(name = "bearer Auth") + @GetMapping("/exams") + fun readAllSharedExams( + @Parameter(hidden = true) @MemberId memberId: UUID, + ): BaseResponse> = + BaseResponse(data = examService.readAllSharedExams(memberId), msg = "공유용 시험 목록 조회 성공") } diff --git a/src/main/kotlin/com/swm_standard/phote/dto/ExamDtos.kt b/src/main/kotlin/com/swm_standard/phote/dto/ExamDtos.kt index 8425dcb..b90e8ec 100644 --- a/src/main/kotlin/com/swm_standard/phote/dto/ExamDtos.kt +++ b/src/main/kotlin/com/swm_standard/phote/dto/ExamDtos.kt @@ -2,6 +2,8 @@ package com.swm_standard.phote.dto import com.fasterxml.jackson.annotation.JsonProperty import com.swm_standard.phote.entity.Category +import com.swm_standard.phote.entity.ExamStatus +import com.swm_standard.phote.entity.ParticipationType import jakarta.validation.constraints.NotBlank import jakarta.validation.constraints.Positive import java.time.LocalDateTime @@ -121,3 +123,17 @@ data class CreateSharedExamRequest( data class CreateSharedExamResponse( val sharedExamId: UUID, ) + +data class ReadAllSharedExamsResponse( + val examId: UUID, + val creator: String, + val title: String, + val startTime: LocalDateTime, + val endTime: LocalDateTime, + val status: ExamStatus, + val role: ParticipationType, + val capacity: Int? = null, + val examineeCount: Int? = null, + val totalCorrect: Int? = null, + val questionQuantity: Int? = null, +) diff --git a/src/main/kotlin/com/swm_standard/phote/entity/Exam.kt b/src/main/kotlin/com/swm_standard/phote/entity/Exam.kt index f5b5fa5..af4afa4 100644 --- a/src/main/kotlin/com/swm_standard/phote/entity/Exam.kt +++ b/src/main/kotlin/com/swm_standard/phote/entity/Exam.kt @@ -20,7 +20,7 @@ data class Exam( @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") val member: Member, - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "workbook_id") val workbook: Workbook, val sequence: Int, diff --git a/src/main/kotlin/com/swm_standard/phote/entity/ExamStatus.kt b/src/main/kotlin/com/swm_standard/phote/entity/ExamStatus.kt new file mode 100644 index 0000000..b08b681 --- /dev/null +++ b/src/main/kotlin/com/swm_standard/phote/entity/ExamStatus.kt @@ -0,0 +1,7 @@ +package com.swm_standard.phote.entity + +enum class ExamStatus { + NOT_STARTED, + IN_PROGRESS, + COMPLETED, +} diff --git a/src/main/kotlin/com/swm_standard/phote/entity/ParticipationType.kt b/src/main/kotlin/com/swm_standard/phote/entity/ParticipationType.kt new file mode 100644 index 0000000..7a9a81e --- /dev/null +++ b/src/main/kotlin/com/swm_standard/phote/entity/ParticipationType.kt @@ -0,0 +1,6 @@ +package com.swm_standard.phote.entity + +enum class ParticipationType { + CREATOR, + EXAMINEE, +} diff --git a/src/main/kotlin/com/swm_standard/phote/repository/ExamResultRepository.kt b/src/main/kotlin/com/swm_standard/phote/repository/ExamResultRepository.kt index 2101698..0965b06 100644 --- a/src/main/kotlin/com/swm_standard/phote/repository/ExamResultRepository.kt +++ b/src/main/kotlin/com/swm_standard/phote/repository/ExamResultRepository.kt @@ -6,6 +6,13 @@ import java.util.UUID interface ExamResultRepository : JpaRepository { fun findByExamId(examId: UUID): ExamResult? - fun findByExamIdAndMemberId(examId: UUID, memberId: UUID): ExamResult + + fun findByExamIdAndMemberId( + examId: UUID, + memberId: UUID, + ): ExamResult + fun findAllByExamId(examId: UUID): List + + fun findAllByMemberId(memberId: UUID): List } diff --git a/src/main/kotlin/com/swm_standard/phote/repository/SharedExamRepository.kt b/src/main/kotlin/com/swm_standard/phote/repository/SharedExamRepository.kt new file mode 100644 index 0000000..552951c --- /dev/null +++ b/src/main/kotlin/com/swm_standard/phote/repository/SharedExamRepository.kt @@ -0,0 +1,9 @@ +package com.swm_standard.phote.repository + +import com.swm_standard.phote.entity.SharedExam +import org.springframework.data.jpa.repository.JpaRepository +import java.util.UUID + +interface SharedExamRepository : JpaRepository { + fun findAllByMemberId(memberId: UUID): List +} diff --git a/src/main/kotlin/com/swm_standard/phote/service/ExamService.kt b/src/main/kotlin/com/swm_standard/phote/service/ExamService.kt index 2f4a132..0604d56 100644 --- a/src/main/kotlin/com/swm_standard/phote/service/ExamService.kt +++ b/src/main/kotlin/com/swm_standard/phote/service/ExamService.kt @@ -8,26 +8,30 @@ import com.swm_standard.phote.dto.ChatGPTResponse import com.swm_standard.phote.dto.CreateSharedExamRequest import com.swm_standard.phote.dto.GradeExamRequest import com.swm_standard.phote.dto.GradeExamResponse -import com.swm_standard.phote.dto.RegradeExamRequest -import com.swm_standard.phote.dto.RegradeExamResponse +import com.swm_standard.phote.dto.ReadAllSharedExamsResponse import com.swm_standard.phote.dto.ReadExamHistoryDetail import com.swm_standard.phote.dto.ReadExamHistoryDetailResponse import com.swm_standard.phote.dto.ReadExamHistoryListResponse -import com.swm_standard.phote.dto.ReadExamResultsResponse import com.swm_standard.phote.dto.ReadExamResultDetail import com.swm_standard.phote.dto.ReadExamResultDetailResponse +import com.swm_standard.phote.dto.ReadExamResultsResponse import com.swm_standard.phote.dto.ReadExamStudentResult +import com.swm_standard.phote.dto.RegradeExamRequest +import com.swm_standard.phote.dto.RegradeExamResponse import com.swm_standard.phote.dto.SubmittedAnswerRequest import com.swm_standard.phote.entity.Answer import com.swm_standard.phote.entity.Category import com.swm_standard.phote.entity.Exam import com.swm_standard.phote.entity.ExamResult +import com.swm_standard.phote.entity.ExamStatus import com.swm_standard.phote.entity.Member +import com.swm_standard.phote.entity.ParticipationType import com.swm_standard.phote.entity.SharedExam import com.swm_standard.phote.entity.Workbook import com.swm_standard.phote.repository.AnswerRepository import com.swm_standard.phote.repository.ExamResultRepository import com.swm_standard.phote.repository.MemberRepository +import com.swm_standard.phote.repository.SharedExamRepository import com.swm_standard.phote.repository.examrepository.ExamRepository import com.swm_standard.phote.repository.questionrepository.QuestionRepository import com.swm_standard.phote.repository.workbookrepository.WorkbookRepository @@ -40,9 +44,19 @@ import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import org.springframework.web.client.RestTemplate +import java.time.LocalDateTime import java.util.UUID import kotlin.jvm.optionals.getOrElse +private fun SharedExam.checkStatus(): ExamStatus = + if (this.startTime.isAfter(LocalDateTime.now())) { + ExamStatus.NOT_STARTED + } else if (this.endTime.isBefore(LocalDateTime.now())) { + ExamStatus.COMPLETED + } else { + ExamStatus.IN_PROGRESS + } + @Service @Transactional(readOnly = true) class ExamService( @@ -53,6 +67,7 @@ class ExamService( private val answerRepository: AnswerRepository, private val template: RestTemplate, private val examResultRepository: ExamResultRepository, + private val sharedExamRepository: SharedExamRepository, ) { @Value("\${openai.model.grading}") lateinit var model: String @@ -126,7 +141,10 @@ class ExamService( return ReadExamResultsResponse(examId, exam.workbook.quantity, responses) } - fun readExamResultDetail(examId: UUID, memberId: UUID): ReadExamResultDetailResponse { + fun readExamResultDetail( + examId: UUID, + memberId: UUID, + ): ReadExamResultDetailResponse { val examResult = examResultRepository.findByExamIdAndMemberId(examId, memberId) val responses = buildList { @@ -300,6 +318,47 @@ class ExamService( } } + fun readAllSharedExams(memberId: UUID): List { + val examsAsCreator = + ( + sharedExamRepository + .findAllByMemberId(memberId) + ).map { exam -> + ReadAllSharedExamsResponse( + examId = exam.id!!, + creator = exam.member.name, + title = exam.title, + startTime = exam.startTime, + endTime = exam.endTime, + capacity = exam.capacity, + status = exam.checkStatus(), + role = ParticipationType.CREATOR, + examineeCount = exam.examineeCount, + ) + } + + val examsAsExaminee = + examResultRepository + .findAllByMemberId(memberId) + .filter { it.exam is SharedExam } + .map { examResult -> + val sharedExam = examResult.exam as SharedExam + ReadAllSharedExamsResponse( + examId = examResult.exam.id!!, + creator = sharedExam.member.name, + title = sharedExam.title, + startTime = sharedExam.startTime, + endTime = sharedExam.endTime, + status = sharedExam.checkStatus(), + role = ParticipationType.EXAMINEE, + totalCorrect = examResult.totalCorrect, + questionQuantity = examResult.calculateTotalQuantity(), + ) + } + + return examsAsCreator + examsAsExaminee + } + private fun findWorkbook(workbookId: UUID): Workbook = workbookRepository .findById(