Skip to content

Commit

Permalink
Merge pull request #47 from Team-Going/feature/34
Browse files Browse the repository at this point in the history
[feat] 여행 TODO 전체 조회 API 구현
  • Loading branch information
SunwoongH authored Jan 9, 2024
2 parents 2590557 + 1942372 commit 157ee7a
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 14 deletions.
2 changes: 2 additions & 0 deletions doorip-api/src/main/java/org/doorip/common/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ public abstract class Constants {
public static final String CHARACTER_TYPE = "utf-8";
public static final String INCOMPLETE = "incomplete";
public static final String COMPLETE = "complete";
public static final String OUR = "our";
public static final String MY = "my";
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package org.doorip.trip.api;

import lombok.RequiredArgsConstructor;
import org.doorip.auth.UserId;
import org.doorip.common.ApiResponse;
import org.doorip.common.ApiResponseUtil;
import org.doorip.message.SuccessMessage;
import org.doorip.trip.dto.request.TodoCreateRequest;
import org.doorip.trip.dto.response.TodoGetResponse;
import org.doorip.trip.service.TodoService;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RequiredArgsConstructor
@RequestMapping("/api/trips")
Expand All @@ -25,4 +26,13 @@ public ResponseEntity<ApiResponse<?>> createTripTodo(@PathVariable final Long tr
todoService.createTripTodo(tripId, request);
return ApiResponseUtil.success(SuccessMessage.CREATED);
}

@GetMapping("/{tripId}/todos")
public ResponseEntity<ApiResponse<?>> getTripTodos(@UserId final Long userId,
@PathVariable final Long tripId,
@RequestParam final String category,
@RequestParam final String progress) {
final List<TodoGetResponse> response = todoService.getTripTodos(userId, tripId, category, progress);
return ApiResponseUtil.success(SuccessMessage.OK, response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.doorip.trip.dto.response;

import lombok.AccessLevel;
import lombok.Builder;
import org.doorip.trip.domain.Allocator;
import org.doorip.trip.domain.Participant;
import org.doorip.user.domain.User;

import java.util.Objects;

@Builder(access = AccessLevel.PRIVATE)
public record TodoAllocatorResponse(
String name,
boolean isOwner
) {
public static TodoAllocatorResponse of(Long userId, Allocator allocator) {
Participant participant = allocator.getParticipant();
User user = participant.getUser();
return TodoAllocatorResponse.builder()
.name(user.getName())
.isOwner(Objects.equals(user.getId(), userId))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.doorip.trip.dto.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AccessLevel;
import lombok.Builder;
import org.doorip.trip.domain.Secret;
import org.doorip.trip.domain.Todo;

import java.time.LocalDate;
import java.util.List;

@Builder(access = AccessLevel.PRIVATE)
public record TodoGetResponse(
Long todoId,
String title,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul")
LocalDate endDate,
List<TodoAllocatorResponse> allocators,
boolean secret
) {
public static TodoGetResponse of(Todo todo, List<TodoAllocatorResponse> allocators) {
return TodoGetResponse.builder()
.todoId(todo.getId())
.title(todo.getTitle())
.endDate(todo.getEndDate())
.allocators(allocators)
.secret(Secret.of(todo.getSecret()))
.build();
}
}
78 changes: 73 additions & 5 deletions doorip-api/src/main/java/org/doorip/trip/service/TodoService.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
package org.doorip.trip.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.doorip.common.Constants;
import org.doorip.exception.EntityNotFoundException;
import org.doorip.exception.InvalidValueException;
import org.doorip.message.ErrorMessage;
import org.doorip.trip.domain.Participant;
import org.doorip.trip.domain.Secret;
import org.doorip.trip.domain.Todo;
import org.doorip.trip.domain.Trip;
import org.doorip.trip.domain.*;
import org.doorip.trip.dto.request.TodoCreateRequest;
import org.doorip.trip.dto.response.TodoAllocatorResponse;
import org.doorip.trip.dto.response.TodoGetResponse;
import org.doorip.trip.repository.ParticipantRepository;
import org.doorip.trip.repository.TodoRepository;
import org.doorip.trip.repository.TripRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

import static org.doorip.trip.domain.Allocator.createAllocator;

@Slf4j
@RequiredArgsConstructor
@Transactional
@Transactional(readOnly = true)
@Service
public class TodoService {
private final TripRepository tripRepository;
private final ParticipantRepository participantRepository;
private final TodoRepository todoRepository;

@Transactional
public void createTripTodo(Long tripId, TodoCreateRequest request) {
validateAllocators(request.allocators());
Trip findTrip = getTrip(tripId);
Expand All @@ -35,6 +39,11 @@ public void createTripTodo(Long tripId, TodoCreateRequest request) {
todoRepository.save(todo);
}

public List<TodoGetResponse> getTripTodos(Long userId, Long tripId, String category, String progress) {
List<Todo> todos = getTripTodosAccordingToCategoryAndProgress(userId, tripId, category, progress);
return getTripTodosResponse(userId, todos);
}

private void validateAllocators(List<Long> allocators) {
if (allocators.isEmpty()) {
throw new InvalidValueException(ErrorMessage.INVALID_ALLOCATOR_COUNT);
Expand All @@ -57,8 +66,67 @@ private void createAllocators(List<Long> allocators, Todo todo) {
});
}

private List<Todo> getTripTodosAccordingToCategoryAndProgress(Long userId, Long tripId, String category, String progress) {
if (category.equals(Constants.OUR)) {
return getOurTodosAccordingToProgress(tripId, progress);
} else if (category.equals(Constants.MY)) {
return getMyTodosAccordingToProgress(userId, tripId, progress);
}
throw new InvalidValueException(ErrorMessage.INVALID_REQUEST_PARAMETER_VALUE);
}

private List<TodoGetResponse> getTripTodosResponse(Long userId, List<Todo> todos) {
List<TodoGetResponse> response = new ArrayList<>();
todos.forEach(todo -> {
List<Allocator> allocators = todo.getAllocators();
List<TodoAllocatorResponse> allocatorResponses = getAllocatorResponses(userId, allocators);
TodoAllocatorResponse ownerAllocator = getOwnerAllocator(allocatorResponses);
sortAllocators(ownerAllocator, allocatorResponses);
response.add(TodoGetResponse.of(todo, allocatorResponses));
});
return response;
}

private Participant getParticipant(Long participantId) {
return participantRepository.findById(participantId)
.orElseThrow(() -> new EntityNotFoundException(ErrorMessage.PARTICIPANT_NOT_FOUND));
}

private List<Todo> getOurTodosAccordingToProgress(Long tripId, String progress) {
if (progress.equals(Constants.INCOMPLETE)) {
return todoRepository.findOurTodoByTripId(tripId, Secret.OUR, Progress.INCOMPLETE);
} else if (progress.equals(Constants.COMPLETE)) {
return todoRepository.findOurTodoByTripId(tripId, Secret.OUR, Progress.COMPLETE);
}
throw new InvalidValueException(ErrorMessage.INVALID_REQUEST_PARAMETER_VALUE);
}

private List<Todo> getMyTodosAccordingToProgress(Long userId, Long tripId, String progress) {
if (progress.equals(Constants.INCOMPLETE)) {
return todoRepository.findMyTodoByTripId(tripId, userId, Progress.INCOMPLETE);
} else if (progress.equals(Constants.COMPLETE)) {
return todoRepository.findMyTodoByTripId(tripId, userId, Progress.COMPLETE);
}
throw new InvalidValueException(ErrorMessage.INVALID_REQUEST_PARAMETER_VALUE);
}

private List<TodoAllocatorResponse> getAllocatorResponses(Long userId, List<Allocator> allocators) {
return new ArrayList<>(allocators.stream()
.map(allocator -> TodoAllocatorResponse.of(userId, allocator))
.toList());
}

private TodoAllocatorResponse getOwnerAllocator(List<TodoAllocatorResponse> allocatorResponses) {
return allocatorResponses.stream()
.filter(TodoAllocatorResponse::isOwner)
.findFirst()
.orElse(null);
}

private void sortAllocators(TodoAllocatorResponse ownerAllocator, List<TodoAllocatorResponse> allocatorResponses) {
if (ownerAllocator != null) {
allocatorResponses.remove(ownerAllocator);
allocatorResponses.add(0, ownerAllocator);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.doorip.trip.service;

import lombok.RequiredArgsConstructor;
import org.doorip.common.Constants;
import org.doorip.exception.EntityNotFoundException;
import org.doorip.exception.InvalidValueException;
import org.doorip.message.ErrorMessage;
Expand All @@ -10,19 +11,17 @@
import org.doorip.trip.dto.request.TripCreateRequest;
import org.doorip.trip.dto.request.TripVerifyRequest;
import org.doorip.trip.dto.response.TripCreateResponse;
import org.doorip.trip.dto.response.TripResponse;
import org.doorip.common.Constants;
import org.doorip.trip.dto.response.TripGetResponse;
import org.doorip.trip.dto.response.TripResponse;
import org.doorip.trip.repository.TripRepository;
import org.doorip.user.domain.User;
import org.doorip.user.repository.UserRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.UUID;

import java.util.List;
import java.util.UUID;

@RequiredArgsConstructor
@Transactional(readOnly = true)
Expand All @@ -39,7 +38,6 @@ public TripCreateResponse createTripAndParticipant(Long userId, TripCreateReques
Trip trip = createTrip(request, code);
createParticipant(request, findUser, trip);
tripRepository.save(trip);

return TripCreateResponse.of(trip);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ public static Secret of(boolean isSecret) {
}
return MY;
}

public static boolean of(Secret secret) {
return !secret.equals(OUR);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,39 @@
package org.doorip.trip.repository;


import org.doorip.trip.domain.Progress;
import org.doorip.trip.domain.Secret;
import org.doorip.trip.domain.Todo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface TodoRepository extends JpaRepository<Todo, Long> {
@Query("select d " +
"from Todo d " +
"join Trip i " +
"on d.trip = i " +
"where i.id = :tripId " +
"and d.progress = :progress " +
"and d.secret = :secret " +
"order by d.endDate")
List<Todo> findOurTodoByTripId(@Param("tripId") Long tripId, @Param("secret") Secret secret, @Param("progress") Progress progress);

@Query("select d " +
"from Todo d " +
"join Trip i " +
"on d.trip = i " +
"join Allocator a " +
"on a.todo = d " +
"join Participant p " +
"on a.participant = p " +
"join User u " +
"on p.user = u " +
"where i.id = :tripId " +
"and u.id = :userId " +
"and d.progress = :progress " +
"order by d.endDate")
List<Todo> findMyTodoByTripId(@Param("tripId") Long tripId, @Param("userId") Long userId, @Param("progress") Progress progress);
}

0 comments on commit 157ee7a

Please sign in to comment.