Skip to content

Commit 2277ebf

Browse files
authored
Merge pull request #41 from hackathon-soa/feat/#38
Refactor : 여행코스 상세 조회 API 2차 구현
2 parents 8bba9e8 + 4762455 commit 2277ebf

File tree

3 files changed

+114
-40
lines changed

3 files changed

+114
-40
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package hackathon.soa.domain.segment;
2+
3+
import hackathon.soa.domain.search.dto.SearchResponseDTO;
4+
import hackathon.soa.domain.segment.dto.SegmentResponseDTO;
5+
import hackathon.soa.entity.CourseSegment;
6+
import hackathon.soa.entity.MoveSegment;
7+
import hackathon.soa.entity.StaySegment;
8+
9+
import java.math.BigDecimal;
10+
import java.time.format.DateTimeFormatter;
11+
import java.util.List;
12+
import java.util.Locale;
13+
14+
public class SegmentConverter {
15+
16+
public static SegmentResponseDTO.CourseDetailResponseDTO toCourseDetailResponseDTO(
17+
Long courseId, Boolean isOwner,
18+
SearchResponseDTO.SearchCourseResponseDTO courseInfo,
19+
List<SegmentResponseDTO.SegmentDetailDTO> segments) {
20+
return SegmentResponseDTO.CourseDetailResponseDTO.builder()
21+
.courseId(courseId)
22+
.isMine(isOwner)
23+
.courseInfo(courseInfo)
24+
.segments(segments)
25+
.build();
26+
}
27+
28+
public static SegmentResponseDTO.SegmentDetailDTO toSegmentDetailDTO(
29+
CourseSegment courseSegment,
30+
StaySegment staySegment,
31+
MoveSegment moveSegment,
32+
Boolean isParticipated) {
33+
34+
// 시간 포맷터 정의
35+
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM/dd(E)", Locale.KOREAN);
36+
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
37+
38+
String segmentType = (staySegment != null) ? "장소" : "이동";
39+
40+
return SegmentResponseDTO.SegmentDetailDTO.builder()
41+
.segmentOrder(courseSegment.getSegmentOrder())
42+
.segmentType(segmentType)
43+
.date(courseSegment.getStartTime().format(dateFormatter))
44+
.startTime(courseSegment.getStartTime().format(timeFormatter))
45+
.endTime(courseSegment.getEndTime().format(timeFormatter))
46+
.staySegment(staySegment != null ? toStaySegmentDTO(staySegment, isParticipated) : null)
47+
.moveSegment(moveSegment != null ? toMoveSegmentDTO(moveSegment) : null)
48+
.build();
49+
}
50+
51+
public static SegmentResponseDTO.StaySegmentDTO toStaySegmentDTO(StaySegment staySegment, Boolean isParticipated) {
52+
return SegmentResponseDTO.StaySegmentDTO.builder()
53+
.segmentId(staySegment.getSegmentId())
54+
.locationName(staySegment.getLocationName())
55+
.locationAddress(staySegment.getLocationAddress())
56+
.isParticipated(isParticipated)
57+
.build();
58+
}
59+
60+
public static SegmentResponseDTO.MoveSegmentDTO toMoveSegmentDTO(MoveSegment moveSegment) {
61+
return SegmentResponseDTO.MoveSegmentDTO.builder()
62+
.segmentId(moveSegment.getSegmentId())
63+
.movementType(moveSegment.getMovementType())
64+
.movementDistanceKm(BigDecimal.valueOf(moveSegment.getMovementDistanceKm()))
65+
.build();
66+
}
67+
}

src/main/java/hackathon/soa/domain/segment/SegmentService.java

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22

33
import hackathon.soa.common.apiPayload.code.status.ErrorStatus;
44
import hackathon.soa.common.apiPayload.exception.CourseHandler;
5+
import hackathon.soa.common.apiPayload.exception.GeneralException;
56
import hackathon.soa.common.apiPayload.exception.SegmentHandler;
67
import hackathon.soa.domain.course.repository.CourseRepository;
8+
import hackathon.soa.domain.likes.LikesRepository;
9+
import hackathon.soa.domain.member.MemberRepository;
10+
import hackathon.soa.domain.search.SearchConverter;
11+
import hackathon.soa.domain.search.dto.SearchResponseDTO;
712
import hackathon.soa.domain.segment.dto.SegmentResponseDTO;
813
import hackathon.soa.domain.segment.repository.CourseSegmentRepository;
914
import hackathon.soa.domain.segment.repository.MoveSegmentRepository;
1015
import hackathon.soa.domain.segment.repository.StaySegmentRepository;
11-
import hackathon.soa.entity.Course;
12-
import hackathon.soa.entity.CourseSegment;
13-
import hackathon.soa.entity.MoveSegment;
14-
import hackathon.soa.entity.StaySegment;
16+
import hackathon.soa.entity.*;
1517
import lombok.RequiredArgsConstructor;
1618
import lombok.extern.slf4j.Slf4j;
1719
import org.springframework.stereotype.Service;
@@ -33,6 +35,8 @@ public class SegmentService {
3335
private final StaySegmentRepository staySegmentRepository;
3436
private final MoveSegmentRepository moveSegmentRepository;
3537
private final CourseRepository courseRepository;
38+
private final MemberRepository memberRepository;
39+
private final LikesRepository likesRepository;
3640

3741
public SegmentResponseDTO.CourseDetailResponseDTO getCourseDetail(Long courseId, Long memberId) {
3842
// 1. 코스 조회 및 작성자 확인
@@ -41,59 +45,45 @@ public SegmentResponseDTO.CourseDetailResponseDTO getCourseDetail(Long courseId,
4145

4246
boolean isOwner = course.getMember().getId().equals(memberId);
4347

44-
// 2. 코스 세그먼트들을 순서대로 조회함
48+
// 2. 코스 기본 정보 및 좋아요 정보 조회
49+
SearchResponseDTO.SearchCourseResponseDTO courseInfo = getCourseById(memberId, courseId);
50+
51+
// 3. 코스 세그먼트들을 순서대로 조회
4552
List<CourseSegment> courseSegments = courseSegmentRepository.findByCourse_IdOrderBySegmentOrder(courseId);
4653

4754
if (courseSegments.isEmpty()) {
4855
throw new CourseHandler(ErrorStatus.NOT_FOUND_COURSE);
4956
}
5057

51-
// 3. 각 세그먼트 정보를 조회하여 DTO 생성
58+
// 4. 각 세그먼트 정보를 조회하여 DTO 생성
5259
List<SegmentResponseDTO.SegmentDetailDTO> segmentDetails = courseSegments.stream()
53-
.map(this::buildSegmentDetail)
60+
.map(segment -> buildSegmentDetail(segment, memberId))
5461
.collect(Collectors.toList());
5562

56-
return SegmentResponseDTO.CourseDetailResponseDTO.builder()
57-
.courseId(courseId)
58-
.isOwner(isOwner)
59-
.segments(segmentDetails)
60-
.build();
63+
// 5. SegmentConverter를 사용하여 최종 응답 DTO 생성
64+
return SegmentConverter.toCourseDetailResponseDTO(courseId, isOwner, courseInfo, segmentDetails);
6165
}
6266

63-
private SegmentResponseDTO.SegmentDetailDTO buildSegmentDetail(CourseSegment courseSegment) {
67+
private SegmentResponseDTO.SegmentDetailDTO buildSegmentDetail(CourseSegment courseSegment, Long memberId) {
6468
Long segmentId = courseSegment.getId();
6569

66-
// 시간 포맷터 정의
67-
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM/dd(E)", Locale.KOREAN);
68-
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
69-
7070
try {
7171
// 장소 세그먼트 먼저 확인 (@MapsId로 PK가 동일함)
7272
Optional<StaySegment> staySegment = staySegmentRepository.findById(segmentId);
7373
if (staySegment.isPresent()) {
74-
return SegmentResponseDTO.SegmentDetailDTO.builder()
75-
.segmentOrder(courseSegment.getSegmentOrder())
76-
.segmentType("장소")
77-
.date(courseSegment.getStartTime().format(dateFormatter))
78-
.startTime(courseSegment.getStartTime().format(timeFormatter))
79-
.endTime(courseSegment.getEndTime().format(timeFormatter))
80-
.staySegment(SegmentResponseDTO.StaySegmentDTO.from(staySegment.get()))
81-
.moveSegment(null)
82-
.build();
74+
// 현재 사용자가 이 장소 세그먼트에 참여했는지 확인
75+
boolean isParticipated = staySegment.get().getSegmentParticipations().stream()
76+
.anyMatch(participation -> participation.getMember().getId().equals(memberId));
77+
78+
// SegmentConverter를 사용하여 장소 세그먼트 DTO 생성
79+
return SegmentConverter.toSegmentDetailDTO(courseSegment, staySegment.get(), null, isParticipated);
8380
}
8481

8582
// 이동 세그먼트 확인 (@MapsId로 PK가 동일함)
8683
Optional<MoveSegment> moveSegment = moveSegmentRepository.findById(segmentId);
8784
if (moveSegment.isPresent()) {
88-
return SegmentResponseDTO.SegmentDetailDTO.builder()
89-
.segmentOrder(courseSegment.getSegmentOrder())
90-
.segmentType("이동")
91-
.date(courseSegment.getStartTime().format(dateFormatter))
92-
.startTime(courseSegment.getStartTime().format(timeFormatter))
93-
.endTime(courseSegment.getEndTime().format(timeFormatter))
94-
.staySegment(null)
95-
.moveSegment(SegmentResponseDTO.MoveSegmentDTO.from(moveSegment.get()))
96-
.build();
85+
// SegmentConverter를 사용하여 이동 세그먼트 DTO 생성
86+
return SegmentConverter.toSegmentDetailDTO(courseSegment, null, moveSegment.get(), false);
9787
}
9888

9989
throw new SegmentHandler(ErrorStatus.SEGMENT_NOT_FOUND);
@@ -103,4 +93,17 @@ private SegmentResponseDTO.SegmentDetailDTO buildSegmentDetail(CourseSegment cou
10393
throw new SegmentHandler(ErrorStatus.SEGMENT_DESERIALIZATION_ERROR);
10494
}
10595
}
96+
97+
public SearchResponseDTO.SearchCourseResponseDTO getCourseById(Long memberId, Long courseId) {
98+
99+
Member member = memberRepository.findById(memberId)
100+
.orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_NOT_FOUND));
101+
102+
Course course = courseRepository.findById(courseId)
103+
.orElseThrow(() -> new GeneralException(ErrorStatus.NOT_FOUND_COURSE));
104+
105+
boolean liked = likesRepository.existsByCourseAndMember(course, member);
106+
107+
return SearchConverter.toSearchCourseResponseDTO(course, liked);
108+
}
106109
}

src/main/java/hackathon/soa/domain/segment/dto/SegmentResponseDTO.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package hackathon.soa.domain.segment.dto;
22

3+
import hackathon.soa.domain.search.dto.SearchResponseDTO;
34
import hackathon.soa.entity.MoveSegment;
45
import hackathon.soa.entity.MovementType;
56
import hackathon.soa.entity.StaySegment;
@@ -19,7 +20,8 @@ public class SegmentResponseDTO {
1920
@AllArgsConstructor
2021
public static class CourseDetailResponseDTO {
2122
private Long courseId;
22-
private Boolean isOwner; // 해당 멤버가 코스 작성자인지 여부
23+
private Boolean isMine; // 해당 멤버가 코스 작성자인지 여부
24+
private SearchResponseDTO.SearchCourseResponseDTO courseInfo; // 코스 기본 정보 및 좋아요 정보
2325
private List<SegmentDetailDTO> segments;
2426
}
2527

@@ -30,9 +32,9 @@ public static class CourseDetailResponseDTO {
3032
public static class SegmentDetailDTO {
3133
private Integer segmentOrder;
3234
private String segmentType; // "장소" or "이동"
33-
private String date; // "07/05(토)"
34-
private String startTime; // "09:00"
35-
private String endTime; // "09:30"
35+
private String date; // "07/05(토)" 형식
36+
private String startTime; // "09:00" 형식
37+
private String endTime; // "09:30" 형식
3638
private StaySegmentDTO staySegment;
3739
private MoveSegmentDTO moveSegment;
3840
}
@@ -45,12 +47,14 @@ public static class StaySegmentDTO {
4547
private Long segmentId;
4648
private String locationName;
4749
private String locationAddress;
50+
private Boolean isParticipated; // 현재 사용자의 참여 여부
4851

49-
public static StaySegmentDTO from(StaySegment staySegment) {
52+
public static StaySegmentDTO from(StaySegment staySegment, Boolean isParticipated) {
5053
return StaySegmentDTO.builder()
5154
.segmentId(staySegment.getSegmentId())
5255
.locationName(staySegment.getLocationName())
5356
.locationAddress(staySegment.getLocationAddress())
57+
.isParticipated(isParticipated)
5458
.build();
5559
}
5660
}

0 commit comments

Comments
 (0)