diff --git a/backend/src/main/java/com/yigongil/backend/domain/member/Member.java b/backend/src/main/java/com/yigongil/backend/domain/member/Member.java index 1f428c232..01c29f85b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/member/Member.java +++ b/backend/src/main/java/com/yigongil/backend/domain/member/Member.java @@ -17,6 +17,7 @@ public class Member extends BaseEntity { private static final int MASTER_NUMBER = 0; private static final int PARTICIPANT_NUMBER = 1; + private static final int MAXIMUM_TIER = 5; @GeneratedValue(strategy = GenerationType.IDENTITY) @Id @@ -79,6 +80,12 @@ public String getIntroduction() { return introduction.getIntroduction(); } + public void upgradeTier() { + if (tier < MAXIMUM_TIER) { + tier++; + } + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java index bdb4066cd..112b1161b 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/round/Round.java +++ b/backend/src/main/java/com/yigongil/backend/domain/round/Round.java @@ -175,7 +175,7 @@ public void updateNecessaryTodoContent(Member member, String content) { public boolean isEndAt(LocalDate today) { LocalDate endAtDate = endAt.toLocalDate(); - return endAtDate.equals(today); + return endAtDate.isBefore(today) || endAtDate.equals(today); } public void updateEndAt(LocalDateTime endAt) { @@ -203,6 +203,12 @@ public RoundOfMember findRoundOfMemberBy(Member member) { ); } + public void updateMembersTier() { + for (RoundOfMember roundOfMember : roundOfMembers) { + roundOfMember.updateMemberTier(); + } + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java b/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java index c5f3ab779..af491f9d0 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java +++ b/backend/src/main/java/com/yigongil/backend/domain/roundofmember/RoundOfMember.java @@ -94,4 +94,8 @@ private OptionalTodo findOptionalTodoById(Long todoId) { public boolean isMemberEquals(Member member) { return this.member.equals(member); } + + public void updateMemberTier() { + member.upgradeTier(); + } } diff --git a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java index fd36aa984..2e72aef57 100644 --- a/backend/src/main/java/com/yigongil/backend/domain/study/Study.java +++ b/backend/src/main/java/com/yigongil/backend/domain/study/Study.java @@ -10,7 +10,6 @@ import com.yigongil.backend.exception.InvalidNumberOfMaximumStudyMember; import com.yigongil.backend.exception.InvalidProcessingStatusException; import com.yigongil.backend.exception.InvalidStudyNameLengthException; -import com.yigongil.backend.exception.RoundNotFoundException; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; @@ -171,15 +170,6 @@ public Integer calculateAverageTier() { return currentRound.calculateAverageTier(); } - public Round findRoundById(Long roundId) { - return rounds.stream() - .filter(round -> round.getId().equals(roundId)) - .findAny() - .orElseThrow( - () -> new RoundNotFoundException("스터디에 해당 회차가 존재하지 않습니다.", roundId) - ); - } - public void addMember(Member member) { validateStudyProcessingStatus(); validateMemberSize(); @@ -231,6 +221,7 @@ private void updateCurrentRound(Round upcomingRound) { private void finishStudy() { this.processingStatus = ProcessingStatus.END; + currentRound.updateMembersTier(); } public void startStudy() { diff --git a/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java b/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java index 276375296..ccc1658dd 100644 --- a/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java +++ b/backend/src/test/java/com/yigongil/backend/domain/study/StudyTest.java @@ -6,11 +6,13 @@ import com.yigongil.backend.domain.member.Member; import com.yigongil.backend.domain.round.Round; +import com.yigongil.backend.domain.roundofmember.RoundOfMember; import com.yigongil.backend.exception.InvalidMemberSizeException; import com.yigongil.backend.exception.InvalidProcessingStatusException; import com.yigongil.backend.fixture.MemberFixture; import com.yigongil.backend.fixture.StudyFixture; import java.time.LocalDateTime; +import java.util.List; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.Test; @@ -55,6 +57,33 @@ class StudyTest { assertThat(study.getProcessingStatus()).isSameAs(ProcessingStatus.END); } + @Test + void 스터디를_성공적으로_완수하면_티어가_증가한다() { + // given + Study study = StudyFixture.자바_스터디_모집중.toStudy(); + study.updateToNextRound(); + study.updateToNextRound(); + List expected = study.getCurrentRound() + .getRoundOfMembers() + .stream() + .map(RoundOfMember::getMember) + .map(Member::getTier) + .map(tier -> tier < 5 ? tier + 1 : tier) + .toList(); + + // when + study.updateToNextRound(); + List actual = study.getCurrentRound() + .getRoundOfMembers() + .stream() + .map(RoundOfMember::getMember) + .map(Member::getTier) + .toList(); + + // then + assertThat(actual).isEqualTo(expected); + } + @Test void 스터디의_현재_라운드가_종료되는_날이면_true를_반환한다() { // given @@ -63,10 +92,14 @@ class StudyTest { LocalDateTime endAt = currentRound.getEndAt(); // when - boolean actual = study.isCurrentRoundEndAt(endAt.toLocalDate()); + boolean actual1 = study.isCurrentRoundEndAt(endAt.toLocalDate()); + boolean actual2 = study.isCurrentRoundEndAt(endAt.plusDays(1).toLocalDate()); // then - assertThat(actual).isTrue(); + assertAll( + () -> assertThat(actual1).isTrue(), + () -> assertThat(actual2).isTrue() + ); } @Test @@ -77,7 +110,7 @@ class StudyTest { LocalDateTime endAt = currentRound.getEndAt(); // when - boolean actual = study.isCurrentRoundEndAt(endAt.plusDays(1).toLocalDate()); + boolean actual = study.isCurrentRoundEndAt(endAt.minusDays(1).toLocalDate()); // then assertThat(actual).isFalse(); @@ -114,12 +147,9 @@ class StudyTest { void 정원이_가득_찬_스터디에_Member를_추가하면_예외가_발생한다() { // given Study study = StudyFixture.자바_스터디_모집중_정원_2.toStudy(); - Member member1 = MemberFixture.폰노이만.toMember(); Member member2 = MemberFixture.마틴파울러.toMember(); // when - study.addMember(member1); - // then assertThatThrownBy(() -> study.addMember(member2)) .isInstanceOf(InvalidMemberSizeException.class); diff --git a/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java b/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java index e5368f584..fb01c071b 100644 --- a/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java +++ b/backend/src/test/java/com/yigongil/backend/fixture/RoundFixture.java @@ -39,7 +39,7 @@ public Round toRound() { .roundNumber(roundNumber) .master(master) .endAt(LocalDateTime.now()) - .roundOfMembers(new ArrayList<>(List.of(RoundOfMemberFixture.김진우_라운드_삼.toRoundOfMember()))) + .roundOfMembers(new ArrayList<>(List.of(RoundOfMemberFixture.김진우_라운드_삼.toRoundOfMember(), RoundOfMemberFixture.노이만_라오멤.toRoundOfMember()))) .build(); } diff --git a/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java b/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java index 38c00b07f..c44b5bda4 100644 --- a/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java +++ b/backend/src/test/java/com/yigongil/backend/fixture/RoundOfMemberFixture.java @@ -6,6 +6,7 @@ public enum RoundOfMemberFixture { 김진우_라운드_삼(1L, MemberFixture.김진우.toMember(), false), + 노이만_라오멤(1L, MemberFixture.폰노이만.toMember(), false), ; private final Long id;