Skip to content

Commit

Permalink
v2.3.0 (#716)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sangwook02 authored Aug 29, 2024
2 parents 9c87b8a + 0eb992e commit a40d6cd
Show file tree
Hide file tree
Showing 33 changed files with 340 additions and 100 deletions.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
id 'io.spring.dependency-management' version '1.1.4'
id 'org.asciidoctor.jvm.convert' version '3.3.2'
id 'com.diffplug.spotless' version '6.23.3'
id "io.sentry.jvm.gradle" version "4.11.0"
}

group = 'com.gdschongik'
Expand Down Expand Up @@ -95,6 +96,9 @@ dependencies {

// Github
implementation 'org.kohsuke:github-api:1.323'

// Sentry
implementation 'io.sentry:sentry-logback:7.14.0'
}

tasks.named('test') {
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ services:
- .env
environment:
- TZ=Asia/Seoul
- DOCKER_IMAGE_TAG=${IMAGE_FULL_URL}
redis:
image: "redis:alpine"
container_name: redis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ public void createFreeOrder(OrderCreateRequest request) {
orderValidator.validateFreeOrderCreate(membership, issuedCoupon, currentMember);

Order order = Order.createFree(request.orderNanoId(), membership, issuedCoupon.orElse(null), moneyInfo);
issuedCoupon.ifPresent(IssuedCoupon::use);

orderRepository.save(order);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import com.gdschongik.gdsc.domain.study.application.MentorStudyDetailService;
import com.gdschongik.gdsc.domain.study.dto.request.AssignmentCreateUpdateRequest;
import com.gdschongik.gdsc.domain.study.dto.response.AssignmentResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudySessionResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyCurriculumResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyMentorAttendanceResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
Expand Down Expand Up @@ -64,11 +65,19 @@ public ResponseEntity<Void> cancelStudyAssignment(@PathVariable Long studyDetail
return ResponseEntity.noContent().build();
}

// TODO 스터디 세션 워딩을 커리큘럼으로 변경해야함
@Operation(summary = "스터디 주차별 커리큘럼 목록 조회", description = "멘토가 자신의 스터디 커리큘럼 목록을 조회합니다")
@GetMapping("/sessions")
public ResponseEntity<List<StudySessionResponse>> getStudySessions(@RequestParam(name = "study") Long studyId) {
List<StudySessionResponse> response = mentorStudyDetailService.getSessions(studyId);
@GetMapping("/curriculums")
public ResponseEntity<List<StudyCurriculumResponse>> getStudyCurriculums(
@RequestParam(name = "studyId") Long studyId) {
List<StudyCurriculumResponse> response = mentorStudyDetailService.getCurriculums(studyId);
return ResponseEntity.ok(response);
}

@Operation(summary = "스터디 주차별 출결번호 조회", description = "멘토가 자신의 스터디 출결번호 목록을 조회합니다. 지난 출석은 목록에서 제외합니다.")
@GetMapping("/attendances")
public ResponseEntity<List<StudyMentorAttendanceResponse>> getAttendanceNumbers(
@RequestParam(name = "studyId") Long studyId) {
List<StudyMentorAttendanceResponse> response = mentorStudyDetailService.getAttendanceNumbers(studyId);
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.gdschongik.gdsc.domain.study.application.StudentStudyDetailService;
import com.gdschongik.gdsc.domain.study.dto.response.AssignmentDashboardResponse;
import com.gdschongik.gdsc.domain.study.dto.response.AssignmentHistoryStatusResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyStudentSessionResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyStudentCurriculumResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyTodoResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
Expand Down Expand Up @@ -38,12 +38,11 @@ public ResponseEntity<List<StudyTodoResponse>> getStudyTodoList(@RequestParam(na
return ResponseEntity.ok(response);
}

// TODO 스터디 세션 워딩을 커리큘럼으로 변경해야함
@Operation(summary = "스터디 커리큘럼 조회", description = "해당 스터디의 커리큘럼들을 조회합니다.")
@GetMapping("/sessions")
public ResponseEntity<List<StudyStudentSessionResponse>> getStudySessions(
@GetMapping("/curriculums")
public ResponseEntity<List<StudyStudentCurriculumResponse>> getStudyCurriculums(
@RequestParam(name = "studyId") Long studyId) {
List<StudyStudentSessionResponse> response = studentStudyDetailService.getStudySessions(studyId);
List<StudyStudentCurriculumResponse> response = studentStudyDetailService.getStudyCurriculums(studyId);
return ResponseEntity.ok(response);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ public class AdminStudyService {

@Transactional
public void createStudyAndStudyDetail(StudyCreateRequest request) {
// TODO: 멘토 권한 부여
final Member mentor = getMemberById(request.mentorId());
Member mentor = getMemberById(request.mentorId());
mentor.assignToMentor();
memberRepository.save(mentor);

Study study = studyDomainFactory.createNewStudy(request, mentor);
final Study savedStudy = studyRepository.save(study);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
import com.gdschongik.gdsc.domain.study.domain.StudyDetailValidator;
import com.gdschongik.gdsc.domain.study.dto.request.AssignmentCreateUpdateRequest;
import com.gdschongik.gdsc.domain.study.dto.response.AssignmentResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudySessionResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyCurriculumResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyMentorAttendanceResponse;
import com.gdschongik.gdsc.global.exception.CustomException;
import com.gdschongik.gdsc.global.util.MemberUtil;
import java.time.LocalDate;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -86,8 +88,19 @@ public void updateStudyAssignment(Long studyDetailId, AssignmentCreateUpdateRequ
}

@Transactional(readOnly = true)
public List<StudySessionResponse> getSessions(Long studyId) {
public List<StudyCurriculumResponse> getCurriculums(Long studyId) {
List<StudyDetail> studyDetails = studyDetailRepository.findAllByStudyIdOrderByWeekAsc(studyId);
return studyDetails.stream().map(StudySessionResponse::from).toList();
return studyDetails.stream().map(StudyCurriculumResponse::from).toList();
}

@Transactional(readOnly = true)
public List<StudyMentorAttendanceResponse> getAttendanceNumbers(Long studyId) {
List<StudyDetail> studyDetails = studyDetailRepository.findAllByStudyIdOrderByWeekAsc(studyId);

// 출석일이 오늘 or 오늘이후인 StudyDetail
return studyDetails.stream()
.filter(studyDetail -> studyDetail.isAttendanceDayNotPassed(LocalDate.now()))
.map(StudyMentorAttendanceResponse::from)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import com.gdschongik.gdsc.domain.study.domain.StudyHistory;
import com.gdschongik.gdsc.domain.study.domain.StudyValidator;
import com.gdschongik.gdsc.domain.study.dto.request.StudyAnnouncementCreateUpdateRequest;
import com.gdschongik.gdsc.domain.study.dto.request.StudySessionCreateRequest;
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.StudyStudentResponse;
Expand Down Expand Up @@ -101,7 +101,6 @@ public void deleteStudyAnnouncement(Long studyAnnouncementId) {
log.info("[MentorStudyService] 스터디 공지 삭제 완료: studyAnnouncementId={}", studyAnnouncement.getId());
}

// TODO session -> curriculum 변경
@Transactional
public void updateStudy(Long studyId, StudyUpdateRequest request) {
Member currentMember = memberUtil.getCurrentMember();
Expand All @@ -112,9 +111,9 @@ public void updateStudy(Long studyId, StudyUpdateRequest request) {
// StudyDetail ID를 추출하여 Set으로 저장
Set<Long> studyDetailIds = studyDetails.stream().map(StudyDetail::getId).collect(Collectors.toSet());

// 요청된 StudySessionCreateRequest의 StudyDetail ID를 추출하여 Set으로 저장
Set<Long> requestIds = request.studySessions().stream()
.map(StudySessionCreateRequest::studyDetailId)
// 요청된 StudyCurriculumCreateRequest의 StudyDetail ID를 추출하여 Set으로 저장
Set<Long> requestIds = request.studyCurriculums().stream()
.map(StudyCurriculumCreateRequest::studyDetailId)
.collect(Collectors.toSet());

studyDetailValidator.validateUpdateStudyDetail(studyDetailIds, requestIds);
Expand All @@ -123,24 +122,24 @@ public void updateStudy(Long studyId, StudyUpdateRequest request) {
studyRepository.save(study);
log.info("[MentorStudyService] 스터디 기본 정보 수정 완료: studyId={}", studyId);

updateAllStudyDetailSession(studyDetails, request.studySessions());
updateAllStudyDetailCurriculum(studyDetails, request.studyCurriculums());
}

private void updateAllStudyDetailSession(
List<StudyDetail> studyDetails, List<StudySessionCreateRequest> studySessions) {
private void updateAllStudyDetailCurriculum(
List<StudyDetail> studyDetails, List<StudyCurriculumCreateRequest> studyCurriculums) {
for (StudyDetail studyDetail : studyDetails) {
Long id = studyDetail.getId();
StudySessionCreateRequest matchingSession = studySessions.stream()
.filter(session -> session.studyDetailId().equals(id))
StudyCurriculumCreateRequest matchingCurriculum = studyCurriculums.stream()
.filter(curriculum -> curriculum.studyDetailId().equals(id))
.findFirst()
.get();

studyDetail.updateSession(
studyDetail.updateCurriculum(
studyDetail.getStudy().getStartTime(),
matchingSession.title(),
matchingSession.description(),
matchingSession.difficulty(),
matchingSession.status());
matchingCurriculum.title(),
matchingCurriculum.description(),
matchingCurriculum.difficulty(),
matchingCurriculum.status());
}
studyDetailRepository.saveAll(studyDetails);
log.info("[MentorStudyService] 스터디 상세정보 커리큘럼 작성 완료: studyDetailId={}", studyDetails);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@
import com.gdschongik.gdsc.domain.study.domain.Attendance;
import com.gdschongik.gdsc.domain.study.domain.StudyDetail;
import com.gdschongik.gdsc.domain.study.domain.StudyHistory;
import com.gdschongik.gdsc.domain.study.dto.response.AssignmentDashboardResponse;
import com.gdschongik.gdsc.domain.study.dto.response.AssignmentHistoryStatusResponse;
import com.gdschongik.gdsc.domain.study.dto.response.AssignmentSubmittableDto;
import com.gdschongik.gdsc.domain.study.dto.response.StudyStudentSessionResponse;
import com.gdschongik.gdsc.domain.study.dto.response.StudyTodoResponse;
import com.gdschongik.gdsc.domain.study.dto.response.*;
import com.gdschongik.gdsc.global.exception.CustomException;
import com.gdschongik.gdsc.global.exception.ErrorCode;
import com.gdschongik.gdsc.global.util.MemberUtil;
Expand Down Expand Up @@ -69,7 +65,7 @@ public List<StudyTodoResponse> getStudyTodoList(Long studyId) {
List<StudyTodoResponse> response = new ArrayList<>();
// 출석체크 정보 (개설 상태이고, 오늘이 출석체크날짜인 것)
studyDetails.stream()
.filter(studyDetail -> studyDetail.getSession().isOpen()
.filter(studyDetail -> studyDetail.getCurriculum().isOpen()
&& studyDetail.getAttendanceDay().equals(now))
.forEach(studyDetail -> response.add(StudyTodoResponse.createAttendanceType(
studyDetail, now, isAttended(attendances, studyDetail))));
Expand All @@ -83,15 +79,15 @@ public List<StudyTodoResponse> getStudyTodoList(Long studyId) {
return response;
}

public List<StudyStudentSessionResponse> getStudySessions(Long studyId) {
public List<StudyStudentCurriculumResponse> getStudyCurriculums(Long studyId) {
Member member = memberUtil.getCurrentMember();
final List<StudyDetail> studyDetails = studyDetailRepository.findAllByStudyIdOrderByWeekAsc(studyId);
final List<AssignmentHistory> assignmentHistories =
assignmentHistoryRepository.findAssignmentHistoriesByStudentAndStudyId(member, studyId);
final List<Attendance> attendances = attendanceRepository.findByMemberAndStudyId(member, studyId);

return studyDetails.stream()
.map(studyDetail -> StudyStudentSessionResponse.of(
.map(studyDetail -> StudyStudentCurriculumResponse.of(
studyDetail,
getSubmittedAssignment(assignmentHistories, studyDetail),
isAttended(attendances, studyDetail),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.gdschongik.gdsc.global.exception.CustomException;
import com.gdschongik.gdsc.global.util.MemberUtil;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -106,7 +107,8 @@ public void attend(Long studyDetailId, StudyAttendCreateRequest request) {
public StudentMyCurrentStudyResponse getMyCurrentStudy() {
Member currentMember = memberUtil.getCurrentMember();
StudyHistory studyHistory = studyHistoryRepository.findAllByStudent(currentMember).stream()
.filter(s -> s.getStudy().isStudyOngoing())
.filter(s -> s.getStudy().getApplicationPeriod().getStartDate().isBefore(LocalDateTime.now())
&& s.getStudy().getPeriod().getEndDate().isAfter(LocalDateTime.now()))
.findFirst()
.orElse(null);
return StudentMyCurrentStudyResponse.from(studyHistory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public static Study createStudy(
DayOfWeek dayOfWeek,
LocalTime startTime,
LocalTime endTime) {
validateApplicationStartDateBeforeSessionStartDate(applicationPeriod.getStartDate(), period.getStartDate());
validateApplicationStartDateBeforeCurriculumStartDate(applicationPeriod.getStartDate(), period.getStartDate());
validateMentorRole(mentor);
validateStudyTime(studyType, startTime, endTime);
return Study.builder()
Expand All @@ -134,7 +134,7 @@ public static Study createStudy(

// 검증 로직

private static void validateApplicationStartDateBeforeSessionStartDate(
private static void validateApplicationStartDateBeforeCurriculumStartDate(
LocalDateTime applicationStartDate, LocalDateTime startDate) {
if (!applicationStartDate.isBefore(startDate)) {
throw new CustomException(STUDY_APPLICATION_START_DATE_INVALID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.gdschongik.gdsc.domain.common.model.BaseEntity;
import com.gdschongik.gdsc.domain.recruitment.domain.vo.Period;
import com.gdschongik.gdsc.domain.study.domain.vo.Assignment;
import com.gdschongik.gdsc.domain.study.domain.vo.Session;
import com.gdschongik.gdsc.domain.study.domain.vo.Curriculum;
import com.gdschongik.gdsc.global.exception.CustomException;
import jakarta.persistence.*;
import java.time.DayOfWeek;
Expand Down Expand Up @@ -41,12 +41,12 @@ public class StudyDetail extends BaseEntity {
private Period period;

@Embedded
@AttributeOverride(name = "title", column = @Column(name = "session_title"))
@AttributeOverride(name = "difficulty", column = @Column(name = "session_difficulty"))
@AttributeOverride(name = "startAt", column = @Column(name = "session_start_at"))
@AttributeOverride(name = "description", column = @Column(name = "session_description"))
@AttributeOverride(name = "status", column = @Column(name = "session_status"))
private Session session;
@AttributeOverride(name = "title", column = @Column(name = "curriculum_title"))
@AttributeOverride(name = "difficulty", column = @Column(name = "curriculum_difficulty"))
@AttributeOverride(name = "startAt", column = @Column(name = "curriculum_start_at"))
@AttributeOverride(name = "description", column = @Column(name = "curriculum_description"))
@AttributeOverride(name = "status", column = @Column(name = "curriculum_status"))
private Curriculum curriculum;

@Embedded
@AttributeOverride(name = "title", column = @Column(name = "assignment_title"))
Expand All @@ -57,12 +57,17 @@ public class StudyDetail extends BaseEntity {

@Builder(access = AccessLevel.PRIVATE)
private StudyDetail(
Study study, Long week, String attendanceNumber, Period period, Session session, Assignment assignment) {
Study study,
Long week,
String attendanceNumber,
Period period,
Curriculum curriculum,
Assignment assignment) {
this.study = study;
this.week = week;
this.attendanceNumber = attendanceNumber;
this.period = period;
this.session = session;
this.curriculum = curriculum;
this.assignment = assignment;
}

Expand All @@ -73,7 +78,7 @@ public static StudyDetail createStudyDetail(Study study, Long week, String atten
.period(period)
.attendanceNumber(attendanceNumber)
.period(period)
.session(Session.createEmptySession())
.curriculum(Curriculum.createEmptyCurriculum())
.assignment(Assignment.createEmptyAssignment())
.build();
}
Expand Down Expand Up @@ -123,9 +128,14 @@ public LocalDate getAttendanceDay() {
return startDate.plusDays(daysToAdd);
}

public void updateSession(
// 출석일이 오늘 or 오늘이후인지 확인
public boolean isAttendanceDayNotPassed(LocalDate now) {
return !getAttendanceDay().isBefore(now);
}

public void updateCurriculum(
LocalTime startAt, String title, String description, Difficulty difficulty, StudyStatus status) {
session = Session.generateSession(startAt, title, description, difficulty, status);
curriculum = Curriculum.generateCurriculum(startAt, title, description, difficulty, status);
}

public void validateAssignmentSubmittable(LocalDateTime now) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ private void validateUpdateDeadline(
}

public void validateUpdateStudyDetail(Set<Long> studyDetails, Set<Long> requests) {
// StudyDetail 목록과 요청된 StudySessionCreateRequest 목록의 크기를 먼저 비교
// StudyDetail 목록과 요청된 StudyCurriculumCreateRequest 목록의 크기를 먼저 비교
if (studyDetails.size() != requests.size()) {
throw new CustomException(STUDY_DETAIL_SESSION_SIZE_MISMATCH);
throw new CustomException(STUDY_DETAIL_CURRICULUM_SIZE_MISMATCH);
}

// 두 ID 집합이 동일한지 비교하여 ID 불일치 시 예외를 던짐
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
@AllArgsConstructor
public enum StudyType {
ASSIGNMENT("과제 스터디"),
ONLINE("온라인 세션"),
OFFLINE("오프라인 세션");
ONLINE("온라인 커리큘럼"),
OFFLINE("오프라인 커리큘럼");

private final String value;
}
Loading

0 comments on commit a40d6cd

Please sign in to comment.