Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] 스터디 지원 결과에 따른 가입 정보 자동 반영 #48

Merged
merged 7 commits into from
Dec 20, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.join.core.application.constant;

public enum ApplicationRejectReason {
ATTENDANCE, AUTHENTICATION, RATING, STUDY_COUNT, OTHER

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.join.core.application.controller;

import com.join.core.application.dto.request.ApplicationCreateRequest;
import com.join.core.application.dto.request.ApplicationRejectRequest;
import com.join.core.application.service.ApplicationDecisionService;
import com.join.core.application.service.ApplicationService;
import com.join.core.auth.domain.UserPrincipal;
Expand Down Expand Up @@ -54,8 +55,10 @@ public ApiResponse<Void> acceptApplication(@PathVariable Long applicationId,
@PreAuthorize("isAuthenticated()")
@PatchMapping("/{applicationId}/reject")
public ApiResponse<Void> rejectApplication(@PathVariable Long applicationId,
@AuthenticationPrincipal UserPrincipal principal) {
applicationDecisionService.rejectApplication(applicationId, principal.getAvatarId());
@AuthenticationPrincipal UserPrincipal principal,
@RequestBody ApplicationRejectRequest rejectRequest) {
applicationDecisionService.rejectApplication(applicationId, principal.getAvatarId(),
rejectRequest.getRejectReason(), rejectRequest.getOtherReason());
return ApiResponse.ok();
}

Expand Down
13 changes: 12 additions & 1 deletion src/main/java/com/join/core/application/domain/Application.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.join.core.application.domain;

import com.join.core.application.constant.ApplicationRejectReason;
import com.join.core.application.constant.ApplicationStatus;
import com.join.core.avatar.domain.Avatar;
import com.join.core.common.domain.BaseTimeEntity;
Expand Down Expand Up @@ -43,6 +44,12 @@ public class Application extends BaseTimeEntity {
@JoinColumn(name = "avatar_id", nullable = false)
private Avatar avatar;

@Size(max = 100)
private String otherReason;

@Enumerated(EnumType.STRING)
private ApplicationRejectReason rejectReason;

public Application(Study study, Avatar avatar, LocalDate appDate, String introduction) {
this.study = study;
this.avatar = avatar;
Expand All @@ -59,9 +66,13 @@ public void accept() {
}
}

public void reject() {
public void reject(ApplicationRejectReason rejectReason, String otherReason) {
if (this.status == ApplicationStatus.PENDING) {
this.status = ApplicationStatus.REJECTED;
this.rejectReason = rejectReason;
if (rejectReason == ApplicationRejectReason.OTHER && otherReason != null) {
this.otherReason = otherReason;
}
} else {
throw new IllegalStateException("이미 처리된 지원입니다.");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.join.core.application.dto.request;

import com.join.core.application.constant.ApplicationRejectReason;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class ApplicationRejectRequest {

@Schema(description = "거절 사유", example = "OTHER")
@NotBlank
private ApplicationRejectReason rejectReason;

@Schema(description = "거절 기타 사유", example = "스터디 성격과 맞지 않은 것 같습니다.")
private String otherReason;

}
Original file line number Diff line number Diff line change
@@ -1,33 +1,57 @@
package com.join.core.application.service;

import com.join.core.application.constant.ApplicationRejectReason;
import com.join.core.application.domain.Application;
import com.join.core.application.repository.ApplicationRepository;
import com.join.core.common.exception.ErrorCode;
import com.join.core.common.exception.impl.EntityNotFoundException;
import com.join.core.common.exception.impl.InvalidParamException;
import com.join.core.common.exception.impl.NoPermissionException;
import com.join.core.enrollment.constant.EnrollmentStatus;
import com.join.core.enrollment.constant.StudyRole;
import com.join.core.enrollment.dto.request.EnrollmentCreateRequest;
import com.join.core.enrollment.service.EnrollmentService;
import com.join.core.study.domain.Study;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

import static com.join.core.common.exception.ErrorCode.INVALID_PARAMETER;

@Service
@RequiredArgsConstructor
public class ApplicationDecisionService {

private final ApplicationRepository applicationRepository;
private final ApplicationStore applicationStore;
private final EnrollmentService enrollmentService;

@Transactional
public void acceptApplication(Long applicationId, Long avatarId) {
Application application = getValidApplication(applicationId, avatarId);
application.accept();
applicationStore.store(application);

EnrollmentCreateRequest enrollmentRequest = new EnrollmentCreateRequest(
application.getStudy().getId(),
application.getAvatar().getId(),
EnrollmentStatus.JOINED,
StudyRole.MEMBER,
LocalDateTime.now()
);

enrollmentService.createEnrollment(enrollmentRequest, application.getStudy(), application.getAvatar());
}

@Transactional
public void rejectApplication(Long applicationId, Long avatarId) {
public void rejectApplication(Long applicationId, Long avatarId, ApplicationRejectReason rejectReason, String otherReason) {
if (rejectReason == ApplicationRejectReason.OTHER && (otherReason == null || otherReason.trim().isEmpty())) {
throw new InvalidParamException(INVALID_PARAMETER, "기타 선택 시 사유를 입력해야 합니다.");
}
Application application = getValidApplication(applicationId, avatarId);
application.reject();
application.reject(rejectReason, otherReason);
applicationStore.store(application);
}

Expand All @@ -40,7 +64,6 @@ private Application getValidApplication(Long applicationId, Long avatarId) {
if (!study.getWriter().getId().equals(avatarId)) {
throw new NoPermissionException(ErrorCode.UNAUTHORIZED_ACCESS);
}

return application;
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.join.core.enrollment.constant;

public enum EnrollmentStatus {
APPROVED, DENIED

}
JOINED, REQUEST_LEAVE, LEFT
}
21 changes: 15 additions & 6 deletions src/main/java/com/join/core/enrollment/domain/Enrollment.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.join.core.enrollment.domain;

import com.join.core.avatar.domain.Avatar;
import com.join.core.enrollment.constant.EnrollmentEndReason;
import com.join.core.enrollment.constant.EnrollmentStatus;
import com.join.core.enrollment.constant.StudyRole;
import com.join.core.study.domain.Study;
import com.join.core.common.domain.BaseTimeEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -27,20 +27,18 @@ public class Enrollment extends BaseTimeEntity {
@Enumerated(EnumType.STRING)
private EnrollmentStatus status;

@Size(min = 10, max = 150)
private String endReason;

@NotNull
@Enumerated(EnumType.STRING)
private StudyRole role;

@NotNull
private LocalDateTime enrolledDate;

@NotNull
private LocalDateTime endDate;

@NotNull
@Enumerated(EnumType.STRING)
private EnrollmentEndReason endReason;

@NotNull
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "study_id")
Expand All @@ -51,4 +49,15 @@ public class Enrollment extends BaseTimeEntity {
@JoinColumn(name = "avatar_id")
private Avatar avatar;

public Enrollment(Study study, Avatar avatar, EnrollmentStatus status, LocalDateTime enrolledDate,
LocalDateTime endDate, String endReason, StudyRole role) {
this.study = study;
this.avatar = avatar;
this.status = status;
this.enrolledDate = enrolledDate;
this.endDate = endDate;
this.endReason = endReason;
this.role = role;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.join.core.enrollment.dto.request;

import com.join.core.enrollment.constant.EnrollmentStatus;
import com.join.core.enrollment.constant.StudyRole;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class EnrollmentCreateRequest {

private Long studyId;
private Long avatarId;
private EnrollmentStatus status;
private StudyRole role;
private LocalDateTime enrolledDate;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.join.core.enrollment.repository;

import com.join.core.enrollment.domain.Enrollment;
import org.springframework.data.jpa.repository.JpaRepository;

public interface EnrollmentRepository extends JpaRepository<Enrollment, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.join.core.enrollment.service;

import com.join.core.enrollment.domain.Enrollment;
import com.join.core.enrollment.dto.request.EnrollmentCreateRequest;
import com.join.core.enrollment.repository.EnrollmentRepository;
import com.join.core.study.domain.Study;
import com.join.core.avatar.domain.Avatar;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class EnrollmentService {

private final EnrollmentRepository enrollmentRepository;

public void createEnrollment(EnrollmentCreateRequest request, Study study, Avatar avatar) {
Enrollment enrollment = new Enrollment(
study,
avatar,
request.getStatus(),
request.getEnrolledDate(),
null,
null,
request.getRole()
);
enrollmentRepository.save(enrollment);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,26 @@
import com.join.core.category.domain.Category;
import com.join.core.category.service.CategoryReader;
import com.join.core.common.exception.ErrorCode;
import com.join.core.common.exception.impl.InvalidParamException;
import com.join.core.common.exception.impl.NoPermissionException;
import com.join.core.schedule.domain.StudySchedule;
import com.join.core.study.domain.Study;
import com.join.core.study.dto.request.StudyReRecruitRequest;
import com.join.core.study.dto.request.StudyRecruitRequest;
import com.join.core.enrollment.service.EnrollmentService;
import com.join.core.enrollment.dto.request.EnrollmentCreateRequest;
import com.join.core.enrollment.constant.EnrollmentStatus;
import com.join.core.enrollment.constant.StudyRole;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

import static com.join.core.common.exception.ErrorCode.INVALID_PARAMETER;

@Service
@RequiredArgsConstructor
public class StudyRecruitService {
Expand All @@ -27,9 +36,19 @@ public class StudyRecruitService {
private final AddressReader addressReader;
private final CategoryReader categoryReader;
private final StudyReader studyReader;
private final EnrollmentService enrollmentService;

@Transactional
public void createStudy(Long avatarId, StudyRecruitRequest recruitRequest) {
LocalDate now = LocalDate.now();

if (recruitRequest.getStDate().isBefore(now) || recruitRequest.getRecruitEndDate().isBefore(now)) {
throw new InvalidParamException(INVALID_PARAMETER, "스터디 시작일과 모집 종료일은 현재 이후여야 합니다.");
}
if (recruitRequest.getStDate().isAfter(recruitRequest.getEndDate())) {
throw new InvalidParamException(INVALID_PARAMETER, "시작일보다 종료일이 이후여야 합니다.");
}

Avatar writer = avatarReader.getAvatarById(avatarId);
Address address = addressReader.getAddressByLocation(recruitRequest.getProvince(), recruitRequest.getCity());
Category category = categoryReader.getCategoryByName(recruitRequest.getCategoryName());
Expand All @@ -44,6 +63,15 @@ public void createStudy(Long avatarId, StudyRecruitRequest recruitRequest) {
}

studyStore.store(study);

EnrollmentCreateRequest enrollmentRequest = new EnrollmentCreateRequest(
study.getId(),
writer.getId(),
EnrollmentStatus.JOINED,
StudyRole.LEADER,
LocalDateTime.now()
);
enrollmentService.createEnrollment(enrollmentRequest, study, writer);
}

@Transactional
Expand All @@ -54,9 +82,14 @@ public void reRecruitStudy(Long avatarId, String studyToken, StudyReRecruitReque
if (!study.getWriter().getId().equals(avatarId)) {
throw new NoPermissionException(ErrorCode.UNAUTHORIZED_ACCESS);
}
if (reRecruitRequest.getRecruitEndDate().isBefore(LocalDate.now())) {
throw new InvalidParamException(INVALID_PARAMETER, "모집 종료일은 현재 이후여야 합니다.");
}
if (study.getStDate().isAfter(reRecruitRequest.getRecruitEndDate())) {
throw new InvalidParamException(INVALID_PARAMETER, "시작일보다 종료일이 이후여야 합니다.");
}

study.updateRecruitDetails(reRecruitRequest);

studyStore.store(study);
}

Expand Down
Loading