Skip to content

Commit 5dacd55

Browse files
authored
v2.3.2 (#730)
2 parents a3ad36d + b2f41b5 commit 5dacd55

15 files changed

+55
-39
lines changed

src/main/java/com/gdschongik/gdsc/domain/membership/application/MembershipService.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ public void submitMembership(Long recruitmentRoundId) {
6969
.findById(recruitmentRoundId)
7070
.orElseThrow(() -> new CustomException(RECRUITMENT_ROUND_NOT_FOUND));
7171

72-
boolean isMembershipAlreadySubmitted =
73-
membershipRepository.existsByMemberAndRecruitment(currentMember, recruitmentRound.getRecruitment());
72+
boolean isMembershipDuplicate = membershipRepository.existsByMemberAndRecruitmentWithSatisfiedRequirements(
73+
currentMember, recruitmentRound.getRecruitment());
7474

75-
membershipValidator.validateMembershipSubmit(currentMember, recruitmentRound, isMembershipAlreadySubmitted);
75+
membershipValidator.validateMembershipSubmit(currentMember, recruitmentRound, isMembershipDuplicate);
7676

7777
Membership membership = Membership.createMembership(currentMember, recruitmentRound);
7878
membershipRepository.save(membership);

src/main/java/com/gdschongik/gdsc/domain/membership/dao/MembershipCustomRepository.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55

66
public interface MembershipCustomRepository {
77

8-
boolean existsByMemberAndRecruitment(Member member, Recruitment recruitment);
8+
boolean existsByMemberAndRecruitmentWithSatisfiedRequirements(Member member, Recruitment recruitment);
99
}

src/main/java/com/gdschongik/gdsc/domain/membership/dao/MembershipCustomRepositoryImpl.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
import static com.gdschongik.gdsc.domain.membership.domain.QMembership.*;
44

5+
import com.gdschongik.gdsc.domain.common.model.RequirementStatus;
56
import com.gdschongik.gdsc.domain.member.domain.Member;
67
import com.gdschongik.gdsc.domain.recruitment.domain.Recruitment;
78
import com.querydsl.core.types.dsl.BooleanExpression;
9+
import com.querydsl.core.types.dsl.EnumPath;
810
import com.querydsl.jpa.impl.JPAQueryFactory;
911
import lombok.RequiredArgsConstructor;
1012

@@ -14,11 +16,14 @@ public class MembershipCustomRepositoryImpl implements MembershipCustomRepositor
1416
private final JPAQueryFactory queryFactory;
1517

1618
@Override
17-
public boolean existsByMemberAndRecruitment(Member member, Recruitment recruitment) {
19+
public boolean existsByMemberAndRecruitmentWithSatisfiedRequirements(Member member, Recruitment recruitment) {
1820
Integer fetchOne = queryFactory
1921
.selectOne()
2022
.from(membership)
21-
.where(eqMember(member), eqRecruitment(recruitment))
23+
.where(
24+
eqMember(member),
25+
eqRecruitment(recruitment),
26+
eqRequirementStatus(membership.regularRequirement.paymentStatus, RequirementStatus.SATISFIED))
2227
.fetchFirst();
2328

2429
return fetchOne != null;
@@ -31,4 +36,9 @@ private BooleanExpression eqMember(Member member) {
3136
private BooleanExpression eqRecruitment(Recruitment recruitment) {
3237
return recruitment != null ? membership.recruitmentRound.recruitment.eq(recruitment) : null;
3338
}
39+
40+
private BooleanExpression eqRequirementStatus(
41+
EnumPath<RequirementStatus> requirement, RequirementStatus requirementStatus) {
42+
return requirementStatus != null ? requirement.eq(requirementStatus) : null;
43+
}
3444
}

src/main/java/com/gdschongik/gdsc/domain/membership/domain/MembershipValidator.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@
1313
public class MembershipValidator {
1414

1515
public void validateMembershipSubmit(
16-
Member currentMember, RecruitmentRound recruitmentRound, boolean isMembershipAlreadySubmitted) {
16+
Member currentMember, RecruitmentRound recruitmentRound, boolean isMembershipDuplicate) {
1717
// 준회원인지 검증
1818
// TODO: 어드민인 경우 리쿠르팅 지원 및 결제에 대한 정책 검토 필요. 현재는 불가능하도록 설정
1919
if (!currentMember.isAssociate()) {
2020
throw new CustomException(MEMBERSHIP_NOT_APPLICABLE);
2121
}
2222

23-
// 이미 접수한 멤버십이 있는지 검증
24-
if (isMembershipAlreadySubmitted) {
23+
// 이미 멤버십이 있는지 검증
24+
if (isMembershipDuplicate) {
2525
throw new CustomException(MEMBERSHIP_ALREADY_SUBMITTED);
2626
}
2727

src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyDetailController.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,18 @@ public class MentorStudyDetailController {
3030

3131
@Operation(summary = "스터디 과제 수정", description = "멘토만 과제를 수정할 수 있습니다.")
3232
@PatchMapping("/{studyDetailId}/assignments")
33-
public ResponseEntity<Void> updateStudyAssignment(
33+
public ResponseEntity<AssignmentResponse> updateStudyAssignment(
3434
@PathVariable Long studyDetailId, @Valid @RequestBody AssignmentCreateUpdateRequest request) {
35-
mentorStudyDetailService.updateStudyAssignment(studyDetailId, request);
36-
return ResponseEntity.ok().build();
35+
AssignmentResponse response = mentorStudyDetailService.updateStudyAssignment(studyDetailId, request);
36+
return ResponseEntity.ok().body(response);
3737
}
3838

3939
@Operation(summary = "스터디 과제 개설", description = "멘토만 과제를 개설할 수 있습니다.")
4040
@PutMapping("/{studyDetailId}/assignments")
41-
public ResponseEntity<Void> publishStudyAssignment(
41+
public ResponseEntity<AssignmentResponse> publishStudyAssignment(
4242
@PathVariable Long studyDetailId, @Valid @RequestBody AssignmentCreateUpdateRequest request) {
43-
mentorStudyDetailService.publishStudyAssignment(studyDetailId, request);
44-
return ResponseEntity.ok().build();
43+
AssignmentResponse response = mentorStudyDetailService.publishStudyAssignment(studyDetailId, request);
44+
return ResponseEntity.ok().body(response);
4545
}
4646

4747
@Operation(summary = "스터디 주차별 과제 목록 조회", description = "주차별 스터디 과제 목록을 조회합니다.")

src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyDetailService.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public void cancelStudyAssignment(Long studyDetailId) {
5858
}
5959

6060
@Transactional
61-
public void publishStudyAssignment(Long studyDetailId, AssignmentCreateUpdateRequest request) {
61+
public AssignmentResponse publishStudyAssignment(Long studyDetailId, AssignmentCreateUpdateRequest request) {
6262
Member currentMember = memberUtil.getCurrentMember();
6363
StudyDetail studyDetail = studyDetailRepository
6464
.findById(studyDetailId)
@@ -67,13 +67,15 @@ public void publishStudyAssignment(Long studyDetailId, AssignmentCreateUpdateReq
6767
studyDetailValidator.validatePublishStudyAssignment(currentMember, studyDetail, request);
6868

6969
studyDetail.publishAssignment(request.title(), request.deadLine(), request.descriptionNotionLink());
70-
studyDetailRepository.save(studyDetail);
70+
StudyDetail savedStudyDetail = studyDetailRepository.save(studyDetail);
7171

7272
log.info("[MentorStudyDetailService] 과제 개설 완료: studyDetailId={}", studyDetailId);
73+
74+
return AssignmentResponse.from(savedStudyDetail);
7375
}
7476

7577
@Transactional
76-
public void updateStudyAssignment(Long studyDetailId, AssignmentCreateUpdateRequest request) {
78+
public AssignmentResponse updateStudyAssignment(Long studyDetailId, AssignmentCreateUpdateRequest request) {
7779
Member currentMember = memberUtil.getCurrentMember();
7880
StudyDetail studyDetail = studyDetailRepository
7981
.findById(studyDetailId)
@@ -82,9 +84,11 @@ public void updateStudyAssignment(Long studyDetailId, AssignmentCreateUpdateRequ
8284
studyDetailValidator.validateUpdateStudyAssignment(currentMember, studyDetail, request);
8385

8486
studyDetail.updateAssignment(request.title(), request.deadLine(), request.descriptionNotionLink());
85-
studyDetailRepository.save(studyDetail);
87+
StudyDetail savedStudyDetail = studyDetailRepository.save(studyDetail);
8688

8789
log.info("[MentorStudyDetailService] 과제 수정 완료: studyDetailId={}", studyDetailId);
90+
91+
return AssignmentResponse.from(savedStudyDetail);
8892
}
8993

9094
@Transactional(readOnly = true)

src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyService.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import com.gdschongik.gdsc.global.exception.CustomException;
1818
import com.gdschongik.gdsc.global.util.MemberUtil;
1919
import java.time.LocalDate;
20-
import java.time.LocalDateTime;
2120
import java.util.List;
2221
import java.util.Optional;
2322
import lombok.RequiredArgsConstructor;
@@ -43,8 +42,8 @@ public StudyApplicableResponse getAllApplicableStudies() {
4342
Member currentMember = memberUtil.getCurrentMember();
4443
List<StudyHistory> studyHistories = studyHistoryRepository.findAllByStudent(currentMember);
4544
Optional<Study> appliedStudy = studyHistories.stream()
45+
.filter(StudyHistory::isWithinApplicationAndCourse)
4646
.map(StudyHistory::getStudy)
47-
.filter(Study::isStudyOngoing)
4847
.findFirst();
4948
List<StudyResponse> studyResponses = studyRepository.findAll().stream()
5049
.filter(Study::isApplicable)
@@ -107,8 +106,7 @@ public void attend(Long studyDetailId, StudyAttendCreateRequest request) {
107106
public StudentMyCurrentStudyResponse getMyCurrentStudy() {
108107
Member currentMember = memberUtil.getCurrentMember();
109108
StudyHistory studyHistory = studyHistoryRepository.findAllByStudent(currentMember).stream()
110-
.filter(s -> s.getStudy().getApplicationPeriod().getStartDate().isBefore(LocalDateTime.now())
111-
&& s.getStudy().getPeriod().getEndDate().isAfter(LocalDateTime.now()))
109+
.filter(StudyHistory::isWithinApplicationAndCourse)
112110
.findFirst()
113111
.orElse(null);
114112
return StudentMyCurrentStudyResponse.from(studyHistory);

src/main/java/com/gdschongik/gdsc/domain/study/domain/Study.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,10 @@ public boolean isApplicable() {
175175
return applicationPeriod.isOpen();
176176
}
177177

178-
public boolean isStudyOngoing() {
179-
return period.isOpen();
178+
public boolean isWithinApplicationAndCourse() {
179+
LocalDateTime now = LocalDateTime.now();
180+
return applicationPeriod.getStartDate().isBefore(now)
181+
&& period.getEndDate().isAfter(now);
180182
}
181183

182184
public LocalDate getStartDate() {

src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyHistory.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public void updateRepositoryLink(String repositoryLink) {
5656
}
5757

5858
// 데이터 전달 로직
59-
public boolean isStudyOngoing() {
60-
return study.isStudyOngoing();
59+
public boolean isWithinApplicationAndCourse() {
60+
return study.isWithinApplicationAndCourse();
6161
}
6262
}

src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyHistoryValidator.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ public void validateApplyStudy(Study study, List<StudyHistory> currentMemberStud
2424
}
2525

2626
// 이미 듣고 있는 스터디가 있는 경우
27-
// todo: StudyHistory가 아닌 Study의 isOngoning 호출하도록 수정
28-
boolean isInOngoingStudy = currentMemberStudyHistories.stream().anyMatch(StudyHistory::isStudyOngoing);
27+
boolean hasAppliedStudy =
28+
currentMemberStudyHistories.stream().anyMatch(StudyHistory::isWithinApplicationAndCourse);
2929

30-
if (isInOngoingStudy) {
30+
if (hasAppliedStudy) {
3131
throw new CustomException(STUDY_HISTORY_ONGOING_ALREADY_EXISTS);
3232
}
3333
}

src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyType.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
@AllArgsConstructor
88
public enum StudyType {
99
ASSIGNMENT("과제 스터디"),
10-
ONLINE("온라인 커리큘럼"),
11-
OFFLINE("오프라인 커리큘럼");
10+
ONLINE("온라인 스터디"),
11+
OFFLINE("오프라인 스터디");
1212

1313
private final String value;
1414
}

src/main/java/com/gdschongik/gdsc/domain/study/dto/response/AssignmentHistoryStatusResponse.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.gdschongik.gdsc.domain.study.dto.response;
22

3-
import static com.gdschongik.gdsc.domain.study.domain.SubmissionFailureType.NOT_SUBMITTED;
4-
53
import com.gdschongik.gdsc.domain.study.domain.*;
64
import com.gdschongik.gdsc.domain.study.domain.vo.Assignment;
75
import io.swagger.v3.oas.annotations.media.Schema;
@@ -34,7 +32,7 @@ public static AssignmentHistoryStatusResponse of(StudyDetail studyDetail, Assign
3432
studyDetail.getAssignment().getDescriptionLink(),
3533
studyDetail.getAssignment().getDeadline(),
3634
null,
37-
NOT_SUBMITTED,
35+
null,
3836
null);
3937
}
4038

src/main/java/com/gdschongik/gdsc/domain/study/dto/response/AssignmentResponse.java

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
public record AssignmentResponse(
1010
Long studyDetailId,
11+
@Schema(description = "스터디 이름") String studyTitle,
1112
@Schema(description = "과제 제목") String title,
1213
@Schema(description = "마감 기한") LocalDateTime deadline,
1314
@Schema(description = "주차") Long week,
@@ -17,6 +18,7 @@ public static AssignmentResponse from(StudyDetail studyDetail) {
1718
Assignment assignment = studyDetail.getAssignment();
1819
return new AssignmentResponse(
1920
studyDetail.getId(),
21+
studyDetail.getStudy().getTitle(),
2022
assignment.getTitle(),
2123
assignment.getDeadline(),
2224
studyDetail.getWeek(),

src/main/java/com/gdschongik/gdsc/domain/study/dto/response/AssignmentSubmittableDto.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public static AssignmentSubmittableDto of(StudyDetail studyDetail, AssignmentHis
2828
}
2929

3030
if (assignmentHistory == null) {
31-
return notSubmittedAssignment(studyDetail, assignment);
31+
return beforeAssignmentSubmit(studyDetail, assignment);
3232
}
3333

3434
return new AssignmentSubmittableDto(
@@ -48,16 +48,16 @@ private static AssignmentSubmittableDto cancelledAssignment(StudyDetail studyDet
4848
studyDetail.getId(), assignment.getStatus(), studyDetail.getWeek(), null, null, null, null, null, null);
4949
}
5050

51-
private static AssignmentSubmittableDto notSubmittedAssignment(StudyDetail studyDetail, Assignment assignment) {
51+
private static AssignmentSubmittableDto beforeAssignmentSubmit(StudyDetail studyDetail, Assignment assignment) {
5252
return new AssignmentSubmittableDto(
5353
studyDetail.getId(),
5454
assignment.getStatus(),
5555
studyDetail.getWeek(),
5656
assignment.getTitle(),
57-
AssignmentSubmissionStatus.FAILURE,
57+
null,
5858
assignment.getDescriptionLink(),
5959
assignment.getDeadline(),
6060
null,
61-
SubmissionFailureType.NOT_SUBMITTED);
61+
null);
6262
}
6363
}

src/test/java/com/gdschongik/gdsc/domain/membership/application/MembershipServiceTest.java

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class 멤버십_가입신청시 {
3737
.isInstanceOf(CustomException.class)
3838
.hasMessage(RECRUITMENT_ROUND_NOT_FOUND.getMessage());
3939
}
40+
41+
// todo: 1차 모집시 멤버십 생성 후 실제 가입은 하지 않고 2차 모집 시 가입하려고 하는 케이스 추가
4042
}
4143

4244
@Test

0 commit comments

Comments
 (0)