diff --git a/src/main/java/codesquad/domain/Answer.java b/src/main/java/codesquad/domain/Answer.java index 461a781..36451b2 100644 --- a/src/main/java/codesquad/domain/Answer.java +++ b/src/main/java/codesquad/domain/Answer.java @@ -6,6 +6,7 @@ import javax.persistence.*; import javax.validation.constraints.Size; +import java.time.LocalDateTime; @Entity public class Answer extends AbstractEntity implements UrlGeneratable { @@ -75,11 +76,12 @@ public void updateContents(User loginUser, String updatedContents) { this.contents = updatedContents; } - public void delete(User loginUser) { + public DeleteHistory delete(User loginUser) { if (!isOwner(loginUser)) { throw new UnAuthorizedException(); } this.deleted = true; + return new DeleteHistory(ContentType.ANSWER, this.getId(), loginUser, LocalDateTime.now()); } @Override diff --git a/src/main/java/codesquad/domain/Question.java b/src/main/java/codesquad/domain/Question.java index a8ed2c5..9edfe26 100644 --- a/src/main/java/codesquad/domain/Question.java +++ b/src/main/java/codesquad/domain/Question.java @@ -1,5 +1,6 @@ package codesquad.domain; +import codesquad.CannotDeleteException; import org.hibernate.annotations.Where; import support.domain.AbstractEntity; import support.domain.UrlGeneratable; @@ -9,6 +10,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; @Entity public class Question extends AbstractEntity implements UrlGeneratable { @@ -86,8 +88,25 @@ public void update(Question updatedQuestion) { this.writer = updatedQuestion.writer; } - public void delete() { + public List delete(User loginUser) throws CannotDeleteException { + + if (!this.isOwner(loginUser)) { + throw new CannotDeleteException("삭제 권한이 없습니다."); + } + + if(!hasSameWriterWithAnswers()) { + throw new CannotDeleteException("삭제 권한이 없습니다."); + } + + List deleteHistories = new ArrayList<>(); + + answers.stream() + .filter(answer -> answer.isOwner(writer)) + .forEach(answer -> deleteHistories.add(answer.delete(loginUser))); + this.deleted = true; + + return deleteHistories; } @Override @@ -108,4 +127,9 @@ public boolean equalsTitleAndContents(Question target) { return this.title.equals(target.getTitle()) && this.contents.equals(target.getContents()); } + + public boolean hasSameWriterWithAnswers() { + return answers.stream() + .allMatch(answer -> answer.isOwner(writer)); + } } diff --git a/src/main/java/codesquad/service/DeleteHistoryService.java b/src/main/java/codesquad/service/DeleteHistoryService.java index 772c798..a656817 100644 --- a/src/main/java/codesquad/service/DeleteHistoryService.java +++ b/src/main/java/codesquad/service/DeleteHistoryService.java @@ -20,4 +20,9 @@ public void saveAll(List deleteHistories) { deleteHistoryRepository.save(deleteHistory); } } + + @Transactional + public void save(DeleteHistory deleteHistory) { + deleteHistoryRepository.save(deleteHistory); + } } diff --git a/src/main/java/codesquad/service/QnaService.java b/src/main/java/codesquad/service/QnaService.java index 8052e36..2ea941a 100644 --- a/src/main/java/codesquad/service/QnaService.java +++ b/src/main/java/codesquad/service/QnaService.java @@ -55,14 +55,9 @@ public Question update(User loginUser, long id, Question updatedQuestion) throws @Transactional public Question deleteQuestion(User loginUser, long questionId) throws CannotDeleteException { - // TODO 삭제 기능 구현 Question savedQuestion = findById(questionId); - if (!savedQuestion.isOwner(loginUser)) { - throw new CannotDeleteException("삭제 권한이 없습니다."); - } - - savedQuestion.delete(); + deleteHistoryService.saveAll(savedQuestion.delete(loginUser)); return questionRepository.save(savedQuestion); } @@ -92,7 +87,7 @@ public Answer updateAnswer(User loginUser, long id, String updatedContents) { @Transactional public Answer deleteAnswer(User loginUser, long id) { Answer answer = findAnswerById(id); - answer.delete(loginUser); + deleteHistoryService.save(answer.delete(loginUser)); return answerRepository.save(answer); } } diff --git a/src/test/java/codesquad/domain/QuestionTest.java b/src/test/java/codesquad/domain/QuestionTest.java index 8bff5ae..fcb3562 100644 --- a/src/test/java/codesquad/domain/QuestionTest.java +++ b/src/test/java/codesquad/domain/QuestionTest.java @@ -1,5 +1,7 @@ package codesquad.domain; +import codesquad.CannotDeleteException; +import codesquad.CannotDeleteException; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -39,12 +41,45 @@ public void update() { } @Test - public void delete() { + public void delete() throws CannotDeleteException { User loginUser = UserTest.JAVAJIGI; Question question = newQuestion(1L, loginUser); - question.delete(); + question.delete(loginUser); assertThat(question.isDeleted()).isTrue(); } + + @Test(expected = CannotDeleteException.class) + public void delete_fail_when_loginUser_mismatch_writer() throws CannotDeleteException { + User loginUser = UserTest.JAVAJIGI; + User otherUser = UserTest.SANJIGI; + Question question = newQuestion(1L, loginUser); + + question.delete(otherUser); + } + + @Test + public void delete_success_when_loginUser_is_writer_correspond_to_answers() throws CannotDeleteException { + User loginUser = UserTest.JAVAJIGI; + Question question = newQuestion(1L, loginUser); + question.addAnswer(new Answer(loginUser, "하이")); + + assertThat(question.hasSameWriterWithAnswers()).isTrue(); + + question.delete(loginUser); + assertThat(question.isDeleted()).isTrue(); + } + + @Test(expected = CannotDeleteException.class) + public void delete_fail_when_loginUser_is_not_writer_correspond_to_answers() throws CannotDeleteException { + User loginUser = UserTest.JAVAJIGI; + User otherUser = UserTest.SANJIGI; + Question question = newQuestion(1L, loginUser); + question.addAnswer(new Answer(otherUser, "하이")); + + assertThat(question.hasSameWriterWithAnswers()).isFalse(); + + question.delete(loginUser); + } } diff --git a/src/test/java/codesquad/web/ApiQuestionAcceptanceTest.java b/src/test/java/codesquad/web/ApiQuestionAcceptanceTest.java index b79dad8..beaf285 100644 --- a/src/test/java/codesquad/web/ApiQuestionAcceptanceTest.java +++ b/src/test/java/codesquad/web/ApiQuestionAcceptanceTest.java @@ -19,11 +19,6 @@ public class ApiQuestionAcceptanceTest extends AcceptanceTest { private Question newQuestion; - @Before - public void setUp() throws Exception { - newQuestion = defaultQuestion(); - } - @Test public void create() { Question newQuestion = defaultQuestion(); @@ -68,7 +63,7 @@ public void update() { } @Test - public void delete() { + public void delete_success() { String location = createResource(DEFAULT_QUESTION_URL, newQuestion); basicAuthTemplate().delete(location); @@ -77,6 +72,16 @@ public void delete() { assertThat(dbQuestion.isDeleted()).isTrue(); } + @Test + public void delete_fail() { + String location = createResource(DEFAULT_QUESTION_URL, newQuestion); + + template().delete(location); + + Question dbQuestion = getResource(location, Question.class); + assertThat(dbQuestion.isDeleted()).isFalse(); + } + @Test public void delete_다른_사람() { String location = createResource(DEFAULT_QUESTION_URL, newQuestion); diff --git a/src/test/java/codesquad/web/QuestionAcceptanceTest.java b/src/test/java/codesquad/web/QuestionAcceptanceTest.java index e1d21b6..3cee27f 100644 --- a/src/test/java/codesquad/web/QuestionAcceptanceTest.java +++ b/src/test/java/codesquad/web/QuestionAcceptanceTest.java @@ -92,7 +92,6 @@ public void update_with_login() { ResponseEntity response = basicAuthTemplate().postForEntity(String.format("/questions/%d", defaultQuestion().getId()), request, String.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FOUND); - assertThat(response.getHeaders().getLocation().getPath()).startsWith("/questions"); } @Test