From a10562399a246ec5b9e2bbddd7f35f06a13310f7 Mon Sep 17 00:00:00 2001 From: sunwoong Date: Wed, 10 Jan 2024 06:21:40 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20=EC=97=AC=ED=96=89=20TODO=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=9A=94=EC=B2=AD=20=ED=8C=8C=EB=9D=BC?= =?UTF-8?q?=EB=AF=B8=ED=84=B0=20=EC=83=81=EC=88=98=ED=99=94=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doorip-api/src/main/java/org/doorip/common/Constants.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doorip-api/src/main/java/org/doorip/common/Constants.java b/doorip-api/src/main/java/org/doorip/common/Constants.java index ad7e715..eb6ec3f 100644 --- a/doorip-api/src/main/java/org/doorip/common/Constants.java +++ b/doorip-api/src/main/java/org/doorip/common/Constants.java @@ -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"; } From 5def6b8f3382444dd9da655b87a0cc906afd3722 Mon Sep 17 00:00:00 2001 From: sunwoong Date: Wed, 10 Jan 2024 06:22:49 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=EC=97=AC=ED=96=89=20TODO=20?= =?UTF-8?q?=EA=B3=B5=EA=B0=9C=EC=97=AC=EB=B6=80=20boolean=20=EB=B3=80?= =?UTF-8?q?=ED=99=98=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/doorip/trip/domain/Secret.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doorip-domain/src/main/java/org/doorip/trip/domain/Secret.java b/doorip-domain/src/main/java/org/doorip/trip/domain/Secret.java index 3841196..5b3cf0b 100644 --- a/doorip-domain/src/main/java/org/doorip/trip/domain/Secret.java +++ b/doorip-domain/src/main/java/org/doorip/trip/domain/Secret.java @@ -9,4 +9,8 @@ public static Secret of(boolean isSecret) { } return MY; } + + public static boolean of(Secret secret) { + return !secret.equals(OUR); + } } From 87b230e42309cead7254e48c1727aad4d942dbf7 Mon Sep 17 00:00:00 2001 From: sunwoong Date: Wed, 10 Jan 2024 06:23:19 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20=EC=97=AC=ED=96=89=20TODO=20?= =?UTF-8?q?=EB=B0=B0=EC=A0=95=EC=9E=90=20=EC=9D=91=EB=8B=B5=20dto=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EA=B5=AC=ED=98=84=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/TodoAllocatorResponse.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 doorip-api/src/main/java/org/doorip/trip/dto/response/TodoAllocatorResponse.java diff --git a/doorip-api/src/main/java/org/doorip/trip/dto/response/TodoAllocatorResponse.java b/doorip-api/src/main/java/org/doorip/trip/dto/response/TodoAllocatorResponse.java new file mode 100644 index 0000000..74664c2 --- /dev/null +++ b/doorip-api/src/main/java/org/doorip/trip/dto/response/TodoAllocatorResponse.java @@ -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(); + } +} From e61ff4684d12a397a9c0a94fa9c19d50b1fe909a Mon Sep 17 00:00:00 2001 From: sunwoong Date: Wed, 10 Jan 2024 06:23:30 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20=EC=97=AC=ED=96=89=20TODO=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=9D=91=EB=8B=B5=20dto=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EA=B5=AC=ED=98=84=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trip/dto/response/TodoGetResponse.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 doorip-api/src/main/java/org/doorip/trip/dto/response/TodoGetResponse.java diff --git a/doorip-api/src/main/java/org/doorip/trip/dto/response/TodoGetResponse.java b/doorip-api/src/main/java/org/doorip/trip/dto/response/TodoGetResponse.java new file mode 100644 index 0000000..440bb56 --- /dev/null +++ b/doorip-api/src/main/java/org/doorip/trip/dto/response/TodoGetResponse.java @@ -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 allocators, + boolean secret +) { + public static TodoGetResponse of(Todo todo, List allocators) { + return TodoGetResponse.builder() + .todoId(todo.getId()) + .title(todo.getTitle()) + .endDate(todo.getEndDate()) + .allocators(allocators) + .secret(Secret.of(todo.getSecret())) + .build(); + } +} From 2a59a85a45a5e22d930fe0bf0d247e4ac1140050 Mon Sep 17 00:00:00 2001 From: sunwoong Date: Wed, 10 Jan 2024 06:23:54 +0900 Subject: [PATCH 5/9] =?UTF-8?q?chore:=20=EC=BD=94=EB=93=9C=20=EC=A0=95?= =?UTF-8?q?=EB=A0=AC=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/doorip/trip/service/TripService.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/doorip-api/src/main/java/org/doorip/trip/service/TripService.java b/doorip-api/src/main/java/org/doorip/trip/service/TripService.java index 93af05c..8972214 100644 --- a/doorip-api/src/main/java/org/doorip/trip/service/TripService.java +++ b/doorip-api/src/main/java/org/doorip/trip/service/TripService.java @@ -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; @@ -9,8 +10,6 @@ import org.doorip.trip.domain.Trip; import org.doorip.trip.dto.request.TripCreateRequest; import org.doorip.trip.dto.response.TripCreateResponse; -import org.doorip.trip.repository.ParticipantRepository; -import org.doorip.common.Constants; import org.doorip.trip.dto.response.TripGetResponse; import org.doorip.trip.repository.TripRepository; import org.doorip.user.domain.User; @@ -19,18 +18,14 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; -import java.util.UUID; - -import static org.doorip.trip.domain.Participant.createParticipant; -import static org.doorip.trip.domain.Trip.createTrip; import java.util.List; +import java.util.UUID; @RequiredArgsConstructor @Transactional(readOnly = true) @Service public class TripService { private final TripRepository tripRepository; - private final ParticipantRepository participantRepository; private final UserRepository userRepository; @Transactional @@ -41,7 +36,6 @@ public TripCreateResponse createTripAndParticipant(Long userId, TripCreateReques Trip trip = createTrip(request, code); createParticipant(request, findUser, trip); tripRepository.save(trip); - return TripCreateResponse.of(trip); } From cf5f921778b8a29f564bd6650e0a4691cbc3767d Mon Sep 17 00:00:00 2001 From: sunwoong Date: Wed, 10 Jan 2024 06:24:50 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20=EC=97=AC=ED=96=89=20Our=20&=20My?= =?UTF-8?q?=20TODO=20=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=EA=B5=AC=ED=98=84=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trip/repository/TodoRepository.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/doorip-domain/src/main/java/org/doorip/trip/repository/TodoRepository.java b/doorip-domain/src/main/java/org/doorip/trip/repository/TodoRepository.java index 932ce39..3eb8499 100644 --- a/doorip-domain/src/main/java/org/doorip/trip/repository/TodoRepository.java +++ b/doorip-domain/src/main/java/org/doorip/trip/repository/TodoRepository.java @@ -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 { + @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 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 findMyTodoByTripId(@Param("tripId") Long tripId, @Param("userId") Long userId, @Param("progress") Progress progress); } From 6e17e0b7868415d0666c3dc0cf8b6c247a2b74b5 Mon Sep 17 00:00:00 2001 From: sunwoong Date: Wed, 10 Jan 2024 06:25:10 +0900 Subject: [PATCH 7/9] =?UTF-8?q?feat:=20=EC=97=AC=ED=96=89=20Our=20&=20My?= =?UTF-8?q?=20TODO=20=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20=EB=B9=84?= =?UTF-8?q?=EC=A6=88=EB=8B=88=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/doorip/trip/service/TodoService.java | 78 +++++++++++++++++-- 1 file changed, 73 insertions(+), 5 deletions(-) diff --git a/doorip-api/src/main/java/org/doorip/trip/service/TodoService.java b/doorip-api/src/main/java/org/doorip/trip/service/TodoService.java index 5859b22..f3a86fb 100644 --- a/doorip-api/src/main/java/org/doorip/trip/service/TodoService.java +++ b/doorip-api/src/main/java/org/doorip/trip/service/TodoService.java @@ -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); @@ -35,6 +39,11 @@ public void createTripTodo(Long tripId, TodoCreateRequest request) { todoRepository.save(todo); } + public List getTripTodos(Long userId, Long tripId, String category, String progress) { + List todos = getTripTodosAccordingToCategoryAndProgress(userId, tripId, category, progress); + return getTripTodosResponse(userId, todos); + } + private void validateAllocators(List allocators) { if (allocators.isEmpty()) { throw new InvalidValueException(ErrorMessage.INVALID_ALLOCATOR_COUNT); @@ -57,8 +66,67 @@ private void createAllocators(List allocators, Todo todo) { }); } + private List 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 getTripTodosResponse(Long userId, List todos) { + List response = new ArrayList<>(); + todos.forEach(todo -> { + List allocators = todo.getAllocators(); + List 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 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 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 getAllocatorResponses(Long userId, List allocators) { + return new ArrayList<>(allocators.stream() + .map(allocator -> TodoAllocatorResponse.of(userId, allocator)) + .toList()); + } + + private TodoAllocatorResponse getOwnerAllocator(List allocatorResponses) { + return allocatorResponses.stream() + .filter(TodoAllocatorResponse::isOwner) + .findFirst() + .orElse(null); + } + + private void sortAllocators(TodoAllocatorResponse ownerAllocator, List allocatorResponses) { + if (ownerAllocator != null) { + allocatorResponses.remove(ownerAllocator); + allocatorResponses.add(0, ownerAllocator); + } + } } From 7f316f1309337082b034aa61f045ee989456de38 Mon Sep 17 00:00:00 2001 From: sunwoong Date: Wed, 10 Jan 2024 06:25:25 +0900 Subject: [PATCH 8/9] =?UTF-8?q?feat:=20=EC=97=AC=ED=96=89=20Our=20&=20My?= =?UTF-8?q?=20TODO=20=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/doorip/trip/api/TodoApiController.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/doorip-api/src/main/java/org/doorip/trip/api/TodoApiController.java b/doorip-api/src/main/java/org/doorip/trip/api/TodoApiController.java index 160a3bf..f63d3c9 100644 --- a/doorip-api/src/main/java/org/doorip/trip/api/TodoApiController.java +++ b/doorip-api/src/main/java/org/doorip/trip/api/TodoApiController.java @@ -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") @@ -25,4 +26,13 @@ public ResponseEntity> createTripTodo(@PathVariable final Long tr todoService.createTripTodo(tripId, request); return ApiResponseUtil.success(SuccessMessage.CREATED); } + + @GetMapping("/{tripId}/todos") + public ResponseEntity> getTripTodos(@UserId final Long userId, + @PathVariable final Long tripId, + @RequestParam final String category, + @RequestParam final String progress) { + final List response = todoService.getTripTodos(userId, tripId, category, progress); + return ApiResponseUtil.success(SuccessMessage.OK, response); + } } From 1942372e5b30c1d07c0057d5d83813e19befb091 Mon Sep 17 00:00:00 2001 From: sunwoong Date: Wed, 10 Jan 2024 06:30:37 +0900 Subject: [PATCH 9/9] =?UTF-8?q?chore:=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/doorip/trip/service/TripService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doorip-api/src/main/java/org/doorip/trip/service/TripService.java b/doorip-api/src/main/java/org/doorip/trip/service/TripService.java index 4f31203..f297bc9 100644 --- a/doorip-api/src/main/java/org/doorip/trip/service/TripService.java +++ b/doorip-api/src/main/java/org/doorip/trip/service/TripService.java @@ -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; @@ -10,9 +11,8 @@ 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;