Skip to content

Commit

Permalink
v2.3.5 (#769)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sangwook02 authored Sep 5, 2024
2 parents 00cc765 + e9e4c62 commit 89856b2
Show file tree
Hide file tree
Showing 20 changed files with 107 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.gdschongik.gdsc.domain.study.application.MentorStudyService;
import com.gdschongik.gdsc.domain.study.dto.request.StudyAnnouncementCreateUpdateRequest;
import com.gdschongik.gdsc.domain.study.dto.request.StudyUpdateRequest;
import com.gdschongik.gdsc.domain.study.dto.response.MentorStudyResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyStudentResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
Expand All @@ -30,8 +30,8 @@ public ResponseEntity<Void> updateStudy(@PathVariable Long studyId, @RequestBody

@Operation(summary = "내 스터디 조회", description = "내가 멘토로 있는 스터디를 조회합니다.")
@GetMapping("/me")
public ResponseEntity<List<MentorStudyResponse>> getStudiesInCharge() {
List<MentorStudyResponse> response = mentorStudyService.getStudiesInCharge();
public ResponseEntity<List<StudyResponse>> getStudiesInCharge() {
List<StudyResponse> response = mentorStudyService.getStudiesInCharge();
return ResponseEntity.ok(response);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public ResponseEntity<List<StudyStudentCurriculumResponse>> getStudyCurriculums(
return ResponseEntity.ok(response);
}

@Deprecated
@Operation(summary = "이번주 제출해야 할 과제 조회", description = "마감 기한이 이번주까지인 과제를 조회합니다.")
@GetMapping("/assignments/upcoming")
public ResponseEntity<List<AssignmentHistoryStatusResponse>> getUpcomingAssignments(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
package com.gdschongik.gdsc.domain.study.application;

import static com.gdschongik.gdsc.global.exception.ErrorCode.STUDY_NOT_FOUND;
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.AttendanceRepository;
import com.gdschongik.gdsc.domain.study.dao.StudyAnnouncementRepository;
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.StudyAnnouncement;
import com.gdschongik.gdsc.domain.study.domain.StudyHistory;
import com.gdschongik.gdsc.domain.study.domain.StudyValidator;
import com.gdschongik.gdsc.domain.study.dto.response.CommonStudyResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyAnnouncementResponse;
import com.gdschongik.gdsc.global.exception.CustomException;
import com.gdschongik.gdsc.global.util.MemberUtil;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
Expand All @@ -29,6 +28,8 @@ public class CommonStudyService {
private final StudyRepository studyRepository;
private final StudyHistoryRepository studyHistoryRepository;
private final StudyAnnouncementRepository studyAnnouncementRepository;
private final AttendanceRepository attendanceRepository;
private final AssignmentHistoryRepository assignmentHistoryRepository;
private final MemberUtil memberUtil;
private final StudyValidator studyValidator;

Expand All @@ -40,15 +41,23 @@ public CommonStudyResponse getStudyInformation(Long studyId) {

@Transactional(readOnly = true)
public List<StudyAnnouncementResponse> getStudyAnnouncements(Long studyId) {
Member currentMember = memberUtil.getCurrentMember();
final Study study = studyRepository.findById(studyId).orElseThrow(() -> new CustomException(STUDY_NOT_FOUND));
Optional<StudyHistory> studyHistory = studyHistoryRepository.findByStudentAndStudyId(currentMember, studyId);

studyValidator.validateStudyMentorOrStudent(currentMember, study, studyHistory);

final List<StudyAnnouncement> studyAnnouncements =
studyAnnouncementRepository.findAllByStudyIdOrderByCreatedAtDesc(studyId);

return studyAnnouncements.stream().map(StudyAnnouncementResponse::from).toList();
}

/**
* 이벤트 핸들러에서 사용되므로, `@Transactional` 을 사용하지 않습니다.
*/
public void deleteAttendance(Long studyId, Long memberId) {
attendanceRepository.deleteByStudyIdAndMemberId(studyId, memberId);
}

/**
* 이벤트 핸들러에서 사용되므로, `@Transactional` 을 사용하지 않습니다.
*/
public void deleteAssignmentHistory(Long studyId, Long memberId) {
assignmentHistoryRepository.deleteByStudyIdAndMemberId(studyId, memberId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import com.gdschongik.gdsc.domain.study.dto.request.StudyAnnouncementCreateUpdateRequest;
import com.gdschongik.gdsc.domain.study.dto.request.StudyCurriculumCreateRequest;
import com.gdschongik.gdsc.domain.study.dto.request.StudyUpdateRequest;
import com.gdschongik.gdsc.domain.study.dto.response.MentorStudyResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyStudentResponse;
import com.gdschongik.gdsc.global.exception.CustomException;
import com.gdschongik.gdsc.global.exception.ErrorCode;
Expand All @@ -42,10 +42,10 @@ public class MentorStudyService {
private final StudyDetailValidator studyDetailValidator;

@Transactional(readOnly = true)
public List<MentorStudyResponse> getStudiesInCharge() {
public List<StudyResponse> getStudiesInCharge() {
Member currentMember = memberUtil.getCurrentMember();
List<Study> myStudies = studyRepository.findAllByMentor(currentMember);
return myStudies.stream().map(MentorStudyResponse::from).toList();
return myStudies.stream().map(StudyResponse::from).toList();
}

@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public void applyStudy(Long studyId) {

@Transactional
public void cancelStudyApply(Long studyId) {
// TODO: 통합 테스트 통해 수강철회 관련 이벤트 처리 확인
Study study = studyRepository.findById(studyId).orElseThrow(() -> new CustomException(STUDY_NOT_FOUND));
Member currentMember = memberUtil.getCurrentMember();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.gdschongik.gdsc.domain.study.application;

import com.gdschongik.gdsc.domain.study.domain.StudyApplyCanceledEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;

@Slf4j
@Component
@RequiredArgsConstructor
public class StudyEventHandler {

private final CommonStudyService commonStudyService;

@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void handleStudyApplyCanceledEvent(StudyApplyCanceledEvent event) {
log.info("[StudyEventHandler] 스터디 수강신청 취소 이벤트 수신: studyId={}, memberId={}", event.studyId(), event.memberId());
commonStudyService.deleteAttendance(event.studyId(), event.memberId());
commonStudyService.deleteAssignmentHistory(event.studyId(), event.memberId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ public interface AssignmentHistoryCustomRepository {
boolean existsSubmittedAssignmentByMemberAndStudy(Member member, Study study);

List<AssignmentHistory> findAssignmentHistoriesByStudentAndStudyId(Member member, Long studyId);

void deleteByStudyIdAndMemberId(Long studyId, Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,16 @@ public List<AssignmentHistory> findAssignmentHistoriesByStudentAndStudyId(Member
private BooleanExpression eqStudyId(Long studyId) {
return studyId != null ? studyDetail.study.id.eq(studyId) : null;
}

@Override
public void deleteByStudyIdAndMemberId(Long studyId, Long memberId) {
queryFactory
.delete(assignmentHistory)
.where(eqMemberId(memberId), eqStudyId(studyId))
.execute();
}

private BooleanExpression eqMemberId(Long memberId) {
return memberId != null ? assignmentHistory.member.id.eq(memberId) : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@

public interface AttendanceCustomRepository {
List<Attendance> findByMemberAndStudyId(Member member, Long studyId);

void deleteByStudyIdAndMemberId(Long studyId, Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,12 @@ private BooleanExpression eqMemberId(Long memberId) {
private BooleanExpression eqStudyId(Long studyId) {
return studyId != null ? attendance.studyDetail.study.id.eq(studyId) : null;
}

@Override
public void deleteByStudyIdAndMemberId(Long studyId, Long memberId) {
queryFactory
.delete(attendance)
.where(eqMemberId(memberId), eqStudyId(studyId))
.execute();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.gdschongik.gdsc.domain.study.domain;

public record StudyApplyCanceledEvent(Long studyId, Long memberId) {}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void validateCancelStudyAssignment(Member member, StudyDetail studyDetail
public void validatePublishStudyAssignment(
Member member, StudyDetail studyDetail, AssignmentCreateUpdateRequest request) {
validateStudyMentorAuthorization(member, studyDetail);
validateDeadLine(request.deadLine());
validateDeadLine(request.deadLine(), studyDetail.getPeriod().getStartDate());
}

// 해당 스터디의 멘토가 아니라면 스터디에 대한 권한이 없다.
Expand All @@ -29,8 +29,8 @@ private void validateStudyMentorAuthorization(Member member, StudyDetail studyDe
}
}

private void validateDeadLine(LocalDateTime deadline) {
if (deadline.isBefore(LocalDateTime.now())) {
private void validateDeadLine(LocalDateTime deadline, LocalDateTime studyStartDate) {
if (deadline.isBefore(LocalDateTime.now()) || deadline.isBefore(studyStartDate)) {
throw new CustomException(ASSIGNMENT_DEADLINE_INVALID);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.PreRemove;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AccessLevel;
Expand Down Expand Up @@ -48,6 +49,11 @@ public static StudyHistory create(Member student, Study study) {
return StudyHistory.builder().student(student).study(study).build();
}

@PreRemove
private void preRemove() {
registerEvent(new StudyApplyCanceledEvent(this.study.getId(), this.student.getId()));
}

/**
* 레포지토리 링크를 업데이트합니다.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.gdschongik.gdsc.domain.member.domain.Member;
import com.gdschongik.gdsc.global.annotation.DomainService;
import com.gdschongik.gdsc.global.exception.CustomException;
import java.util.Optional;

@DomainService
public class StudyValidator {
Expand All @@ -25,21 +24,4 @@ public void validateStudyMentor(Member currentMember, Study study) {
throw new CustomException(STUDY_MENTOR_INVALID);
}
}

public void validateStudyMentorOrStudent(Member currentMember, Study study, Optional<StudyHistory> studyHistory) {
// 어드민인 경우 검증 통과
if (currentMember.isAdmin()) {
return;
}

// 해당 스터디의 수강생인지 검증
if (currentMember.isStudent() && studyHistory.isEmpty()) {
throw new CustomException(STUDY_ACCESS_NOT_ALLOWED);
}

// 해당 스터디의 담당 멘토인지 검증
if (!currentMember.getId().equals(study.getMentor().getId())) {
throw new CustomException(STUDY_MENTOR_INVALID);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ public record AssignmentResponse(
@Schema(description = "마감 기한") LocalDateTime deadline,
@Schema(description = "주차") Long week,
@Schema(description = "과제 명세 링크") String descriptionLink,
@Schema(description = "과제 상태") StudyStatus assignmentStatus) {
@Schema(description = "과제 상태") StudyStatus assignmentStatus,
@Schema(description = "주차 시작일") LocalDateTime studyDetailStartDate) {
public static AssignmentResponse from(StudyDetail studyDetail) {
Assignment assignment = studyDetail.getAssignment();
return new AssignmentResponse(
Expand All @@ -23,6 +24,7 @@ public static AssignmentResponse from(StudyDetail studyDetail) {
assignment.getDeadline(),
studyDetail.getWeek(),
assignment.getDescriptionLink(),
assignment.getStatus());
assignment.getStatus(),
studyDetail.getPeriod().getStartDate());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public record AssignmentSubmittableDto(
@Nullable @Schema(description = "과제 명세 링크") String descriptionLink,
@Nullable @Schema(description = "마감 기한") LocalDateTime deadline,
@Nullable @Schema(description = "과제 제출 링크") String submissionLink,
@Nullable @Schema(description = "과제 제출 실패 사유") SubmissionFailureType submissionFailureType) {
@Nullable @Schema(description = "과제 제출 실패 사유") SubmissionFailureType submissionFailureType,
@Nullable @Schema(description = "최종 수정 일시") LocalDateTime committedAt) {
public static AssignmentSubmittableDto of(StudyDetail studyDetail, AssignmentHistory assignmentHistory) {
Assignment assignment = studyDetail.getAssignment();

Expand All @@ -40,12 +41,22 @@ public static AssignmentSubmittableDto of(StudyDetail studyDetail, AssignmentHis
assignment.getDescriptionLink(),
assignment.getDeadline(),
assignmentHistory.getSubmissionLink(),
assignmentHistory.getSubmissionFailureType());
assignmentHistory.getSubmissionFailureType(),
assignmentHistory.getCommittedAt());
}

private static AssignmentSubmittableDto cancelledAssignment(StudyDetail studyDetail, Assignment assignment) {
return new AssignmentSubmittableDto(
studyDetail.getId(), assignment.getStatus(), studyDetail.getWeek(), null, null, null, null, null, null);
studyDetail.getId(),
assignment.getStatus(),
studyDetail.getWeek(),
null,
null,
null,
null,
null,
null,
null);
}

private static AssignmentSubmittableDto beforeAssignmentSubmit(StudyDetail studyDetail, Assignment assignment) {
Expand All @@ -58,6 +69,7 @@ private static AssignmentSubmittableDto beforeAssignmentSubmit(StudyDetail study
assignment.getDescriptionLink(),
assignment.getDeadline(),
null,
null,
null);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
public class GithubConstant {

public static final String GITHUB_DOMAIN = "github.com/";
public static final String GITHUB_ASSIGNMENT_PATH = "week%d/WIL.md";
public static final String GITHUB_ASSIGNMENT_PATH = "week%d/wil.md";
public static final String GITHUB_USER_API_URL = "https://api.github.com/user/%s";

private GithubConstant() {}
Expand Down
Loading

0 comments on commit 89856b2

Please sign in to comment.