Skip to content

Commit

Permalink
Merge pull request #76 from Team-Going/feature/54
Browse files Browse the repository at this point in the history
[feat] 여행 Our TODO 상세 조회 API 구현
  • Loading branch information
SunwoongH authored Jan 11, 2024
2 parents 6f60f8b + bd252b3 commit d46fa5b
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,11 @@ public ResponseEntity<ApiResponse<?>> getMyTodoDetail(@PathVariable final Long t
final MyTodoResponse response = tripDetailService.getMyTodoDetail(tripId);
return ApiResponseUtil.success(SuccessMessage.OK, response);
}

@GetMapping("/{tripId}/our")
public ResponseEntity<ApiResponse<?>> getOurTodoDetail(@UserId final Long userId,
@PathVariable final Long tripId) {
final OurTodoResponse response = tripDetailService.getOurTodoDetail(userId, tripId);
return ApiResponseUtil.success(SuccessMessage.OK, response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.doorip.trip.dto.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AccessLevel;
import lombok.Builder;
import org.doorip.trip.domain.Participant;
import org.doorip.trip.domain.Trip;

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

@Builder(access = AccessLevel.PRIVATE)
public record OurTodoResponse(
String title,
int day,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd", timezone = "Asia/Seoul")
LocalDate startDate,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd", timezone = "Asia/Seoul")
LocalDate endDate,
int progress,
String code,
boolean isComplete,
List<TripParticipantResponse> participants
) {
public static OurTodoResponse of(Trip trip, int progress, boolean isComplete, List<Participant> participants) {
return OurTodoResponse.builder()
.title(trip.getTitle())
.day((int) ChronoUnit.DAYS.between(LocalDate.now(), trip.getStartDate()))
.startDate(trip.getStartDate())
.endDate(trip.getEndDate())
.progress(progress)
.code(trip.getCode())
.isComplete(isComplete)
.participants(participants.stream()
.map(TripParticipantResponse::of)
.toList())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.doorip.trip.dto.response;

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

@Builder(access = AccessLevel.PRIVATE)
public record TripParticipantResponse(
Long participantId,
String name,
int result
) {
public static TripParticipantResponse of(Participant participant) {
User user = participant.getUser();
return TripParticipantResponse.builder()
.participantId(participant.getId())
.name(user.getName())
.result(user.getResult().getNumResult())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,24 @@
import lombok.RequiredArgsConstructor;
import org.doorip.exception.EntityNotFoundException;
import org.doorip.message.ErrorMessage;
import org.doorip.trip.domain.Participant;
import org.doorip.trip.domain.Progress;
import org.doorip.trip.domain.Trip;
import org.doorip.trip.dto.response.MyTodoResponse;
import org.doorip.trip.dto.response.OurTodoResponse;
import org.doorip.trip.repository.TodoRepository;
import org.doorip.trip.repository.TripRepository;
import org.doorip.user.domain.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Objects;

import static java.lang.Math.round;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
Expand All @@ -24,12 +34,54 @@ public MyTodoResponse getMyTodoDetail(Long tripId) {
return MyTodoResponse.of(findTrip.getTitle(), count);
}

public OurTodoResponse getOurTodoDetail(Long userId, Long tripId) {
Trip findTrip = getTrip(tripId);
boolean isComplete = judgeTrip(findTrip);
List<Participant> participants = findTrip.getParticipants();
Participant ownerParticipant = getOwnerParticipant(userId, participants);
sortParticipants(participants, ownerParticipant);
int progressRate = calculateTodoProgressRate(tripId);
return OurTodoResponse.of(findTrip, progressRate, isComplete, participants);
}

private int getIncompleteTodoCount(Long tripId) {
return todoRepository.countTodoByTripIdAndProgress(tripId, Progress.INCOMPLETE);
}

private boolean judgeTrip(Trip trip) {
LocalDate endDate = trip.getEndDate();
LocalDate now = LocalDate.now();
return ChronoUnit.DAYS.between(now, endDate) < 0;
}

private Participant getOwnerParticipant(Long userId, List<Participant> participants) {
return participants.stream()
.filter(participant -> {
User findUser = participant.getUser();
return isOwnerParticipant(userId, findUser);
})
.findFirst()
.orElseThrow(() -> new EntityNotFoundException(ErrorMessage.OWNER_NOT_FOUND));
}

private void sortParticipants(List<Participant> participants, Participant ownerParticipant) {
participants.remove(ownerParticipant);
participants.add(0, ownerParticipant);
}

private int calculateTodoProgressRate(Long tripId) {
int incompleteTodoCount = todoRepository.countTodoByTripIdAndProgress(tripId, Progress.INCOMPLETE);
int completeTodoCount = todoRepository.countTodoByTripIdAndProgress(tripId, Progress.COMPLETE);
int totalTodoCount = incompleteTodoCount + completeTodoCount;
return round(((float) completeTodoCount / totalTodoCount) * 100);
}

private Trip getTrip(Long tripId) {
return tripRepository.findById(tripId)
.orElseThrow(() -> new EntityNotFoundException(ErrorMessage.TRIP_NOT_FOUND));
}

private int getIncompleteTodoCount(Long tripId) {
return todoRepository.countTodoByTripIdAndProgress(tripId, Progress.INCOMPLETE);
private boolean isOwnerParticipant(Long userId, User user) {
return Objects.equals(user.getId(), userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public enum ErrorMessage {
PARTICIPANT_NOT_FOUND(HttpStatus.NOT_FOUND, "e4044", "존재하지 않는 참여자입니다."),
RESULT_NOT_FOUND(HttpStatus.NOT_FOUND, "e4045", "유저의 성향 결과 값을 찾을 수 없습니다."),
TODO_NOT_FOUND(HttpStatus.NOT_FOUND, "e4046", "존재하지 않는 여행 TODO입니다."),
OWNER_NOT_FOUND(HttpStatus.NOT_FOUND, "e4047", "해당 여행에 참여자로 존재하지 않습니다."),

/**
* 405 Method Not Allowed
Expand Down

0 comments on commit d46fa5b

Please sign in to comment.