Skip to content

Commit

Permalink
v2.3.4 (#751)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sangwook02 authored Sep 4, 2024
2 parents c44c039 + 6471966 commit 00cc765
Show file tree
Hide file tree
Showing 12 changed files with 91 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"member_id", "recruitment_round_id"})})
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Membership extends BaseEntity {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ public List<StudyMentorAttendanceResponse> getAttendanceNumbers(Long studyId) {
return studyDetails.stream()
.filter(studyDetail -> studyDetail.isAttendanceDayNotPassed(LocalDate.now()))
.map(StudyMentorAttendanceResponse::from)
.limit(2)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
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;
Expand Down Expand Up @@ -56,8 +55,7 @@ public void updateRepository(Long studyId, RepositoryUpdateRequest request) thro

boolean isAnyAssignmentSubmitted =
assignmentHistoryRepository.existsSubmittedAssignmentByMemberAndStudy(currentMember, study);
String ownerRepo = getOwnerRepo(request.repositoryLink());
GHRepository repository = githubClient.getRepository(ownerRepo);
GHRepository repository = githubClient.getRepository(request.repositoryLink());
// TODO: GHRepository 등을 wrapper로 감싸서 테스트 가능하도록 변경
studyHistoryValidator.validateUpdateRepository(
isAnyAssignmentSubmitted, String.valueOf(repository.getOwner().getId()), currentMember.getOauthId());
Expand All @@ -71,11 +69,6 @@ public void updateRepository(Long studyId, RepositoryUpdateRequest request) thro
request.repositoryLink());
}

private String getOwnerRepo(String repositoryLink) {
int startIndex = repositoryLink.indexOf(GITHUB_DOMAIN) + GITHUB_DOMAIN.length();
return repositoryLink.substring(startIndex);
}

@Transactional(readOnly = true)
public List<AssignmentHistoryResponse> getAllAssignmentHistories(Long studyId) {
Member currentMember = memberUtil.getCurrentMember();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,14 @@ public void attend(Long studyDetailId, StudyAttendCreateRequest request) {
.orElseThrow(() -> new CustomException(STUDY_DETAIL_NOT_FOUND));
final Member currentMember = memberUtil.getCurrentMember();
final Study study = studyDetail.getStudy();
final boolean isAlreadyAttended =
attendanceRepository.existsByStudentIdAndStudyDetailId(currentMember.getId(), studyDetailId);
final StudyHistory studyHistory = studyHistoryRepository
.findByStudentAndStudy(currentMember, study)
.orElseThrow(() -> new CustomException(STUDY_HISTORY_NOT_FOUND));

attendanceValidator.validateAttendance(studyDetail, request.attendanceNumber(), LocalDate.now());
attendanceValidator.validateAttendance(
studyDetail, request.attendanceNumber(), LocalDate.now(), isAlreadyAttended);

Attendance attendance = Attendance.create(currentMember, studyDetail);
attendanceRepository.save(attendance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
import com.gdschongik.gdsc.domain.study.domain.Attendance;
import org.springframework.data.jpa.repository.JpaRepository;

public interface AttendanceRepository extends JpaRepository<Attendance, Long>, AttendanceCustomRepository {}
public interface AttendanceRepository extends JpaRepository<Attendance, Long>, AttendanceCustomRepository {
boolean existsByStudentIdAndStudyDetailId(Long studentId, Long studyDetailId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

@DomainService
public class AttendanceValidator {
public void validateAttendance(StudyDetail studyDetail, String attendanceNumber, LocalDate date) {
public void validateAttendance(
StudyDetail studyDetail, String attendanceNumber, LocalDate date, boolean isAlreadyAttended) {
// 출석체크 날짜 검증
LocalDate attendanceDay = studyDetail.getAttendanceDay();
if (!attendanceDay.equals(date)) {
Expand All @@ -19,5 +20,10 @@ public void validateAttendance(StudyDetail studyDetail, String attendanceNumber,
if (!studyDetail.getAttendanceNumber().equals(attendanceNumber)) {
throw new CustomException(ATTENDANCE_NUMBER_MISMATCH);
}

// 출석체크 번호 검증
if (isAlreadyAttended) {
throw new CustomException(STUDY_DETAIL_ALREADY_ATTENDED);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.gdschongik.gdsc.domain.study.dto.request;

import com.gdschongik.gdsc.global.common.constant.RegexConstant;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;

public record RepositoryUpdateRequest(@NotBlank String repositoryLink) {}
public record RepositoryUpdateRequest(
@NotBlank @Pattern(regexp = RegexConstant.GITHUB_REPOSITORY) String repositoryLink) {}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class RegexConstant {
public static final String ZONED_DATETIME = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
public static final String DATE = "yyyy-MM-dd";
public static final String ACADEMIC_YEAR = "^[0-9]{4}$";
public static final String GITHUB_REPOSITORY =
"^https:\\/\\/github\\.com\\/[A-Za-z0-9]+(-[A-Za-z0-9]+)*\\/[A-Za-z0-9._-]+$";

public static final String ATTENDANCE_NUMBER = "^[0-9]{4}$";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ public enum ErrorCode {
// Attendance
ATTENDANCE_DATE_INVALID(HttpStatus.CONFLICT, "강의일이 아니면 출석체크할 수 없습니다."),
ATTENDANCE_NUMBER_MISMATCH(HttpStatus.CONFLICT, "출석번호가 일치하지 않습니다."),
STUDY_DETAIL_ALREADY_ATTENDED(HttpStatus.CONFLICT, "이미 출석 처리된 스터디입니다."),

// Order
ORDER_NOT_FOUND(HttpStatus.NOT_FOUND, "주문이 존재하지 않습니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ public class GithubClient {
private final GitHub github;
private final GitHubConnector gitHubConnector = GitHubConnector.DEFAULT;

public GHRepository getRepository(String ownerRepo) {
public GHRepository getRepository(String repo) {
try {
String ownerRepo = getOwnerRepo(repo);
return github.getRepository(ownerRepo);
} catch (IOException e) {
throw new CustomException(GITHUB_REPOSITORY_NOT_FOUND);
Expand Down Expand Up @@ -107,4 +108,9 @@ private LocalDateTime getCommitDate(GHCommit ghLatestCommit) {
throw new CustomException(GITHUB_COMMIT_DATE_FETCH_FAILED);
}
}

private String getOwnerRepo(String repositoryLink) {
int startIndex = repositoryLink.indexOf(GITHUB_DOMAIN) + GITHUB_DOMAIN.length();
return repositoryLink.substring(startIndex);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@

import static com.gdschongik.gdsc.domain.common.model.RequirementStatus.SATISFIED;
import static com.gdschongik.gdsc.domain.member.domain.MemberRole.ASSOCIATE;
import static com.gdschongik.gdsc.global.common.constant.RecruitmentConstant.*;
import static com.gdschongik.gdsc.global.exception.ErrorCode.*;
import static org.assertj.core.api.Assertions.*;

import com.gdschongik.gdsc.domain.common.vo.Money;
import com.gdschongik.gdsc.domain.member.domain.Member;
import com.gdschongik.gdsc.domain.membership.dao.MembershipRepository;
import com.gdschongik.gdsc.domain.membership.domain.Membership;
import com.gdschongik.gdsc.domain.recruitment.domain.RecruitmentRound;
import com.gdschongik.gdsc.domain.recruitment.domain.RoundType;
import com.gdschongik.gdsc.global.exception.CustomException;
import com.gdschongik.gdsc.helper.IntegrationTest;
import java.time.LocalDateTime;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -38,7 +42,36 @@ class 멤버십_가입신청시 {
.hasMessage(RECRUITMENT_ROUND_NOT_FOUND.getMessage());
}

// todo: 1차 모집시 멤버십 생성 후 실제 가입은 하지 않고 2차 모집 시 가입하려고 하는 케이스 추가
@Test
void 멤버십을_1차모집시_생성했지만_정회원_가입조건을_만족하지_않았다면_2차모집에서_멤버십_가입신청에_성공한다() {
// given
createMember();
logoutAndReloginAs(1L, ASSOCIATE);

RecruitmentRound firstRound = createRecruitmentRound(
RECRUITMENT_ROUND_NAME,
LocalDateTime.now().minusDays(5),
LocalDateTime.now().plusDays(1),
ACADEMIC_YEAR,
SEMESTER_TYPE,
ROUND_TYPE,
Money.from(20000L));

RecruitmentRound secondRound = createRecruitmentRound(
RECRUITMENT_ROUND_NAME,
LocalDateTime.now().minusDays(1),
LocalDateTime.now().plusDays(1),
ACADEMIC_YEAR,
SEMESTER_TYPE,
RoundType.SECOND,
Money.from(20000L));

// when & then
membershipService.submitMembership(firstRound.getId());

assertThatCode(() -> membershipService.submitMembership(secondRound.getId()))
.doesNotThrowAnyException();
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static com.gdschongik.gdsc.global.common.constant.StudyConstant.ATTENDANCE_NUMBER;
import static com.gdschongik.gdsc.global.exception.ErrorCode.ATTENDANCE_DATE_INVALID;
import static com.gdschongik.gdsc.global.exception.ErrorCode.ATTENDANCE_NUMBER_MISMATCH;
import static com.gdschongik.gdsc.global.exception.ErrorCode.STUDY_DETAIL_ALREADY_ATTENDED;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import com.gdschongik.gdsc.domain.member.domain.Member;
Expand Down Expand Up @@ -36,7 +37,7 @@ class 스터디_출석체크시 {

// when & then
assertThatThrownBy(() -> attendanceValidator.validateAttendance(
studyDetail, ATTENDANCE_NUMBER, attendanceDay.plusDays(1)))
studyDetail, ATTENDANCE_NUMBER, attendanceDay.plusDays(1), false))
.isInstanceOf(CustomException.class)
.hasMessage(ATTENDANCE_DATE_INVALID.getMessage());
}
Expand All @@ -55,10 +56,30 @@ class 스터디_출석체크시 {
LocalDate attendanceDay = studyDetail.getAttendanceDay();

// when & then
assertThatThrownBy(() ->
attendanceValidator.validateAttendance(studyDetail, ATTENDANCE_NUMBER + 1, attendanceDay))
assertThatThrownBy(() -> attendanceValidator.validateAttendance(
studyDetail, ATTENDANCE_NUMBER + 1, attendanceDay, false))
.isInstanceOf(CustomException.class)
.hasMessage(ATTENDANCE_NUMBER_MISMATCH.getMessage());
}

@Test
void 이미_출석했다면_실패한다() {
// given
Member mentor = fixtureHelper.createAssociateMember(1L);

LocalDateTime now = LocalDateTime.now();
Period period = Period.createPeriod(now.plusDays(10), now.plusDays(65));
Period applicationPeriod = Period.createPeriod(now.minusDays(10), now.plusDays(5));
Study study = fixtureHelper.createStudy(mentor, period, applicationPeriod);
StudyDetail studyDetail = fixtureHelper.createStudyDetail(study, now, now.plusDays(7));

LocalDate attendanceDay = studyDetail.getAttendanceDay();

// when & then
assertThatThrownBy(() ->
attendanceValidator.validateAttendance(studyDetail, ATTENDANCE_NUMBER, attendanceDay, true))
.isInstanceOf(CustomException.class)
.hasMessage(STUDY_DETAIL_ALREADY_ATTENDED.getMessage());
}
}
}

0 comments on commit 00cc765

Please sign in to comment.