Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ public class Application {
@Column(columnDefinition = "int not null default 0")
private Integer updateCount;

@Column(length = 50, nullable = false)
private String term;

@ManyToOne
private UniversityInfoForApply firstChoiceUniversity;

Expand All @@ -63,10 +66,14 @@ public class Application {
public Application(
SiteUser siteUser,
Gpa gpa,
LanguageTest languageTest) {
LanguageTest languageTest,
String term) {
this.siteUser = siteUser;
this.gpa = gpa;
this.languageTest = languageTest;
this.term = term;
this.updateCount = 0;
this.verifyStatus = PENDING;
}

public void updateGpaAndLanguageTest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public record UniversityApplicantsResponse(

public static UniversityApplicantsResponse of(UniversityInfoForApply universityInfoForApply, List<ApplicantResponse> applicant) {
return new UniversityApplicantsResponse(
universityInfoForApply.getUniversity().getKoreanName(),
universityInfoForApply.getKoreanName(),
universityInfoForApply.getStudentCapacity(),
universityInfoForApply.getUniversity().getRegion().getKoreanName(),
universityInfoForApply.getUniversity().getCountry().getKoreanName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ public interface ApplicationRepository extends JpaRepository<Application, Long>

boolean existsByNicknameForApply(String nicknameForApply);

Optional<Application> findBySiteUser_Email(String email);
Optional<Application> findTop1BySiteUser_EmailOrderByTermDesc(String email);

Optional<Application> findBySiteUser(SiteUser siteUser);
Optional<Application> findBySiteUserAndTerm(SiteUser siteUser, String term);

List<Application> findAllByFirstChoiceUniversityAndVerifyStatus(UniversityInfoForApply firstChoiceUniversity, VerifyStatus verifyStatus);
List<Application> findAllByFirstChoiceUniversityAndVerifyStatusAndTerm(UniversityInfoForApply firstChoiceUniversity, VerifyStatus verifyStatus, String term);

List<Application> findAllBySecondChoiceUniversityAndVerifyStatus(UniversityInfoForApply secondChoiceUniversity, VerifyStatus verifyStatus);
List<Application> findAllBySecondChoiceUniversityAndVerifyStatusAndTerm(UniversityInfoForApply secondChoiceUniversity, VerifyStatus verifyStatus, String term);

List<Application> findAllByThirdChoiceUniversityAndVerifyStatus(UniversityInfoForApply thirdChoiceUniversity, VerifyStatus verifyStatus);
List<Application> findAllByThirdChoiceUniversityAndVerifyStatusAndTerm(UniversityInfoForApply thirdChoiceUniversity, VerifyStatus verifyStatus, String term);

default Application getApplicationBySiteUser(SiteUser siteUser) {
return findBySiteUser(siteUser)
default Application getApplicationBySiteUserAndTerm(SiteUser siteUser, String term) {
return findBySiteUserAndTerm(siteUser, term)
.orElseThrow(() -> new CustomException(APPLICATION_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,41 +52,43 @@ public ApplicationsResponse getApplicants(String email, String regionCode, Strin
List<University> universities
= universityFilterRepository.findByRegionCodeAndKeywords(regionCode, List.of(keyword));

// 1지망, 2지망 지원자들을 조회한다.
List<UniversityApplicantsResponse> firstChoiceApplicants = getFirstChoiceApplicants(universities, siteUser);
List<UniversityApplicantsResponse> secondChoiceApplicants = getSecondChoiceApplicants(universities, siteUser);
List <UniversityApplicantsResponse> thirdChoiceApplicants = getThirdChoiceApplicants(universities, siteUser);
// 1지망, 2지망, 3지망 지원자들을 조회한다.
List<UniversityApplicantsResponse> firstChoiceApplicants = getFirstChoiceApplicants(universities, siteUser, term);
List<UniversityApplicantsResponse> secondChoiceApplicants = getSecondChoiceApplicants(universities, siteUser, term);
List<UniversityApplicantsResponse> thirdChoiceApplicants = getThirdChoiceApplicants(universities, siteUser, term);
return new ApplicationsResponse(firstChoiceApplicants, secondChoiceApplicants, thirdChoiceApplicants);
}

// 학기별로 상태가 관리된다.
// 금학기에 지원이력이 있는 사용자만 지원정보를 확인할 수 있도록 한다.
private void validateSiteUserCanViewApplicants(SiteUser siteUser) {
VerifyStatus verifyStatus = applicationRepository.getApplicationBySiteUser(siteUser).getVerifyStatus();
VerifyStatus verifyStatus = applicationRepository.getApplicationBySiteUserAndTerm(siteUser,term).getVerifyStatus();
if (verifyStatus != VerifyStatus.APPROVED) {
throw new CustomException(APPLICATION_NOT_APPROVED);
}
}

private List<UniversityApplicantsResponse> getFirstChoiceApplicants(List<University> universities, SiteUser siteUser) {
private List<UniversityApplicantsResponse> getFirstChoiceApplicants(List<University> universities, SiteUser siteUser, String term) {
return getApplicantsByChoice(
universities,
siteUser,
uia -> applicationRepository.findAllByFirstChoiceUniversityAndVerifyStatus(uia, VerifyStatus.APPROVED)
uia -> applicationRepository.findAllByFirstChoiceUniversityAndVerifyStatusAndTerm(uia, VerifyStatus.APPROVED, term)
);
}

private List<UniversityApplicantsResponse> getSecondChoiceApplicants(List<University> universities, SiteUser siteUser) {
private List<UniversityApplicantsResponse> getSecondChoiceApplicants(List<University> universities, SiteUser siteUser, String term) {
return getApplicantsByChoice(
universities,
siteUser,
uia -> applicationRepository.findAllBySecondChoiceUniversityAndVerifyStatus(uia, VerifyStatus.APPROVED)
uia -> applicationRepository.findAllBySecondChoiceUniversityAndVerifyStatusAndTerm(uia, VerifyStatus.APPROVED, term)
);
}

private List<UniversityApplicantsResponse> getThirdChoiceApplicants(List<University> universities, SiteUser siteUser) {
private List<UniversityApplicantsResponse> getThirdChoiceApplicants(List<University> universities, SiteUser siteUser, String term) {
return getApplicantsByChoice(
universities,
siteUser,
uia -> applicationRepository.findAllByThirdChoiceUniversityAndVerifyStatus(uia, VerifyStatus.APPROVED)
uia -> applicationRepository.findAllByThirdChoiceUniversityAndVerifyStatusAndTerm(uia, VerifyStatus.APPROVED, term)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,9 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.*;

import static com.example.solidconnection.custom.exception.ErrorCode.APPLY_UPDATE_LIMIT_EXCEED;
import static com.example.solidconnection.custom.exception.ErrorCode.CANT_APPLY_FOR_SAME_UNIVERSITY;
import static com.example.solidconnection.custom.exception.ErrorCode.SCORE_SHOULD_SUBMITTED_FIRST;
import static com.example.solidconnection.custom.exception.ErrorCode.*;

@RequiredArgsConstructor
@Service
Expand All @@ -35,11 +31,12 @@ public class ApplicationSubmissionService {
private final SiteUserRepository siteUserRepository;

@Value("${university.term}")
public String term;
private String term;

/*
* 학점과 영어 성적을 제출한다.
* - 기존에 제출한 적이 있다면, 수정한다.
* - 금학기에 제출한 적이 있다면, 수정한다.
* - 성적을 제출한적이 한번도 없거나 제출한적이 있지만 금학기에 제출한 적이 없다면 새로 등록한다.
* - 수정을 하고 나면, 성적 승인 상태(verifyStatus)를 PENDING 상태로 변경한다.
* */
@Transactional
Expand All @@ -48,15 +45,14 @@ public boolean submitScore(String email, ScoreRequest scoreRequest) {
Gpa gpa = scoreRequest.toGpa();
LanguageTest languageTest = scoreRequest.toLanguageTest();

applicationRepository.findBySiteUser_Email(email)
applicationRepository.findBySiteUserAndTerm(siteUser, term)
.ifPresentOrElse(
// 수정
// 금학기에 성적 제출 이력이 있는 경우
application -> application.updateGpaAndLanguageTest(gpa, languageTest),

// 최초 등록
() -> applicationRepository.save(
new Application(siteUser, gpa, languageTest)
)
() -> {
// 성적 제출한적이 한번도 없는 경우 && 성적 제출한적이 있지만 금학기에 없는 경우
applicationRepository.save(new Application(siteUser, gpa, languageTest, term));
}
);
return true;
}
Expand All @@ -73,9 +69,20 @@ public boolean submitScore(String email, ScoreRequest scoreRequest) {
@Transactional
public boolean submitUniversityChoice(String email, UniversityChoiceRequest universityChoiceRequest) {
validateNoDuplicateUniversityChoices(universityChoiceRequest);
Application application = applicationRepository.findBySiteUser_Email(email)

// 성적 제출한 적이 한번도 없는 경우
Application existingApplication = applicationRepository.findTop1BySiteUser_EmailOrderByTermDesc(email)
.orElseThrow(() -> new CustomException(SCORE_SHOULD_SUBMITTED_FIRST));

Application application = Optional.of(existingApplication)
.filter(app -> !app.getTerm().equals(term))
.map(app -> {
// 성적 제출한 적이 있지만 금학기에 없는 경우, 이전 성적으로 새 Application 객체를 등록
SiteUser siteUser = siteUserRepository.getByEmail(email);
return applicationRepository.save(new Application(siteUser, app.getGpa(), app.getLanguageTest(), term));
})
.orElse(existingApplication); // 금학기에 이미 성적 제출한 경우 기존 객체 사용

UniversityInfoForApply firstChoiceUniversity = universityInfoForApplyRepository
.getUniversityInfoForApplyByIdAndTerm(universityChoiceRequest.firstChoiceUniversityId(), term);
UniversityInfoForApply secondChoiceUniversity = universityInfoForApplyRepository
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.example.solidconnection.siteuser.repository.SiteUserRepository;
import com.example.solidconnection.type.VerifyStatus;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -25,13 +26,17 @@ public class VerifyStatusQueryService {
private final ApplicationRepository applicationRepository;
private final SiteUserRepository siteUserRepository;

@Value("${university.term}")
private String term;

/*
* 지원 상태를 조회한다.
* 학기별로 상태가 관리된다.
* */
@Transactional(readOnly = true)
public VerifyStatusResponse getVerifyStatus(String email) {
SiteUser siteUser = siteUserRepository.getByEmail(email);
Optional<Application> application = applicationRepository.findBySiteUser_Email(siteUser.getEmail());
Optional<Application> application = applicationRepository.findBySiteUserAndTerm(siteUser,term);

// 아무것도 제출 안함
if (application.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
import com.example.solidconnection.comment.domain.Comment;
import com.example.solidconnection.siteuser.dto.PostFindSiteUserResponse;

import java.time.LocalDateTime;
import java.time.ZonedDateTime;

public record PostFindCommentResponse(
Long id,
Long parentId,
String content,
Boolean isOwner,
LocalDateTime createdAt,
LocalDateTime updatedAt,
ZonedDateTime createdAt,
ZonedDateTime updatedAt,
PostFindSiteUserResponse postFindSiteUserResponse

) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.example.solidconnection.custom.exception.ErrorCode.CAN_NOT_UPDATE_DEPRECATED_COMMENT;
import static com.example.solidconnection.custom.exception.ErrorCode.INVALID_POST_ACCESS;
import static com.example.solidconnection.custom.exception.ErrorCode.*;

@Service
@RequiredArgsConstructor
Expand All @@ -43,6 +41,13 @@ private void validateDeprecated(Comment comment) {
}
}

// 대대댓글부터 허용하지 않음
private void validateCommentDepth(Comment parentComment) {
if (parentComment.getParentComment() != null) {
throw new CustomException(INVALID_COMMENT_LEVEL);
}
}

@Transactional(readOnly = true)
public List<PostFindCommentResponse> findCommentsByPostId(String email, Long postId) {
return commentRepository.findCommentTreeByPostId(postId)
Expand All @@ -60,6 +65,7 @@ public CommentCreateResponse createComment(String email, Long postId, CommentCre
Comment parentComment = null;
if (commentCreateRequest.parentId() != null) {
parentComment = commentRepository.getById(commentCreateRequest.parentId());
validateCommentDepth(parentComment);
}
Comment createdComment = commentRepository.save(commentCreateRequest.toEntity(siteUser, post, parentComment));

Expand Down Expand Up @@ -87,15 +93,28 @@ public CommentDeleteResponse deleteCommentById(String email, Long postId, Long c
Comment comment = commentRepository.getById(commentId);
validateOwnership(comment, email);

if (comment.getCommentList().isEmpty()) {
// 하위 댓글이 없다면 삭제한다.
if (comment.getParentComment() != null) {
// 대댓글인 경우
Comment parentComment = comment.getParentComment();
// 대댓글을 삭제합니다.
comment.resetPostAndSiteUserAndParentComment();
commentRepository.deleteById(commentId);
// 대댓글 삭제 이후, 부모댓글이 무의미하다면 이역시 삭제합니다.
if (parentComment.getCommentList().isEmpty() && parentComment.getContent() == null) {
parentComment.resetPostAndSiteUserAndParentComment();
commentRepository.deleteById(parentComment.getId());
}
} else {
// 하위 댓글 있으면 value만 null로 수정한다.
comment.deprecateComment();
// 댓글인 경우
if (comment.getCommentList().isEmpty()) {
// 대댓글이 없는 경우
comment.resetPostAndSiteUserAndParentComment();
commentRepository.deleteById(commentId);
} else {
// 대댓글이 있는 경우
comment.deprecateComment();
}
}

return new CommentDeleteResponse(commentId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public enum ErrorCode {
APPLY_UPDATE_LIMIT_EXCEED(HttpStatus.BAD_REQUEST.value(), "지원 정보 수정은 " + APPLICATION_UPDATE_COUNT_LIMIT + "회까지만 가능합니다."),
CANT_APPLY_FOR_SAME_UNIVERSITY(HttpStatus.BAD_REQUEST.value(), "1, 2, 3지망에 동일한 대학교를 입력할 수 없습니다."),
CAN_NOT_CHANGE_NICKNAME_YET(HttpStatus.BAD_REQUEST.value(), "마지막 닉네임 변경으로부터 " + MIN_DAYS_BETWEEN_NICKNAME_CHANGES + "일이 지나지 않았습니다."),
PROFILE_IMAGE_NEEDED(HttpStatus.BAD_REQUEST.value(), "프로필 이미지가 필요합니다."),

// community
INVALID_POST_CATEGORY(HttpStatus.BAD_REQUEST.value(),"잘못된 카테고리명입니다."),
Expand All @@ -59,6 +60,7 @@ public enum ErrorCode {
CAN_NOT_DELETE_OR_UPDATE_QUESTION(HttpStatus.BAD_REQUEST.value(), "질문글은 수정이나 삭제할 수 없습니다."),
CAN_NOT_UPLOAD_MORE_THAN_FIVE_IMAGES(HttpStatus.BAD_REQUEST.value(), "5개 이상의 파일을 업로드할 수 없습니다."),
INVALID_COMMENT_ID(HttpStatus.BAD_REQUEST.value(), "존재하지 않는 댓글입니다."),
INVALID_COMMENT_LEVEL(HttpStatus.BAD_REQUEST.value(), "최대 대댓글까지만 작성할 수 있습니다."),
INVALID_COMMENT_ACCESS(HttpStatus.BAD_REQUEST.value(), "자신의 댓글만 제어할 수 있습니다."),
CAN_NOT_UPDATE_DEPRECATED_COMMENT(HttpStatus.BAD_REQUEST.value(),"이미 삭제된 댓글을 수정할 수 없습니다."),
INVALID_POST_LIKE(HttpStatus.BAD_REQUEST.value(), "존재하지 않는 게시글 좋아요입니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import lombok.Getter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
Expand All @@ -18,9 +19,17 @@
@DynamicInsert
public abstract class BaseEntity {

@CreatedDate
private LocalDateTime createdAt;
private ZonedDateTime createdAt;
private ZonedDateTime updatedAt;

@LastModifiedDate
private LocalDateTime updatedAt;
@PrePersist
public void onPrePersist() {
this.createdAt = ZonedDateTime.now(ZoneId.of("UTC"));
this.updatedAt = this.createdAt;
}

@PreUpdate
public void onPreUpdate() {
this.updatedAt = ZonedDateTime.now(ZoneId.of("UTC"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.example.solidconnection.entity.PostImage;
import com.example.solidconnection.post.domain.Post;

import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.stream.Collectors;

Expand All @@ -13,8 +13,8 @@ public record BoardFindPostResponse(
String content,
Long likeCount,
Integer commentCount,
LocalDateTime createdAt,
LocalDateTime updatedAt,
ZonedDateTime createdAt,
ZonedDateTime updatedAt,
String postCategory,
String url
) {
Expand Down
Loading