Skip to content

Commit

Permalink
Feat : DIG-35 루틴 상세 조회 API 구현
Browse files Browse the repository at this point in the history
- 해당하는 루틴의 상세 데이터를 반환
- 루틴 내부의 운동을 찾을 수 없는 경우 예외 추가
  • Loading branch information
bstaran committed Nov 9, 2023
1 parent cf4c7f3 commit 1a67cf0
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public enum ErrorCode implements ErrorType {
NOT_FOUND_ROUTINE(HttpStatus.BAD_REQUEST, "400", "루틴을 찾을 수 없습니다"),
NOT_FOUND_ROUTINE_COMMENT(HttpStatus.BAD_REQUEST, "400", "루틴 댓글을 찾을 수 없습니다"),
NOT_FOUND_EXERCISE_JOURNAL(HttpStatus.BAD_REQUEST, "400", "운동일지를 찾을 수 없습니다"),
NO_EXERCISE_IN_ROUTINE(HttpStatus.NOT_FOUND, "404", "루틴의 운동을 찾을 수 없습니다."),
REFRESH_TOKEN_AUTHENTICATION_FAIL(HttpStatus.UNAUTHORIZED, "401", "Refresh Token 인증 오류"),
ACCESS_TOKEN_AUTHENTICATION_FAIL(HttpStatus.UNAUTHORIZED, "401", "Access Token 인증 오류"),

Expand Down
9 changes: 5 additions & 4 deletions src/main/java/com/ogjg/daitgym/domain/exercise/Exercise.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package com.ogjg.daitgym.domain.exercise;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -19,6 +16,10 @@ public class Exercise {
@GeneratedValue(strategy = IDENTITY)
private Long id;

@OneToOne
@JoinColumn(name = "exercise_part_id")
private ExercisePart exercisePart;

@Column(unique = true)
private String name;
}
5 changes: 5 additions & 0 deletions src/main/java/com/ogjg/daitgym/domain/routine/Day.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

import static jakarta.persistence.FetchType.*;
import static jakarta.persistence.GenerationType.*;
import static lombok.AccessLevel.PROTECTED;
Expand All @@ -21,6 +23,9 @@ public class Day {
@JoinColumn(name = "routine_id")
private Routine routine;

@OneToMany(mappedBy = "day", fetch = LAZY, cascade = CascadeType.ALL)
private List<ExerciseDetail> exerciseDetails;

private int dayNumber;

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.ogjg.daitgym.domain.routine;

import com.ogjg.daitgym.domain.BaseEntity;
import com.ogjg.daitgym.domain.Exercise;
import com.ogjg.daitgym.domain.exercise.Exercise;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.ogjg.daitgym.common.exception.ErrorCode;
import com.ogjg.daitgym.common.response.ApiResponse;
import com.ogjg.daitgym.routine.dto.RoutineDetailsResponseDto;
import com.ogjg.daitgym.routine.dto.RoutineDto;
import com.ogjg.daitgym.routine.dto.RoutineListResponseDto;
import com.ogjg.daitgym.routine.repository.RoutineRepository;
Expand Down Expand Up @@ -45,4 +46,12 @@ public ApiResponse<RoutineListResponseDto> getFollowerRoutines(String myEmail, P

return new ApiResponse<>(ErrorCode.SUCCESS, routinesOfFollowing);
}

@GetMapping("/{routineId}/details")
public ApiResponse<RoutineDetailsResponseDto> getRoutineDetails(@PathVariable("routineId") Long routineId) {

RoutineDetailsResponseDto routineDetails = routineService.getRoutineDetails(routineId);

return new ApiResponse<>(ErrorCode.SUCCESS, routineDetails);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.ogjg.daitgym.routine.dto;

import lombok.Builder;

import java.time.LocalDateTime;
import java.util.List;

public class RoutineDetailsResponseDto {

private String writer;
private String writerImg;
private LocalDateTime createdAt;
private String title;
private String description;
private boolean liked;
private int likeCounts;
private int scrapCounts;
private RoutineDto routine;

@Builder
public RoutineDetailsResponseDto(String writer, String writerImg, LocalDateTime createdAt, String title, String description, boolean liked, int likeCounts, int scrapCounts, RoutineDto routine) {
this.writer = writer;
this.writerImg = writerImg;
this.createdAt = createdAt;
this.title = title;
this.description = description;
this.liked = liked;
this.likeCounts = likeCounts;
this.scrapCounts = scrapCounts;
this.routine = routine;
}

public static class RoutineDto {
private Long id;
private List<DayDto> days;

@Builder
public RoutineDto(Long id, List<DayDto> days) {
this.id = id;
this.days = days;
}
}

public static class DayDto {
private Long id;
private int order;
private boolean isSpread;
private List<ExerciseDto> exercises;

@Builder
public DayDto(Long id, int order, boolean isSpread, List<ExerciseDto> exercises) {
this.id = id;
this.order = order;
this.isSpread = isSpread;
this.exercises = exercises;
}
}

public static class ExerciseDto {
private Long id;
private int order;
private String name;
private String part;
private RestTimeDto restTime;
private List<ExerciseSets> exerciseSets;

@Builder
public ExerciseDto(Long id, int order, String name, String part, RestTimeDto restTime, List<ExerciseSets> exerciseSets) {
this.id = id;
this.order = order;
this.name = name;
this.part = part;
this.restTime = restTime;
this.exerciseSets = exerciseSets;
}
}

public static class RestTimeDto {
private int hours;
private int minutes;
private int seconds;

@Builder
public RestTimeDto(int hours, int minutes, int seconds) {
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
}
}

public static class ExerciseSets {
private Long id;
private int order;
private int weights;
private int counts;
private boolean completed;

@Builder
public ExerciseSets(Long id, int order, int weights, int counts, boolean completed) {
this.id = id;
this.order = order;
this.weights = weights;
this.counts = counts;
this.completed = completed;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.ogjg.daitgym.routine.exception;

import com.ogjg.daitgym.common.exception.CustomException;
import com.ogjg.daitgym.common.exception.ErrorCode;
import com.ogjg.daitgym.common.exception.ErrorData;

public class NoExerciseInRoutine extends CustomException {
public NoExerciseInRoutine() {
super(ErrorCode.NO_EXERCISE_IN_ROUTINE);
}

public NoExerciseInRoutine(String message) {
super(ErrorCode.NO_EXERCISE_IN_ROUTINE, message);
}

public NoExerciseInRoutine(ErrorData errorData) {
super(ErrorCode.NO_EXERCISE_IN_ROUTINE, errorData);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

import com.ogjg.daitgym.domain.routine.Day;
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;
import java.util.Optional;

public interface DayRepository extends JpaRepository<Day, Long> {

@Query("SELECT d FROM Day d LEFT JOIN FETCH d.exerciseDetails WHERE d.routine.id = :routineId")
Optional<List<Day>> findAllWithExerciseDetailsByRoutineId(@Param("routineId") Long routineId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ public interface RoutineRepository extends JpaRepository<Routine, String> {

Optional<Slice<Routine>> findByUserEmailIn(List<String> followerEmails, Pageable pageable);

Optional<Routine> findById(Long routineId);

}
84 changes: 75 additions & 9 deletions src/main/java/com/ogjg/daitgym/routine/service/RoutineService.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package com.ogjg.daitgym.routine.service;

import com.ogjg.daitgym.comment.routine.exception.NotFoundRoutine;
import com.ogjg.daitgym.domain.routine.Day;
import com.ogjg.daitgym.domain.routine.Routine;
import com.ogjg.daitgym.follow.repository.FollowRepository;
import com.ogjg.daitgym.routine.dto.RoutineDetailsResponseDto;
import com.ogjg.daitgym.routine.dto.RoutineDto;
import com.ogjg.daitgym.routine.dto.RoutineListResponseDto;
import com.ogjg.daitgym.routine.exception.NoExerciseInRoutine;
import com.ogjg.daitgym.routine.repository.DayRepository;
import com.ogjg.daitgym.routine.repository.ExerciseDetailRepository;
import com.ogjg.daitgym.routine.repository.RoutineRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -15,6 +20,9 @@
import java.awt.print.Pageable;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static com.ogjg.daitgym.routine.dto.RoutineDetailsResponseDto.*;

@Slf4j
@Service
Expand All @@ -23,6 +31,8 @@ public class RoutineService {

private final RoutineRepository routineRepository;
private final FollowRepository followRepository;
private final DayRepository dayRepository;
private final ExerciseDetailRepository exerciseDetailRepository;

@Transactional(readOnly = true)
public RoutineListResponseDto getRoutines(Pageable pageable) {
Expand All @@ -39,17 +49,15 @@ private RoutineListResponseDto getRoutineListResponseDto(Slice<Routine> routines
}

List<RoutineDto> routineDtos = routines.stream()
.map(routine -> {
return RoutineDto.builder()
.id(routine.getId())
.title(routine.getTitle())
.author(routine.getUser().getNickname())
.description(routine.getContent())
.map(routine -> RoutineDto.builder()
.id(routine.getId())
.title(routine.getTitle())
.author(routine.getUser().getNickname())
.description(routine.getContent())
// .likeCounts()
// .scrapCounts()
.createdAt(routine.getCreatedAt())
.build();
})
.createdAt(routine.getCreatedAt())
.build())
.toList();

return RoutineListResponseDto.builder()
Expand Down Expand Up @@ -82,4 +90,62 @@ public RoutineListResponseDto getFollowerRoutines(String myEmail, Pageable pagea
return getRoutineListResponseDto(routines);
}

@Transactional(readOnly = true)
public RoutineDetailsResponseDto getRoutineDetails(Long routineId) {
Routine routine = routineRepository.findById(routineId)
.orElseThrow(NotFoundRoutine::new);

List<Day> days = dayRepository.findAllWithExerciseDetailsByRoutineId(routine.getId())
.orElseThrow(NoExerciseInRoutine::new);

List<DayDto> dayDtos = days.stream()
.map(day -> {
List<ExerciseDto> exerciseDtos = day.getExerciseDetails().stream()
.map(exerciseDetail -> {
ExerciseSets exerciseSet = ExerciseSets.builder()
.id(exerciseDetail.getId())
.order(exerciseDetail.getSetCount())
.weights(exerciseDetail.getWeight())
.counts(exerciseDetail.getRepetitionCount())
.completed(false)
.build();

return ExerciseDto.builder()
.id(exerciseDetail.getExercise().getId())
.order(exerciseDetail.getOrder())
.name(exerciseDetail.getExercise().getName())
.part(exerciseDetail.getExercise().getExercisePart().getPart())
.restTime(new RestTimeDto(
exerciseDetail.getRestTime().getHour(),
exerciseDetail.getRestTime().getMinute(),
exerciseDetail.getRestTime().getSecond()))
.exerciseSets(Collections.singletonList(exerciseSet))
.build();
})
.collect(Collectors.toList());

return DayDto.builder()
.id(day.getId())
.order(day.getDayNumber())
.isSpread(false)
.exercises(exerciseDtos)
.build();
})
.toList();

return RoutineDetailsResponseDto.builder()
.writer(routine.getUser().getNickname())
.writerImg(routine.getUser().getImageUrl())
.title(routine.getTitle())
.description(routine.getContent())
.liked(false)
.likeCounts(0)
.scrapCounts(0)
.routine(RoutineDetailsResponseDto.RoutineDto.builder()
.id(routine.getId())
.days(dayDtos)
.build())
.createdAt(routine.getCreatedAt())
.build();
}
}

0 comments on commit 1a67cf0

Please sign in to comment.