Skip to content

Commit

Permalink
Merge pull request #64 from solid-connection/main
Browse files Browse the repository at this point in the history
[RELEASE]댓글, 게시글 좋아요 기능, 지원서 3차 지망 대학
  • Loading branch information
wibaek authored Aug 19, 2024
2 parents 50b6702 + 61bd393 commit ce1026e
Show file tree
Hide file tree
Showing 45 changed files with 1,715 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ public class Application {
@ManyToOne
private UniversityInfoForApply secondChoiceUniversity;

@ManyToOne
private UniversityInfoForApply thirdChoiceUniversity;

@ManyToOne
private SiteUser siteUser;

Expand All @@ -77,12 +80,14 @@ public void updateGpaAndLanguageTest(
public void updateUniversityChoice(
UniversityInfoForApply firstChoiceUniversity,
UniversityInfoForApply secondChoiceUniversity,
UniversityInfoForApply thirdChoiceUniversity,
String nicknameForApply) {
if (this.firstChoiceUniversity != null) {
this.updateCount++;
}
this.firstChoiceUniversity = firstChoiceUniversity;
this.secondChoiceUniversity = secondChoiceUniversity;
this.thirdChoiceUniversity = thirdChoiceUniversity;
this.nicknameForApply = nicknameForApply;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@ public record ApplicationsResponse(
List<UniversityApplicantsResponse> firstChoice,

@ArraySchema(arraySchema = @Schema(description = "2지망 대학에 지원한 지원자 목록"))
List<UniversityApplicantsResponse> secondChoice) {
List<UniversityApplicantsResponse> secondChoice,

@ArraySchema(arraySchema = @Schema(description = "3지망 대학에 지원한 지원자 목록"))
List<UniversityApplicantsResponse> thirdChoice) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ public record UniversityChoiceRequest(
Long firstChoiceUniversityId,

@Schema(description = "2지망 대학교의 지원 정보 ID (선택사항)", example = "2", nullable = true)
Long secondChoiceUniversityId) {
}
Long secondChoiceUniversityId,

@Schema(description = "3지망 대학교의 지원 정보 ID (선택사항)", example = "3", nullable = true)
Long thirdChoiceUniversityId) {}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public interface ApplicationRepository extends JpaRepository<Application, Long>

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

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

default Application getApplicationBySiteUser(SiteUser siteUser) {
return findBySiteUser(siteUser)
.orElseThrow(() -> new CustomException(APPLICATION_NOT_FOUND));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ public ApplicationsResponse getApplicants(String email, String regionCode, Strin
// 1지망, 2지망 지원자들을 조회한다.
List<UniversityApplicantsResponse> firstChoiceApplicants = getFirstChoiceApplicants(universities, siteUser);
List<UniversityApplicantsResponse> secondChoiceApplicants = getSecondChoiceApplicants(universities, siteUser);
return new ApplicationsResponse(firstChoiceApplicants, secondChoiceApplicants);
List <UniversityApplicantsResponse> thirdChoiceApplicants = getThirdChoiceApplicants(universities, siteUser);
return new ApplicationsResponse(firstChoiceApplicants, secondChoiceApplicants, thirdChoiceApplicants);
}

private void validateSiteUserCanViewApplicants(SiteUser siteUser) {
Expand All @@ -81,6 +82,14 @@ private List<UniversityApplicantsResponse> getSecondChoiceApplicants(List<Univer
);
}

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

private List<UniversityApplicantsResponse> getApplicantsByChoice(
List<University> searchedUniversities,
SiteUser siteUser,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +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 static com.example.solidconnection.custom.exception.ErrorCode.APPLY_UPDATE_LIMIT_EXCEED;
import static com.example.solidconnection.custom.exception.ErrorCode.CANT_APPLY_FOR_SAME_UNIVERSITY;
Expand Down Expand Up @@ -61,7 +63,7 @@ public boolean submitScore(String email, ScoreRequest scoreRequest) {

/*
* 지망 대학교를 제출한다.
* - 첫번째 지망과 두번째 지망이 같은지 검증한다.
* - 지망 대학중 중복된 대학교가 있는지 검증한다.
* - 지원 정보 제출 내역이 없다면, 지금의 프로세스(성적 제출 후 지망대학 제출)에 벗어나는 요청이므로 예외를 응답한다.
* - 기존에 제출한 적이 있다면, 수정한다.
* - 수정 횟수 제한을 초과하지 않았는지 검증한다.
Expand All @@ -70,17 +72,19 @@ public boolean submitScore(String email, ScoreRequest scoreRequest) {
* */
@Transactional
public boolean submitUniversityChoice(String email, UniversityChoiceRequest universityChoiceRequest) {
validateFirstAndSecondChoiceIdDifferent(universityChoiceRequest);
validateNoDuplicateUniversityChoices(universityChoiceRequest);
Application application = applicationRepository.findBySiteUser_Email(email)
.orElseThrow(() -> new CustomException(SCORE_SHOULD_SUBMITTED_FIRST));

UniversityInfoForApply firstChoiceUniversity = universityInfoForApplyRepository
.getUniversityInfoForApplyByIdAndTerm(universityChoiceRequest.firstChoiceUniversityId(), term);
UniversityInfoForApply secondChoiceUniversity = universityInfoForApplyRepository
.getUniversityInfoForApplyByIdAndTerm(universityChoiceRequest.secondChoiceUniversityId(), term);
UniversityInfoForApply thirdChoiceUniversity = universityInfoForApplyRepository
.getUniversityInfoForApplyByIdAndTerm(universityChoiceRequest.thirdChoiceUniversityId(), term);

validateUpdateLimitNotExceed(application);
application.updateUniversityChoice(firstChoiceUniversity, secondChoiceUniversity, getRandomNickname());
application.updateUniversityChoice(firstChoiceUniversity, secondChoiceUniversity, thirdChoiceUniversity, getRandomNickname());
return true;
}

Expand All @@ -98,10 +102,14 @@ private void validateUpdateLimitNotExceed(Application application) {
}
}

private void validateFirstAndSecondChoiceIdDifferent(UniversityChoiceRequest universityChoiceRequest) {
if (Objects.equals(
universityChoiceRequest.firstChoiceUniversityId(),
universityChoiceRequest.secondChoiceUniversityId())) {
private void validateNoDuplicateUniversityChoices(UniversityChoiceRequest universityChoiceRequest) {
Set<Long> uniqueUniversityIds = new HashSet<>();

uniqueUniversityIds.add(universityChoiceRequest.firstChoiceUniversityId());
uniqueUniversityIds.add(universityChoiceRequest.secondChoiceUniversityId());
uniqueUniversityIds.add(universityChoiceRequest.thirdChoiceUniversityId());

if (uniqueUniversityIds.size() < 3) {
throw new CustomException(CANT_APPLY_FOR_SAME_UNIVERSITY);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@
import com.example.solidconnection.type.BoardCode;
import com.example.solidconnection.type.PostCategory;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.EnumUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

import static com.example.solidconnection.custom.exception.ErrorCode.INVALID_POST_CATEGORY;

@Service
@RequiredArgsConstructor
public class BoardService {
Expand All @@ -28,12 +31,11 @@ private String validateCode(String code) {
}
}

private PostCategory validatePostCategory(String postCategory) {
try {
return PostCategory.valueOf(postCategory);
} catch (IllegalArgumentException ex) {
throw new CustomException(ErrorCode.INVALID_POST_CATEGORY);
private PostCategory validatePostCategory(String category){
if(!EnumUtils.isValidEnum(PostCategory.class, category)){
throw new CustomException(INVALID_POST_CATEGORY);
}
return PostCategory.valueOf(category);
}

@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.example.solidconnection.comment.controller;

import com.example.solidconnection.comment.dto.*;
import com.example.solidconnection.comment.service.CommentService;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityRequirements;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;

import static com.example.solidconnection.config.swagger.SwaggerConfig.ACCESS_TOKEN;

@RestController
@RequiredArgsConstructor
@RequestMapping("/posts")
@SecurityRequirements
@SecurityRequirement(name = ACCESS_TOKEN)
public class CommentController {

private final CommentService commentService;

@PostMapping("/{post_id}/comments")
public ResponseEntity<?> createComment(
Principal principal,
@PathVariable("post_id") Long postId,
@Valid @RequestBody CommentCreateRequest commentCreateRequest
) {

CommentCreateResponse commentCreateResponse = commentService.createComment(
principal.getName(), postId, commentCreateRequest);
return ResponseEntity.ok().body(commentCreateResponse);
}

@PatchMapping("/{post_id}/comments/{comment_id}")
public ResponseEntity<?> updateComment(
Principal principal,
@PathVariable("post_id") Long postId,
@PathVariable("comment_id") Long commentId,
@Valid @RequestBody CommentUpdateRequest commentUpdateRequest
) {

CommentUpdateResponse commentUpdateResponse = commentService.updateComment(
principal.getName(), postId, commentId, commentUpdateRequest
);
return ResponseEntity.ok().body(commentUpdateResponse);
}

@DeleteMapping("/{post_id}/comments/{comment_id}")
public ResponseEntity<?> deleteCommentById(
Principal principal,
@PathVariable("post_id") Long postId,
@PathVariable("comment_id") Long commentId
) {

CommentDeleteResponse commentDeleteResponse = commentService.deleteCommentById(principal.getName(), postId, commentId);
return ResponseEntity.ok().body(commentDeleteResponse);
}

}
111 changes: 111 additions & 0 deletions src/main/java/com/example/solidconnection/comment/domain/Comment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package com.example.solidconnection.comment.domain;

import com.example.solidconnection.entity.common.BaseEntity;
import com.example.solidconnection.post.domain.Post;
import com.example.solidconnection.siteuser.domain.SiteUser;
import jakarta.persistence.*;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor
@EqualsAndHashCode(of = "id")
public class Comment extends BaseEntity {

// for recursive query
@Transient
private int level;

@Transient
private String path;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(length = 255)
private String content;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id")
private Post post;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "site_user_id")
private SiteUser siteUser;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
private Comment parentComment;

@OneToMany(mappedBy = "parentComment", cascade = CascadeType.ALL)
private List<Comment> commentList = new ArrayList<>();

public Comment(String content) {
this.content = content;
}

public void setParentCommentAndPostAndSiteUser(Comment parentComment, Post post, SiteUser siteUser) {

if (this.parentComment != null) {
this.parentComment.getCommentList().remove(this);
}
this.parentComment = parentComment;
parentComment.getCommentList().add(this);

if (this.post != null) {
this.post.getCommentList().remove(this);
}
this.post = post;
post.getCommentList().add(this);

if (this.siteUser != null) {
this.siteUser.getCommentList().remove(this);
}
this.siteUser = siteUser;
siteUser.getCommentList().add(this);
}

public void setPostAndSiteUser(Post post, SiteUser siteUser) {

if (this.post != null) {
this.post.getCommentList().remove(this);
}
this.post = post;
post.getCommentList().add(this);

if (this.siteUser != null) {
this.siteUser.getCommentList().remove(this);
}
this.siteUser = siteUser;
siteUser.getCommentList().add(this);
}

public void resetPostAndSiteUserAndParentComment() {
if (this.post != null) {
this.post.getCommentList().remove(this);
this.post = null;
}
if (this.siteUser != null) {
this.siteUser.getCommentList().remove(this);
this.siteUser = null;
}
if (this.parentComment != null) {
this.parentComment.getCommentList().remove(this);
this.parentComment = null;
}
}

public void updateContent(String content) {
this.content = content;
}

public void deprecateComment() {
this.content = null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.solidconnection.comment.dto;

import com.example.solidconnection.comment.domain.Comment;
import com.example.solidconnection.post.domain.Post;
import com.example.solidconnection.siteuser.domain.SiteUser;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public record CommentCreateRequest(
@NotBlank(message = "댓글 내용은 빈 값일 수 없습니다.")
@Size(min = 1, max = 255, message = "댓글 내용은 최소 1자 이상, 최대 255자 이하여야 합니다.")
String content,
Long parentId
) {
public Comment toEntity(SiteUser siteUser, Post post, Comment parentComment) {

Comment comment = new Comment(
this.content
);

if (parentComment == null) {
comment.setPostAndSiteUser(post, siteUser);
} else {
comment.setParentCommentAndPostAndSiteUser(parentComment, post, siteUser);
}
return comment;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.solidconnection.comment.dto;

import com.example.solidconnection.comment.domain.Comment;

public record CommentCreateResponse(
Long id
) {

public static CommentCreateResponse from(Comment comment) {
return new CommentCreateResponse(
comment.getId()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.example.solidconnection.comment.dto;

public record CommentDeleteResponse(
Long id
) {
}
Loading

0 comments on commit ce1026e

Please sign in to comment.