Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/com/codeit/todo/repository/TodoRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ public interface TodoRepository extends JpaRepository<Todo, Integer> {

@Query("select t from Todo t where t.goal.goalId = :goalId and :today between t.startDate and t.endDate")
List<Todo> findTodosByGoalIdBetweenDates(@Param("goalId") int goalId, @Param("today") LocalDate today);

List<Todo> findByGoal_GoalId(int goalId);
}
2 changes: 2 additions & 0 deletions src/main/java/com/codeit/todo/service/goal/GoalService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.codeit.todo.web.dto.response.goal.CreateGoalResponse;
import com.codeit.todo.web.dto.response.goal.ReadGoalsResponse;
import com.codeit.todo.web.dto.response.goal.UpdateGoalResponse;
import com.codeit.todo.web.dto.response.todo.ReadTodosWithGoalsResponse;

import java.util.List;

Expand All @@ -20,4 +21,5 @@ public interface GoalService {
DeleteGoalResponse deleteGoal(int userId, int goalId);


List<ReadTodosWithGoalsResponse> findAllGoals(int userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,26 @@

import com.codeit.todo.common.exception.goal.GoalNotFoundException;
import com.codeit.todo.common.exception.user.UserNotFoundException;
import com.codeit.todo.domain.Complete;
import com.codeit.todo.domain.Goal;
import com.codeit.todo.domain.Todo;
import com.codeit.todo.domain.User;
import com.codeit.todo.repository.CompleteRepository;
import com.codeit.todo.repository.GoalRepository;
import com.codeit.todo.repository.TodoRepository;
import com.codeit.todo.repository.UserRepository;
import com.codeit.todo.service.goal.GoalService;
import com.codeit.todo.service.todo.TodoService;
import com.codeit.todo.service.todo.impl.TodoServiceImpl;
import com.codeit.todo.web.dto.response.complete.ReadCompleteResponse;
import com.codeit.todo.web.dto.response.goal.DeleteGoalResponse;
import com.codeit.todo.web.dto.request.goal.UpdateGoalRequest;
import com.codeit.todo.web.dto.request.goal.CreateGoalRequest;
import com.codeit.todo.web.dto.response.goal.CreateGoalResponse;
import com.codeit.todo.web.dto.response.goal.ReadGoalsResponse;
import com.codeit.todo.web.dto.response.goal.UpdateGoalResponse;
import com.codeit.todo.web.dto.response.todo.ReadTodosResponse;
import com.codeit.todo.web.dto.response.todo.ReadTodosWithGoalsResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -28,6 +37,9 @@ public class GoalServiceImpl implements GoalService {

private final UserRepository userRepository;
private final GoalRepository goalRepository;
private final TodoRepository todoRepository;
private final CompleteRepository completeRepository;
private final TodoServiceImpl todoServiceImpl;


@Override
Expand Down Expand Up @@ -86,4 +98,21 @@ public DeleteGoalResponse deleteGoal(int userId, int goalId) {
goalRepository.delete(goal);
return new DeleteGoalResponse(goalId);
}

@Override
public List<ReadTodosWithGoalsResponse> findAllGoals(int userId) {
List<Goal> goals = goalRepository.findByUser_UserId(userId);
List<ReadTodosWithGoalsResponse> goalsResponses = goals.stream()
.map(goal -> {
List<Todo> todos = todoRepository.findByGoal_GoalId(goal.getGoalId());

List<ReadTodosResponse> todosResponses = todoServiceImpl.makeTodosResponses(todos);

double goalProgress = todoServiceImpl.calculateGoalProgress(todos);

return ReadTodosWithGoalsResponse.from(goal, todosResponses, goalProgress);
}).toList();

return goalsResponses;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,7 @@ public Slice<ReadTodosWithGoalsResponse> findTodoListWithGoals(int userId, @Vali
.map(goal -> {
List<Todo> todos = todoRepository.findTodosByGoalIdBetweenDates(goal.getGoalId(), LocalDate.now());

List<ReadTodosResponse> todosResponses = todos.stream()
.map(todo -> {
List<Complete> completes = completeRepository.findByTodo_TodoId(todo.getTodoId());

List<ReadCompleteResponse> completeResponses = completes.stream()
.map(ReadCompleteResponse::from)
.toList();

return ReadTodosResponse.from(todo, completeResponses);
}).toList();
List<ReadTodosResponse> todosResponses = makeTodosResponses(todos);

double goalProgress = calculateGoalProgress(todos);

Expand Down Expand Up @@ -268,7 +259,7 @@ private List<ReadTodosResponse> getTodoResponses(Slice<Todo> todos) {
}).toList();
}

private double calculateGoalProgress(List<Todo> todos) {
public double calculateGoalProgress(List<Todo> todos) {
long totalCompletes = 0;
long completedCompletes = 0;

Expand All @@ -282,4 +273,19 @@ private double calculateGoalProgress(List<Todo> todos) {

return totalCompletes > 0 ? (completedCompletes / (double) totalCompletes) * 100 : 0;
}

public List<ReadTodosResponse> makeTodosResponses(List<Todo> todos){
List<ReadTodosResponse> todosResponses = todos.stream()
.map(todo -> {
List<Complete> completes = completeRepository.findByTodo_TodoId(todo.getTodoId());

List<ReadCompleteResponse> completeResponses = completes.stream()
.map(ReadCompleteResponse::from)
.toList();

return ReadTodosResponse.from(todo, completeResponses);
}).toList();

return todosResponses;
}
}
15 changes: 15 additions & 0 deletions src/main/java/com/codeit/todo/web/controller/GoalController.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.codeit.todo.web.dto.response.goal.CreateGoalResponse;
import com.codeit.todo.web.dto.response.goal.ReadGoalsResponse;
import com.codeit.todo.web.dto.response.goal.UpdateGoalResponse;
import com.codeit.todo.web.dto.response.todo.ReadTodosWithGoalsResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
Expand Down Expand Up @@ -83,4 +84,18 @@ public Response<DeleteGoalResponse> deleteGoal(
return Response.ok(goalService.deleteGoal(userId, goalId));
}

@Transactional
Copy link
Member

@bbbbooo bbbbooo Dec 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

소희님은 컨트롤러에 @Transactional 많이 쓰시나요? 이 글 참고해보시면 좋을 것 같습니다!

저는 서비스 클래스에 @Transactional 붙이고 조회하는 메소드는 readOnly = true 옵션을 활성화해요.

@Transactional
public class TodoServiceImpl implements TodoService {

    private static final String COMPLETE = "인증";

    private final TodoRepository todoRepository;
    private final GoalRepository goalRepository;
    private final CompleteRepository completeRepository;

    private final StorageService storageService;

    @Transactional(readOnly = true)
    @Override
    public Slice<ReadTodosResponse> findTodoList(int userId, ReadTodoRequest request) {
        List<Goal> goals = goalRepository.findByUser_UserId(userId);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

감사합니다~ 서비스 클래스로 옮겨두었습니다.

@Operation(
summary = "목표와 할 일, 인증 상세조회",
description = "종료된 할 일 또는 인증도 포함해서 목표, 할 일, 인증을 모두 불러옵니다."
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "조회 성공")
})
@GetMapping("/all")
public Response<List<ReadTodosWithGoalsResponse>> getGoalsDetail(@AuthenticationPrincipal CustomUserDetails userDetails) {
int userId = userDetails.getUserId();
return Response.ok(goalService.findAllGoals(userId));
}

}
Loading