Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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);
}
4 changes: 4 additions & 0 deletions src/main/java/com/codeit/todo/service/goal/GoalService.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.codeit.todo.service.goal;

import com.codeit.todo.web.dto.request.todo.ReadTodoCompleteWithGoalRequest;
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.ReadTodosWithGoalsResponse;
import org.springframework.data.domain.Slice;

import java.util.List;

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


Slice<ReadTodosWithGoalsResponse> findAllGoals(int userId, ReadTodoCompleteWithGoalRequest request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,34 @@
import com.codeit.todo.common.exception.goal.GoalNotFoundException;
import com.codeit.todo.common.exception.user.UserNotFoundException;
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.impl.TodoServiceImpl;
import com.codeit.todo.web.dto.request.todo.ReadTodoCompleteWithGoalRequest;
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.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;

Expand All @@ -28,6 +41,8 @@ public class GoalServiceImpl implements GoalService {

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


@Override
Expand Down Expand Up @@ -67,6 +82,7 @@ public CreateGoalResponse saveGoal(int userId, CreateGoalRequest request) {
return CreateGoalResponse.fromEntity(savedGoal);
}

@Transactional
@Override
public UpdateGoalResponse updateGoal(int userId, int goalId, UpdateGoalRequest request) {
Goal goal = goalRepository.findByGoalIdAndUser_UserId(goalId, userId)
Expand All @@ -86,4 +102,50 @@ public DeleteGoalResponse deleteGoal(int userId, int goalId) {
goalRepository.delete(goal);
return new DeleteGoalResponse(goalId);
}

@Transactional(readOnly = true)
@Override
public Slice<ReadTodosWithGoalsResponse> findAllGoals(int userId, ReadTodoCompleteWithGoalRequest request) {
int pageSize = request.size();
Pageable pageable = PageRequest.of(0, pageSize);

Slice<Goal> goals = todoServiceImpl.getGoalsPagination(userId, request, pageable);

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();

List<ReadTodosWithGoalsResponse> sortedGoalsResponses = sortAllGoals(goalsResponses);

return new SliceImpl<>(sortedGoalsResponses, pageable, goals.hasNext());
}

private List<ReadTodosWithGoalsResponse> sortAllGoals(List<ReadTodosWithGoalsResponse> goalsResponses){
List<ReadTodosWithGoalsResponse> sortedGoalsResponses = new ArrayList<>();

//todo status "진행"
List<ReadTodosWithGoalsResponse> goalsWithPriority = goalsResponses.stream()
.filter( goalResponse -> goalResponse.todos().stream()
.anyMatch(todo -> "진행".equals(todo.todoStatus())))
.toList();

//todo status not "진행"
List<ReadTodosWithGoalsResponse> goalsWithoutPriority = goalsResponses.stream()
.filter( goalResponse -> goalResponse.todos().stream()
.noneMatch(todo -> "진행".equals(todo.todoStatus())))
.toList();
//combine two lists
sortedGoalsResponses.addAll(goalsWithPriority);
sortedGoalsResponses.addAll(goalsWithoutPriority);

return sortedGoalsResponses;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public interface TodoService {

CreateTodoResponse saveTodo(int userId, CreateTodoRequest request);

Slice<ReadTodosWithGoalsResponse> findTodoListWithGoals(int userId, ReadDashBoardTodoWithGoalRequest request);
Slice<ReadTodosWithGoalsResponse> findTodoListWithGoals(int userId, ReadTodoCompleteWithGoalRequest request);

Slice<ReadTodoWithGoalResponse> findTodoListWithGoal(int userId, int goalId, ReadTodoWithGoalRequest request);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,31 +106,17 @@ public CreateTodoResponse saveTodo(int userId, CreateTodoRequest request) {

@Transactional(readOnly = true)
@Override
public Slice<ReadTodosWithGoalsResponse> findTodoListWithGoals(int userId, @Valid ReadDashBoardTodoWithGoalRequest request) {
public Slice<ReadTodosWithGoalsResponse> findTodoListWithGoals(int userId, @Valid ReadTodoCompleteWithGoalRequest request) {
int pageSize = request.size();
Pageable pageable = PageRequest.of(0, pageSize);

Slice<Goal> goals;
if (Objects.isNull(request.lastGoalId()) || request.lastGoalId() <= 0) {
goals = goalRepository.findByUser_UserId(userId, pageable);
} else {
goals = goalRepository.findByGoalIdAndUser_UserId(request.lastGoalId(), userId, pageable);
}
Slice<Goal> goals = getGoalsPagination(userId, request, pageable);

List<ReadTodosWithGoalsResponse> responses = goals.getContent().stream()
.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 +254,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 +268,30 @@ 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;
}

public Slice<Goal> getGoalsPagination(int userId, ReadTodoCompleteWithGoalRequest request, Pageable pageable){
Slice<Goal> goals;
if (Objects.isNull(request.lastGoalId()) || request.lastGoalId() <= 0) {
goals = goalRepository.findByUser_UserId(userId, pageable);
} else {
goals = goalRepository.findByGoalIdAndUser_UserId(request.lastGoalId(), userId, pageable);
}

return goals;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.security.SignatureException;
import java.time.LocalDateTime;
Expand All @@ -40,6 +41,7 @@ public class UserServiceImpl implements UserService {

private static final int BAD_REQUEST = 400;

@Transactional
@Override
public SignUpResponse signUpUser(SignUpRequest request) {
//기존에 있는 이메일인지 확인
Expand Down Expand Up @@ -94,6 +96,7 @@ public ReadUserResponse findUserInfo(int userId) {
return ReadUserResponse.from(user);
}

@Transactional
@Override
public UpdatePictureResponse updateProfilePicture(int userId, UpdatePictureRequest pictureRequest) {
User user = getUser(userId);
Expand Down
11 changes: 2 additions & 9 deletions src/main/java/com/codeit/todo/web/controller/AuthController.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,15 @@
import com.codeit.todo.web.dto.request.auth.LoginRequest;
import com.codeit.todo.web.dto.request.auth.SignUpRequest;
import com.codeit.todo.web.dto.request.auth.UpdatePictureRequest;
import com.codeit.todo.web.dto.request.complete.UpdateCompleteRequest;
import com.codeit.todo.web.dto.response.Response;
import com.codeit.todo.web.dto.response.auth.ReadUserResponse;
import com.codeit.todo.web.dto.response.auth.UpdatePictureResponse;
import com.codeit.todo.web.dto.response.complete.UpdateCompleteResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

@RestController
Expand All @@ -33,7 +26,7 @@ public class AuthController {
private final JwtTokenProvider jwtTokenProvider;


@Transactional

@Operation(summary = "회원가입", description = "이름, 이메일, 비밀번호로 회원가입")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "회원가입 성공")
Expand Down Expand Up @@ -66,7 +59,7 @@ public Response getUserInfo(@AuthenticationPrincipal CustomUserDetails customUse
return Response.ok( userService.findUserInfo(userId) );
}

@Transactional

@Operation(
summary = "프로필 사진 수정",
description = "유저가 원하는 사진을 골라 프로필 사진을 수정"
Expand Down
24 changes: 21 additions & 3 deletions src/main/java/com/codeit/todo/web/controller/GoalController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@
import com.codeit.todo.service.goal.GoalService;
import com.codeit.todo.web.dto.request.goal.CreateGoalRequest;
import com.codeit.todo.web.dto.request.goal.UpdateGoalRequest;
import com.codeit.todo.web.dto.request.todo.ReadTodoCompleteWithGoalRequest;
import com.codeit.todo.web.dto.response.Response;
import com.codeit.todo.web.dto.response.goal.DeleteGoalResponse;
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;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Slice;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;
Expand Down Expand Up @@ -52,7 +54,7 @@ public Response<CreateGoalResponse> createGoal(
}


@Transactional

@Operation(summary = "목표 수정",
description = "기존 목표 제목 수정 API, 수정된 목표의 ID 반환")
@ApiResponses(value = {
Expand All @@ -68,7 +70,7 @@ public Response<UpdateGoalResponse> updateGoal(
return Response.ok(goalService.updateGoal(userId, goalId, request));
}

@Transactional

@Operation(summary = "목표 삭제",
description = "목표 삭제 API, 삭제된 목표의 ID 반환")
@ApiResponses(value = {
Expand All @@ -83,4 +85,20 @@ public Response<DeleteGoalResponse> deleteGoal(
return Response.ok(goalService.deleteGoal(userId, goalId));
}

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.codeit.todo.service.todo.TodoService;
import com.codeit.todo.web.dto.request.todo.*;
import com.codeit.todo.web.dto.response.Response;
import com.codeit.todo.web.dto.response.goal.ReadGoalsResponse;
import com.codeit.todo.web.dto.response.todo.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
Expand Down Expand Up @@ -49,7 +48,7 @@ public Response<Slice<ReadTodosResponse>> getTodoList(
})
@GetMapping("/goals")
public Response<Slice<ReadTodosWithGoalsResponse>> getTodoWithGoalList(
@Valid @ModelAttribute ReadDashBoardTodoWithGoalRequest request,
@Valid @ModelAttribute ReadTodoCompleteWithGoalRequest request,
@AuthenticationPrincipal CustomUserDetails userDetails
) {
int userId = userDetails.getUserId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import jakarta.validation.constraints.Min;

public record ReadDashBoardTodoWithGoalRequest(
public record ReadTodoCompleteWithGoalRequest(
Integer lastGoalId,
@Min(3)
int size
Expand Down
Loading