-
Notifications
You must be signed in to change notification settings - Fork 1
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 추가 #594
Changes from 7 commits
a0eb5e6
c34d2dd
fc70a79
513ddbc
2aced6f
c8be71d
dc1361e
501f005
0e7a6c3
be273f1
6310570
eb8cc08
87555c5
d97e05b
81b3b5c
1eb8af5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,20 @@ | ||
package com.gdschongik.gdsc.domain.study.application; | ||
|
||
import static com.gdschongik.gdsc.global.common.constant.GithubConstant.*; | ||
import static com.gdschongik.gdsc.global.exception.ErrorCode.*; | ||
|
||
import com.gdschongik.gdsc.domain.member.domain.Member; | ||
import com.gdschongik.gdsc.domain.study.dao.AssignmentHistoryRepository; | ||
import com.gdschongik.gdsc.domain.study.dao.StudyHistoryRepository; | ||
import com.gdschongik.gdsc.domain.study.dao.StudyRepository; | ||
import com.gdschongik.gdsc.domain.study.domain.Study; | ||
import com.gdschongik.gdsc.domain.study.domain.StudyHistory; | ||
import com.gdschongik.gdsc.domain.study.domain.StudyHistoryValidator; | ||
import com.gdschongik.gdsc.domain.study.dto.request.RepositoryUpdateRequest; | ||
import com.gdschongik.gdsc.domain.study.dto.response.StudyResponse; | ||
import com.gdschongik.gdsc.global.exception.CustomException; | ||
import com.gdschongik.gdsc.global.util.MemberUtil; | ||
import com.gdschongik.gdsc.infra.client.github.GithubClient; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
@@ -24,8 +28,10 @@ | |
public class StudyService { | ||
|
||
private final MemberUtil memberUtil; | ||
private final GithubClient githubClient; | ||
private final StudyRepository studyRepository; | ||
private final StudyHistoryRepository studyHistoryRepository; | ||
private final AssignmentHistoryRepository assignmentHistoryRepository; | ||
private final StudyHistoryValidator studyHistoryValidator; | ||
|
||
public List<StudyResponse> getAllApplicableStudies() { | ||
|
@@ -64,4 +70,34 @@ public void cancelStudyApply(Long studyId) { | |
|
||
log.info("[StudyService] 스터디 수강신청 취소: studyId={}, memberId={}", study.getId(), currentMember.getId()); | ||
} | ||
|
||
@Transactional | ||
public void updateRepository(Long studyId, RepositoryUpdateRequest request) { | ||
Member currentMember = memberUtil.getCurrentMember(); | ||
Study study = studyRepository.findById(studyId).orElseThrow(() -> new CustomException(STUDY_NOT_FOUND)); | ||
|
||
StudyHistory studyHistory = studyHistoryRepository | ||
.findByMenteeAndStudy(currentMember, study) | ||
.orElseThrow(() -> new CustomException(STUDY_HISTORY_NOT_FOUND)); | ||
|
||
boolean isAnyAssignmentSubmitted = | ||
assignmentHistoryRepository.existsSubmittedAssignmentByMemberAndStudy(currentMember, study); | ||
studyHistoryValidator.validateUpdateRepository(isAnyAssignmentSubmitted); | ||
validateRepositoryLink(request.repositoryLink()); | ||
|
||
studyHistory.updateRepositoryLink(request.repositoryLink()); | ||
studyHistoryRepository.save(studyHistory); | ||
|
||
log.info("[StudentStudyService] 레포지토리 입력: studyHistoryId={}", studyHistory.getId()); | ||
} | ||
|
||
private void validateRepositoryLink(String repositoryLink) { | ||
String ownerRepo = getOwnerRepo(repositoryLink); | ||
githubClient.getRepository(ownerRepo); | ||
} | ||
|
||
private String getOwnerRepo(String repositoryLink) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. REpository라고 끝까지 치는게 더 좋지 않을까용 |
||
int startIndex = repositoryLink.indexOf(GITHUB_DOMAIN) + GITHUB_DOMAIN.length(); | ||
return repositoryLink.substring(startIndex); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.gdschongik.gdsc.domain.study.dao; | ||
|
||
import com.gdschongik.gdsc.domain.member.domain.Member; | ||
import com.gdschongik.gdsc.domain.study.domain.Study; | ||
|
||
public interface AssignmentHistoryCustomRepository { | ||
|
||
boolean existsSubmittedAssignmentByMemberAndStudy(Member member, Study study); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.gdschongik.gdsc.domain.study.dao; | ||
|
||
import static com.gdschongik.gdsc.domain.study.domain.AssignmentSubmissionStatus.*; | ||
import static com.gdschongik.gdsc.domain.study.domain.QAssignmentHistory.*; | ||
|
||
import com.gdschongik.gdsc.domain.member.domain.Member; | ||
import com.gdschongik.gdsc.domain.study.domain.Study; | ||
import com.querydsl.core.types.dsl.BooleanExpression; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@RequiredArgsConstructor | ||
public class AssignmentHistoryCustomRepositoryImpl implements AssignmentHistoryCustomRepository { | ||
|
||
private final JPAQueryFactory queryFactory; | ||
|
||
@Override | ||
public boolean existsSubmittedAssignmentByMemberAndStudy(Member member, Study study) { | ||
Integer fetchOne = queryFactory | ||
.selectOne() | ||
.from(assignmentHistory) | ||
.where(eqMember(member), eqStudy(study), isSubmitted()) | ||
.fetchFirst(); | ||
|
||
return fetchOne != null; | ||
} | ||
|
||
private BooleanExpression eqMember(Member member) { | ||
return member == null ? null : assignmentHistory.member.eq(member); | ||
} | ||
|
||
private BooleanExpression eqStudy(Study study) { | ||
return study == null ? null : assignmentHistory.studyDetail.study.eq(study); | ||
} | ||
|
||
private BooleanExpression isSubmitted() { | ||
return assignmentHistory.submissionStatus.in(FAILURE, SUCCESS); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.gdschongik.gdsc.domain.study.dao; | ||
|
||
import com.gdschongik.gdsc.domain.study.domain.AssignmentHistory; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface AssignmentHistoryRepository | ||
extends JpaRepository<AssignmentHistory, Long>, AssignmentHistoryCustomRepository {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,8 @@ public class StudyHistory extends BaseEntity { | |
@JoinColumn(name = "study_id") | ||
private Study study; | ||
|
||
private String repositoryLink; | ||
|
||
@Builder(access = AccessLevel.PRIVATE) | ||
private StudyHistory(Member mentee, Study study) { | ||
this.mentee = mentee; | ||
|
@@ -43,6 +45,13 @@ public static StudyHistory create(Member mentee, Study study) { | |
return StudyHistory.builder().mentee(mentee).study(study).build(); | ||
} | ||
|
||
/** | ||
* 레포지토리 링크를 업데이트합니다. | ||
*/ | ||
public void updateRepositoryLink(String repositoryLink) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 한번 등록시 변경 불가능하도록 정책 설정하면 좋을듯 합니다 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분은 피그마에 '과제 최초 제출 시'까지 변경 가능하다고 써있더라고요. |
||
this.repositoryLink = repositoryLink; | ||
} | ||
|
||
// 데이터 전달 로직 | ||
public boolean isStudyOngoing() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이건 해당 PR건은 아니지만 올바른 책임의 메서드가 아닌 것 같네요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그렇네요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ++ todo 달아두겠습니다~ |
||
return study.isStudyOngoing(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.gdschongik.gdsc.domain.study.dto.request; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
|
||
public record RepositoryUpdateRequest(@NotBlank String repositoryLink) {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.gdschongik.gdsc.global.common.constant; | ||
|
||
public class GithubConstant { | ||
|
||
public static final String GITHUB_DOMAIN = "github.com/"; | ||
|
||
private GithubConstant() {} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이건 궁금증인데 혹시 이 플젝에서 Patch Put을 쓰는 기준이 있나요? 어떤건 PUT인거같고 어떤건 PATCH인거같아서요!
저는 이전 플젝들 할때는 PATCH로 고정해서 사용했었거든요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
테이블에 있는 필드들을 전반적으로 수정할 때는 put을 사용하고 있고요. 특정 필드만 수정할 때는 patch 사용하고 있습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저는 이것도 put이 맞는 것 같네요
patch -> 해당 endpoint가 나타내는 리소스의 일부분만 수정
put -> 해당 endpoint가 나타내는 리소스의 전체를 수정 + 덮어쓰기
그리고 레포지터리는 수강이력에서 관리되는 리소스이기 때문에 endpoint도 수정되어야 합니다