diff --git a/src/main/java/server/poptato/todo/api/TodoController.java b/src/main/java/server/poptato/todo/api/TodoController.java index 9c7b6f5..7fa02a2 100644 --- a/src/main/java/server/poptato/todo/api/TodoController.java +++ b/src/main/java/server/poptato/todo/api/TodoController.java @@ -109,4 +109,11 @@ public BaseResponse updateContent(@UserId Long userId, todoService.updateContent(userId, todoId, requestDto.getContent()); return new BaseResponse<>(); } + + @PatchMapping("/todo/{todoId}/achieve") + public BaseResponse updateIsCompleted(@UserId Long userId, + @PathVariable Long todoId){ + todoService.updateIsCompleted(userId, todoId); + return new BaseResponse<>(); + } } diff --git a/src/main/java/server/poptato/todo/application/TodoService.java b/src/main/java/server/poptato/todo/application/TodoService.java index 89bcf33..97df337 100644 --- a/src/main/java/server/poptato/todo/application/TodoService.java +++ b/src/main/java/server/poptato/todo/application/TodoService.java @@ -31,6 +31,7 @@ import static server.poptato.todo.exception.errorcode.TodoExceptionErrorCode.TODO_NOT_EXIST; +@Transactional @RequiredArgsConstructor @Service public class TodoService { @@ -81,13 +82,12 @@ public BacklogListResponseDto getBacklogList(Long userId, int page, int size) { .build(); } - @Transactional public void deleteTodoById(Long todoId) { Todo todo = todoRepository.findById(todoId) .orElseThrow(() -> new TodoException(TODO_NOT_EXIST)); todoRepository.delete(todo); } - @Transactional + public void toggleIsBookmark(Long todoId) { // 해당 Todo를 조회 Todo todo = todoRepository.findById(todoId) @@ -115,7 +115,6 @@ public PaginatedHistoryResponseDto getHistories(Long userId, int page, int size) return new PaginatedHistoryResponseDto(histories, todosPage.getTotalPages()); } - @Transactional public void swipe(Long userId, Long todoId) { checkIsExistUser(userId); Todo todo = todoRepository.findById(todoId) @@ -220,6 +219,7 @@ private void checkIsExistUser(Long userId) { -> new UserException(UserExceptionErrorCode.USER_NOT_EXIST)); } + public Long generateBacklog(Long userId, String content) { checkIsExistUser(userId); Integer maxBacklogOrder = todoRepository.findMaxBacklogOrderByUserIdOrZero(userId); @@ -263,4 +263,26 @@ public void updateContent(Long userId, Long todoId, String content) { //TODO: 여기도 왜 SAVE가 필수인지 몰겟담 todoRepository.save(findTodo); } + + public void updateIsCompleted(Long userId, Long todoId) { + checkIsExistUser(userId); + Todo findTodo = todoRepository.findById(todoId) + .orElseThrow(() -> new TodoException(TODO_NOT_EXIST)); + checkIsValidToUpdateIsCompleted(userId,findTodo); + + if(findTodo.getTodayStatus().equals(TodayStatus.COMPLETED)){ + findTodo.updateTodayStatusToInComplete(); + }else { + findTodo.updateTodayStatusToCompleted(); + } + } + + private void checkIsValidToUpdateIsCompleted(Long userId, Todo todo) { + if(todo.getUserId()!=userId) + throw new TodoException(TodoExceptionErrorCode.TODO_USER_NOT_MATCH); + if(todo.getType().equals(Type.BACKLOG)) + throw new TodoException(TodoExceptionErrorCode.BACKLOG_CANT_COMPLETE); + if(todo.getType().equals(Type.YESTERDAY) && todo.getTodayStatus().equals(TodayStatus.COMPLETED)) + throw new TodoException(TodoExceptionErrorCode.YESTERDAY_CANT_COMPLETE); + } } diff --git a/src/main/java/server/poptato/todo/application/response/BacklogResponseDto.java b/src/main/java/server/poptato/todo/application/response/BacklogResponseDto.java index 2bcbda2..13a4847 100644 --- a/src/main/java/server/poptato/todo/application/response/BacklogResponseDto.java +++ b/src/main/java/server/poptato/todo/application/response/BacklogResponseDto.java @@ -3,6 +3,7 @@ import lombok.Getter; import server.poptato.todo.domain.entity.Todo; +import java.time.LocalDate; import java.time.temporal.ChronoUnit; @Getter @@ -10,15 +11,17 @@ public class BacklogResponseDto { Long todoId; String content; boolean isBookmark; - Integer deadline; + Integer dDay; + LocalDate deadline; public BacklogResponseDto(Todo todo) { this.todoId = todo.getId(); this.content = todo.getContent(); this.isBookmark = todo.isBookmark(); + this.deadline = todo.getDeadline(); if (todo.getDeadline() != null && todo.getTodayDate() != null) { - this.deadline = (int) ChronoUnit.DAYS.between(todo.getTodayDate(), todo.getDeadline()); + this.dDay = (int) ChronoUnit.DAYS.between(todo.getTodayDate(), todo.getDeadline()); } else { // 마감 기한을 계산할 수 없는 경우 NULL this.deadline = null; diff --git a/src/main/java/server/poptato/todo/application/response/TodayResponseDto.java b/src/main/java/server/poptato/todo/application/response/TodayResponseDto.java index f34c8f0..9d6ca4a 100644 --- a/src/main/java/server/poptato/todo/application/response/TodayResponseDto.java +++ b/src/main/java/server/poptato/todo/application/response/TodayResponseDto.java @@ -4,6 +4,7 @@ import server.poptato.todo.domain.entity.Todo; import server.poptato.todo.domain.value.TodayStatus; +import java.time.LocalDate; import java.time.temporal.ChronoUnit; @Getter @@ -12,19 +13,21 @@ public class TodayResponseDto { String content; TodayStatus todayStatus; boolean isBookmark; - Integer deadline; + Integer dDay; + LocalDate deadline; public TodayResponseDto(Todo todo) { this.todoId = todo.getId(); this.content = todo.getContent(); this.todayStatus = todo.getTodayStatus(); this.isBookmark = todo.isBookmark(); + this.deadline = todo.getDeadline(); if (todo.getDeadline() != null && todo.getTodayDate() != null) { - this.deadline = (int) ChronoUnit.DAYS.between(todo.getTodayDate(), todo.getDeadline()); + this.dDay = (int) ChronoUnit.DAYS.between(todo.getTodayDate(), todo.getDeadline()); } else { // 마감 기한을 계산할 수 없는 경우 NULL - this.deadline = null; + this.dDay = null; } } } diff --git a/src/main/java/server/poptato/todo/domain/entity/Todo.java b/src/main/java/server/poptato/todo/domain/entity/Todo.java index ec25425..3c5b85c 100644 --- a/src/main/java/server/poptato/todo/domain/entity/Todo.java +++ b/src/main/java/server/poptato/todo/domain/entity/Todo.java @@ -96,4 +96,15 @@ public void updateDeadline(LocalDate deadline) { public void updateContent(String content) { this.content = content; } + + public void updateTodayStatusToInComplete() { + this.todayStatus = TodayStatus.INCOMPLETE; + this.completedDateTime = null; + } + + public void updateTodayStatusToCompleted() { + this.todayStatus = TodayStatus.COMPLETED; + this.completedDateTime = LocalDateTime.now(); + this.todayOrder = null; + } } diff --git a/src/main/java/server/poptato/todo/exception/errorcode/TodoExceptionErrorCode.java b/src/main/java/server/poptato/todo/exception/errorcode/TodoExceptionErrorCode.java index f2a9350..7915b26 100644 --- a/src/main/java/server/poptato/todo/exception/errorcode/TodoExceptionErrorCode.java +++ b/src/main/java/server/poptato/todo/exception/errorcode/TodoExceptionErrorCode.java @@ -15,7 +15,9 @@ public enum TodoExceptionErrorCode implements ResponseStatus { TODO_NOT_EXIST(5001, HttpStatus.BAD_REQUEST.value(), "투두가 존재하지 않습니다"), TODO_USER_NOT_MATCH(5002, HttpStatus.BAD_REQUEST.value(), "사용자의 할 일이 아닙니다."), ALREADY_COMPLETED_TODO(5003, HttpStatus.BAD_REQUEST.value(), "달성된 할 일은 스와이프할 수 없습니다."), - TODO_TYPE_NOT_MATCH(5004, HttpStatus.BAD_REQUEST.value(), "드래그앤드롭 시 할 일 리스트와 할 일 타입이 맞지 않습니다." ); + TODO_TYPE_NOT_MATCH(5004, HttpStatus.BAD_REQUEST.value(), "드래그앤드롭 시 할 일 리스트와 할 일 타입이 맞지 않습니다." ), + BACKLOG_CANT_COMPLETE(5005,HttpStatus.BAD_REQUEST.value(), "백로그 할 일은 달성할 수 없습니다."), + YESTERDAY_CANT_COMPLETE(5006, HttpStatus.BAD_REQUEST.value(), "이미 달성한 어제 한 일은 취소할 수 없습니다."); private final int code; diff --git a/src/test/java/server/poptato/todo/api/TodoControllerTest.java b/src/test/java/server/poptato/todo/api/TodoControllerTest.java index 5e6ea05..149b026 100644 --- a/src/test/java/server/poptato/todo/api/TodoControllerTest.java +++ b/src/test/java/server/poptato/todo/api/TodoControllerTest.java @@ -363,4 +363,18 @@ public void shouldReturnOk_WhenIsBookmarkToggled() throws Exception { .andExpect(status().isOk()) .andDo(print()); } + + @DisplayName("투데이 달성여부 변경 요청 시 성공한다.") + @Test + void 투데이_달성여부_변경_요청_성공_응답() throws Exception { + //given + Long todoId = 1L; + + //when + mockMvc.perform(patch("/todo/{todoId}/achieve", todoId) + .header("Authorization", "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(print()); + } } diff --git a/src/test/java/server/poptato/todo/application/TodoServiceTest.java b/src/test/java/server/poptato/todo/application/TodoServiceTest.java index c2283ee..480b4dc 100644 --- a/src/test/java/server/poptato/todo/application/TodoServiceTest.java +++ b/src/test/java/server/poptato/todo/application/TodoServiceTest.java @@ -18,6 +18,7 @@ import java.time.LocalDate; import java.util.List; import java.util.Optional; +import java.util.Stack; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -411,4 +412,49 @@ void getYesterdays_ShouldReturnPagedResult() { //then assertThat(findTodo.getContent()).isEqualTo(updateContent); } + + @DisplayName("투데이 달성여부 변경 시 성공한다.") + @Test + void 투데이_달성여부_변경_성공(){ + //given + Long userId = 1L; + Long todoId = 1L; + + //when + todoService.updateIsCompleted(userId,todoId); + Todo findTodo = todoRepository.findById(todoId).get(); + + //then + assertThat(findTodo.getTodayStatus()).isEqualTo(TodayStatus.COMPLETED); + assertThat(findTodo.getCompletedDateTime()).isNotNull(); + } + + @DisplayName("어제한일 달성여부 변경 시 성공한다.") + @Test + void 어제한일_달성여부_변경_성공(){ + //given + Long userId = 1L; + Long todoId = 35L; + + //when + todoService.updateIsCompleted(userId,todoId); + Todo findTodo = todoRepository.findById(todoId).get(); + + //then + assertThat(findTodo.getTodayStatus()).isEqualTo(TodayStatus.COMPLETED); + assertThat(findTodo.getCompletedDateTime()).isNotNull(); + } + + @DisplayName("백로그 달성여부 변경 시 예외가 발생한다.") + @Test + void 백로그_달성여부_변경_예외(){ + //given + Long userId = 1L; + Long todoId = 20L; + + //when & then + assertThatThrownBy(()-> todoService.updateIsCompleted(userId,todoId)) + .isInstanceOf(TodoException.class) + .hasMessage(TodoExceptionErrorCode.BACKLOG_CANT_COMPLETE.getMessage()); + } } \ No newline at end of file diff --git a/src/test/java/server/poptato/todo/application/response/TodayResponseDtoTest.java b/src/test/java/server/poptato/todo/application/response/TodayResponseDtoTest.java index 7e3177a..6480505 100644 --- a/src/test/java/server/poptato/todo/application/response/TodayResponseDtoTest.java +++ b/src/test/java/server/poptato/todo/application/response/TodayResponseDtoTest.java @@ -15,7 +15,7 @@ class TodayResponseDtoTest { void 마감기한이_정상적으로_계산된다() { //given Todo todo = Todo.builder() - .id(1L) + .id(1000L) .content("Test Todo") .todayStatus(TodayStatus.COMPLETED) .isBookmark(false) @@ -27,7 +27,7 @@ class TodayResponseDtoTest { TodayResponseDto responseDto = new TodayResponseDto(todo); //then - assertThat(responseDto.getDeadline()).isEqualTo(4); + assertThat(responseDto.getDDay()).isEqualTo(4); } @DisplayName("마감이 설정안되어있는 경우 NULL로 정상 응답된다.")