-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: 스터치 회차 에러코드 추가 * feat: 스터디 회차 관련 조회 메서드 추가 * feat: 회차 ID로 스터디 조회하는 메서드 추가 * feat: 과제 제출 가능 검증 로직 추가 * feat: 과제 히스토리 레포지터리 추가 * feat: 과제 채점 도메인 서비스 V2 추가 * feat: 과제 제출하기 V2 API 구현 * feat: 누락된 리턴문 추가 * fix: 오타 수정 * refactor: 메서드 이름 수정
- Loading branch information
Showing
10 changed files
with
238 additions
and
5 deletions.
There are no files selected for viewing
27 changes: 27 additions & 0 deletions
27
...ain/java/com/gdschongik/gdsc/domain/studyv2/api/StudentAssignmentHistoryControllerV2.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.api; | ||
|
||
import com.gdschongik.gdsc.domain.studyv2.application.StudentAssignmentHistoryServiceV2; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@Tag(name = "Student Assignment History V2", description = "학생 과제 제출이력 API입니다.") | ||
@RestController | ||
@RequestMapping("/v2/assignment-histories") | ||
@RequiredArgsConstructor | ||
public class StudentAssignmentHistoryControllerV2 { | ||
|
||
private final StudentAssignmentHistoryServiceV2 studentAssignmentHistoryServiceV2; | ||
|
||
@Operation(summary = "내 과제 제출하기", description = "나의 과제를 제출합니다. 제출된 과제는 채점되어 제출내역에 반영됩니다.") | ||
@PostMapping("/submit") | ||
public ResponseEntity<Void> submitMyAssignment(@RequestParam(name = "studySessionId") Long studySessionId) { | ||
studentAssignmentHistoryServiceV2.submitMyAssignment(studySessionId); | ||
return ResponseEntity.ok().build(); | ||
} | ||
} |
77 changes: 77 additions & 0 deletions
77
...ava/com/gdschongik/gdsc/domain/studyv2/application/StudentAssignmentHistoryServiceV2.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.application; | ||
|
||
import static com.gdschongik.gdsc.global.exception.ErrorCode.*; | ||
|
||
import com.gdschongik.gdsc.domain.member.domain.Member; | ||
import com.gdschongik.gdsc.domain.study.domain.AssignmentSubmissionFetcher; | ||
import com.gdschongik.gdsc.domain.studyv2.dao.AssignmentHistoryV2Repository; | ||
import com.gdschongik.gdsc.domain.studyv2.dao.StudyHistoryV2Repository; | ||
import com.gdschongik.gdsc.domain.studyv2.dao.StudyV2Repository; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.AssignmentHistoryGraderV2; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.AssignmentHistoryV2; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.AssignmentHistoryValidatorV2; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.StudyHistoryV2; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.StudySessionV2; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.StudyV2; | ||
import com.gdschongik.gdsc.global.exception.CustomException; | ||
import com.gdschongik.gdsc.global.util.MemberUtil; | ||
import com.gdschongik.gdsc.infra.github.client.GithubClient; | ||
import jakarta.transaction.Transactional; | ||
import java.time.LocalDateTime; | ||
import java.util.Optional; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
public class StudentAssignmentHistoryServiceV2 { | ||
|
||
private final MemberUtil memberUtil; | ||
private final GithubClient githubClient; | ||
private final StudyV2Repository studyV2Repository; | ||
private final StudyHistoryV2Repository studyHistoryV2Repository; | ||
private final AssignmentHistoryV2Repository assignmentHistoryV2Repository; | ||
private final AssignmentHistoryValidatorV2 assignmentHistoryValidatorV2; | ||
private final AssignmentHistoryGraderV2 assignmentHistoryGraderV2; | ||
|
||
@Transactional | ||
public void submitMyAssignment(Long studySessionId) { | ||
Member currentMember = memberUtil.getCurrentMember(); | ||
StudyV2 study = studyV2Repository | ||
.findFetchBySessionId(studySessionId) | ||
.orElseThrow(() -> new CustomException(STUDY_NOT_FOUND)); | ||
Optional<StudyHistoryV2> optionalStudyHistory = | ||
studyHistoryV2Repository.findByStudentAndStudy(currentMember, study); | ||
|
||
boolean isAppliedToStudy = optionalStudyHistory.isPresent(); | ||
StudySessionV2 studySession = study.getStudySession(studySessionId); | ||
LocalDateTime now = LocalDateTime.now(); | ||
|
||
assignmentHistoryValidatorV2.validateSubmitAvailable(isAppliedToStudy, studySession, now); | ||
|
||
String repositoryLink = | ||
optionalStudyHistory.map(StudyHistoryV2::getRepositoryLink).orElse(null); | ||
AssignmentSubmissionFetcher fetcher = | ||
githubClient.getLatestAssignmentSubmissionFetcher(repositoryLink, studySession.getPosition()); | ||
AssignmentHistoryV2 assignmentHistory = findOrCreate(currentMember, studySession); | ||
|
||
assignmentHistoryGraderV2.judge(fetcher, assignmentHistory); | ||
|
||
assignmentHistoryV2Repository.save(assignmentHistory); | ||
|
||
log.info( | ||
"[StudentAssignmentHistoryServiceV2] 과제 제출: studySessionId={}, studentId={}, submissionStatus={}, submissionFailureType={}", | ||
studySessionId, | ||
currentMember.getId(), | ||
assignmentHistory.getSubmissionStatus(), | ||
assignmentHistory.getSubmissionFailureType()); | ||
} | ||
|
||
private AssignmentHistoryV2 findOrCreate(Member student, StudySessionV2 studySession) { | ||
return assignmentHistoryV2Repository | ||
.findByMemberAndStudySession(student, studySession) | ||
.orElseGet(() -> AssignmentHistoryV2.create(studySession, student)); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/AssignmentHistoryV2Repository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.dao; | ||
|
||
import com.gdschongik.gdsc.domain.member.domain.Member; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.AssignmentHistoryV2; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.StudySessionV2; | ||
import java.util.Optional; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface AssignmentHistoryV2Repository extends JpaRepository<AssignmentHistoryV2, Long> { | ||
Optional<AssignmentHistoryV2> findByMemberAndStudySession(Member member, StudySessionV2 studySession); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
src/main/java/com/gdschongik/gdsc/domain/studyv2/domain/AssignmentHistoryGraderV2.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.domain; | ||
|
||
import static com.gdschongik.gdsc.domain.study.domain.SubmissionFailureType.*; | ||
import static com.gdschongik.gdsc.global.exception.ErrorCode.*; | ||
|
||
import com.gdschongik.gdsc.domain.study.domain.AssignmentSubmission; | ||
import com.gdschongik.gdsc.domain.study.domain.AssignmentSubmissionFetcher; | ||
import com.gdschongik.gdsc.domain.study.domain.SubmissionFailureType; | ||
import com.gdschongik.gdsc.global.annotation.DomainService; | ||
import com.gdschongik.gdsc.global.exception.CustomException; | ||
import com.gdschongik.gdsc.global.exception.ErrorCode; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Slf4j | ||
@DomainService | ||
public class AssignmentHistoryGraderV2 { | ||
|
||
private static final int MINIMUM_ASSIGNMENT_CONTENT_LENGTH = 300; | ||
|
||
public void judge(AssignmentSubmissionFetcher assignmentSubmissionFetcher, AssignmentHistoryV2 assignmentHistory) { | ||
try { | ||
AssignmentSubmission assignmentSubmission = assignmentSubmissionFetcher.fetch(); | ||
judgeAssignmentSubmission(assignmentSubmission, assignmentHistory); | ||
} catch (CustomException e) { | ||
SubmissionFailureType failureType = translateException(e); | ||
assignmentHistory.fail(failureType); | ||
} | ||
} | ||
|
||
private void judgeAssignmentSubmission( | ||
AssignmentSubmission assignmentSubmission, AssignmentHistoryV2 assignmentHistory) { | ||
if (assignmentSubmission.contentLength() < MINIMUM_ASSIGNMENT_CONTENT_LENGTH) { | ||
assignmentHistory.fail(WORD_COUNT_INSUFFICIENT); | ||
return; | ||
} | ||
|
||
assignmentHistory.success( | ||
assignmentSubmission.url(), | ||
assignmentSubmission.commitHash(), | ||
assignmentSubmission.contentLength(), | ||
assignmentSubmission.committedAt()); | ||
} | ||
|
||
private SubmissionFailureType translateException(CustomException e) { | ||
ErrorCode errorCode = e.getErrorCode(); | ||
|
||
if (errorCode == GITHUB_CONTENT_NOT_FOUND) { | ||
return LOCATION_UNIDENTIFIABLE; | ||
} | ||
|
||
log.warn("[AssignmentHistoryGrader] 과제 제출정보 조회 중 알 수 없는 오류 발생: {}", e.getMessage()); | ||
|
||
return UNKNOWN; | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/main/java/com/gdschongik/gdsc/domain/studyv2/domain/AssignmentHistoryValidatorV2.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.domain; | ||
|
||
import static com.gdschongik.gdsc.global.exception.ErrorCode.*; | ||
|
||
import com.gdschongik.gdsc.global.annotation.DomainService; | ||
import com.gdschongik.gdsc.global.exception.CustomException; | ||
import java.time.LocalDateTime; | ||
|
||
@DomainService | ||
public class AssignmentHistoryValidatorV2 { | ||
|
||
/** | ||
* 채점을 수행하기 전, 과제 제출이 가능한지 검증합니다. | ||
*/ | ||
public void validateSubmitAvailable(boolean isAppliedToStudy, StudySessionV2 studySession, LocalDateTime now) { | ||
if (!isAppliedToStudy) { | ||
throw new CustomException(ASSIGNMENT_STUDY_NOT_APPLIED); | ||
} | ||
|
||
studySession.validateAssignmentSubmittable(now); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters