-
Notifications
You must be signed in to change notification settings - Fork 4
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
게시글 조기 마감 기능 구현 #115
게시글 조기 마감 기능 구현 #115
Changes from 15 commits
24057e5
e65bfab
1d93dd7
8ab5bf2
c1692e2
03fd8bd
7b5e0b7
50380e4
9b775e3
b4c9b43
e0f4990
bc66a7b
21d10f3
34e5aa7
3f0f28a
b8d8b56
82c227e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -18,6 +18,7 @@ | |||||
import jakarta.persistence.JoinColumn; | ||||||
import jakarta.persistence.ManyToOne; | ||||||
import jakarta.persistence.OneToMany; | ||||||
import java.time.Duration; | ||||||
import java.time.LocalDateTime; | ||||||
import java.util.ArrayList; | ||||||
import java.util.List; | ||||||
|
@@ -104,7 +105,7 @@ public boolean hasPostOption(final PostOption postOption) { | |||||
} | ||||||
|
||||||
public void validateWriter(final Member member) { | ||||||
if (!Objects.equals(this.member.getId(), member.getId())) { | ||||||
if (!Objects.equals(this.member, member)) { | ||||||
throw new BadRequestException(PostExceptionType.NOT_WRITER); | ||||||
} | ||||||
} | ||||||
|
@@ -124,18 +125,31 @@ public Vote makeVote(Member member, PostOption postOption) { | |||||
.build(); | ||||||
} | ||||||
|
||||||
private void validateDeadLine() { | ||||||
public void validateDeadLine() { | ||||||
if (isClosed()) { | ||||||
throw new IllegalStateException("게시글이 이미 마감되었습니다."); | ||||||
throw new BadRequestException(PostExceptionType.POST_CLOSED); | ||||||
} | ||||||
} | ||||||
|
||||||
private void validatePostOption(PostOption postOption) { | ||||||
if (!hasPostOption(postOption)) { | ||||||
throw new IllegalArgumentException("해당 게시글에서 존재하지 않는 선택지 입니다."); | ||||||
throw new BadRequestException(PostExceptionType.POST_OPTION_NOT_FOUND); | ||||||
} | ||||||
} | ||||||
|
||||||
public void validateHalfDeadLine() { | ||||||
final Duration betweenDuration = Duration.between(getCreatedAt(), this.deadline); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duration...처음 봤습니다 이런 기능이 있었군요! |
||||||
final LocalDateTime midpoint = getCreatedAt().plus(betweenDuration.dividedBy(2)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
변수명을 조금 더 명확하게 해도 좋을 것 같아요 :) |
||||||
|
||||||
if (midpoint.isAfter(LocalDateTime.now())) { | ||||||
throw new BadRequestException(PostExceptionType.POST_NOT_HALF_DEADLINE); | ||||||
} | ||||||
} | ||||||
|
||||||
public void closeEarly() { | ||||||
this.deadline = LocalDateTime.now(); | ||||||
} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
|
||||||
public void addComment(final Comment comment) { | ||||||
comments.add(comment); | ||||||
comment.setPost(this); | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,8 @@ public enum PostExceptionType implements ExceptionType { | |
POST_OPTION_NOT_FOUND(1001, "해당 게시글 투표 옵션이 존재하지 않습니다."), | ||
UNRELATED_POST_OPTION(1002, "게시글 투표 옵션이 게시글과 연관되어 있지 않습니다."), | ||
NOT_WRITER(1003, "해당 게시글 작성자가 아닙니다."), | ||
POST_CLOSED(1004, "게시글이 이미 마감되었습니다."), | ||
POST_NOT_HALF_DEADLINE(1005, "게시글이 마감 시간까지 절반의 시간 이상이 지나지 않으면 조기마감을 할 수 없습니다."), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
; | ||
|
||
private final int code; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -135,4 +135,15 @@ private String groupAgeRange(final String ageRange) { | |
return ageRange; | ||
} | ||
|
||
@Transactional | ||
public void closePostEarlyById(final Long id, final Member loginMember) { | ||
final Post post = postRepository.findById(id) | ||
.orElseThrow(() -> new IllegalArgumentException("해당 게시글은 존재하지 않습니다.")); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
위의 정보에 대한 검증이 필요해 보입니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 동의합니다 특히나 3번 검증 과정은 정책상 필수적이라는 생각이 드네요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 지금까지 예외 처리에 대한 부분은 고민하지 않고 구현을 했었는데, 이제 Exception 구조가 자리 잡혔으니 바로 적용해보도록 하겠습니다. |
||
post.validateWriter(loginMember); | ||
post.validateDeadLine(); | ||
post.validateHalfDeadLine(); | ||
post.closeEarly(); | ||
Comment on lines
+221
to
+224
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -150,4 +150,20 @@ void getVoteOptionStatistics() { | |
assertThat(result).usingRecursiveComparison().isEqualTo(response); | ||
} | ||
|
||
@Test | ||
@DisplayName("게시글을 조기 마감 합니다") | ||
void postClosedEarly() { | ||
// given | ||
long postId = 1L; | ||
|
||
// when | ||
ExtractableResponse<MockMvcResponse> response = RestAssuredMockMvc.given().log().all() | ||
.when().patch("/posts/{postId}/close", postId) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍🏻 |
||
.then().log().all() | ||
.extract(); | ||
|
||
// then | ||
assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,21 @@ | ||
package com.votogether.domain.post.entity; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatNoException; | ||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
import static org.junit.jupiter.api.Assertions.assertAll; | ||
|
||
import com.votogether.domain.category.entity.Category; | ||
import com.votogether.domain.member.entity.Member; | ||
import com.votogether.domain.post.exception.PostExceptionType; | ||
import com.votogether.exception.BadRequestException; | ||
import com.votogether.fixtures.MemberFixtures; | ||
import java.time.LocalDateTime; | ||
import java.time.temporal.ChronoUnit; | ||
import java.util.List; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.test.util.ReflectionTestUtils; | ||
|
||
class PostTest { | ||
|
||
|
@@ -29,6 +37,94 @@ void mapCategories() { | |
assertThat(actualPostCategories.getPostCategories()).hasSize(2); | ||
} | ||
|
||
@Test | ||
@DisplayName("게시글의 작성자 여부에 따라 예외를 던질 지 결정한다.") | ||
void throwExceptionIsWriter() { | ||
// given | ||
final Member writer = MemberFixtures.MALE_30.get(); | ||
ReflectionTestUtils.setField(writer, "id", 1L); | ||
|
||
final Member newMember = MemberFixtures.FEMALE_30.get(); | ||
ReflectionTestUtils.setField(newMember, "id", 2L); | ||
|
||
Post post1 = Post.builder() | ||
.member(writer) | ||
.build(); | ||
|
||
Post post2 = Post.builder() | ||
.member(writer) | ||
.build(); | ||
|
||
// when, then | ||
assertAll( | ||
() -> assertThatThrownBy(() -> post1.validateWriter(newMember)) | ||
.isInstanceOf(BadRequestException.class) | ||
.hasMessage(PostExceptionType.NOT_WRITER.getMessage()), | ||
() -> assertThatNoException() | ||
.isThrownBy(() -> post2.validateWriter(writer)) | ||
); | ||
} | ||
|
||
@Test | ||
@DisplayName("게시글의 마감 여부에 따라 예외를 던질 지 결정한다.") | ||
void throwExceptionIsDeadlinePassed() { | ||
// given | ||
final Member writer = MemberFixtures.MALE_30.get(); | ||
ReflectionTestUtils.setField(writer, "id", 1L); | ||
|
||
Post post1 = Post.builder() | ||
.member(writer) | ||
.deadline(LocalDateTime.of(2000, 1, 1, 1, 1)) | ||
.build(); | ||
|
||
Post post2 = Post.builder() | ||
.member(writer) | ||
.deadline(LocalDateTime.of(9999, 1, 1, 1, 1)) | ||
.build(); | ||
|
||
// when, then | ||
assertAll( | ||
() -> assertThatThrownBy(post1::validateDeadLine) | ||
.isInstanceOf(BadRequestException.class) | ||
.hasMessage(PostExceptionType.POST_CLOSED.getMessage()), | ||
() -> assertThatNoException() | ||
.isThrownBy(post2::validateDeadLine) | ||
); | ||
} | ||
|
||
@Test | ||
@DisplayName("게시글의 마감까지 절반의 시간을 넘겼는 지에 따라 예외를 던질 지 결정한다.") | ||
void throwExceptionIsHalfToTheDeadline() { | ||
// given | ||
final Member writer = MemberFixtures.MALE_30.get(); | ||
ReflectionTestUtils.setField(writer, "id", 1L); | ||
|
||
Post post1 = Post.builder() | ||
.member(writer) | ||
.deadline(LocalDateTime.of(9999, 1, 1, 1, 1)) | ||
.build(); | ||
ReflectionTestUtils.setField(post1, "createdAt", LocalDateTime.now()); | ||
|
||
Post post2 = Post.builder() | ||
.member(writer) | ||
.deadline(LocalDateTime.now().plus(100, ChronoUnit.MILLIS)) | ||
.build(); | ||
ReflectionTestUtils.setField(post2, "createdAt", LocalDateTime.now()); | ||
|
||
// when, then | ||
assertAll( | ||
() -> assertThatThrownBy(post1::validateHalfDeadLine) | ||
.isInstanceOf(BadRequestException.class) | ||
.hasMessage(PostExceptionType.POST_NOT_HALF_DEADLINE.getMessage()), | ||
() -> { | ||
Thread.sleep(50); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
assertThatNoException() | ||
.isThrownBy(post2::validateHalfDeadLine); | ||
|
||
} | ||
); | ||
} | ||
|
||
@Test | ||
@DisplayName("게시글의 마감 여부를 확인한다.") | ||
void isClosed() { | ||
|
@@ -52,4 +148,20 @@ void isClosed() { | |
); | ||
} | ||
|
||
@Test | ||
@DisplayName("해당 게시글을 조기 마감 합니다.") | ||
void closedEarly() { | ||
// given | ||
LocalDateTime deadline = LocalDateTime.of(2100, 1, 1, 0, 0); | ||
Post post = Post.builder() | ||
.deadline(deadline) | ||
.build(); | ||
|
||
// when | ||
post.closeEarly(); | ||
|
||
// then | ||
assertThat(post.getDeadline()).isBefore(deadline); | ||
} | ||
|
||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3
크게 중요하진 않지만 BadRequestException인데 NotFound를 던지고 있으니 개인적으로는 어색하다는 생각이 듭니다.
NonExistPostOption등의 네이밍으로 변경해보는 것은 어떨까요?