Skip to content

Commit 837159c

Browse files
authored
Merge pull request #39 from WHERE2GOES/v3-certification
feat: 인증 조회 시 리턴 구조체 추가 수정
2 parents 17ab0ad + e201d4e commit 837159c

File tree

5 files changed

+119
-2
lines changed

5 files changed

+119
-2
lines changed

greatjourney/src/main/java/backend/greatjourney/domain/certification/dto/CourseCertificationStatusResponse.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ public record CourseCertificationStatusResponse(
66
boolean isCompleted, // 코스 완료 여부
77
long totalCertificationsCount, // (추가) 해당 코스의 전체 인증소 개수
88
long certifiedCount, // (추가) 사용자가 인증한 개수
9-
List<CertificationStatusDto> certifications // 기존 인증 내역 리스트
9+
List<CertificationStatusDto> certifications, // 기존 인증 내역 리스트
10+
List<UncertifiedPlaceDto> uncertifiedList // (추가) 아직 인증하지 않은 목록
1011
) {}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package backend.greatjourney.domain.certification.dto;
2+
3+
4+
import backend.greatjourney.domain.course.domain.Place;
5+
6+
public record UncertifiedPlaceDto(
7+
Long placeId,
8+
String placeName
9+
// String address,
10+
// Double latitude,
11+
// Double longitude
12+
) {
13+
/**
14+
* Place 엔티티를 UncertifiedPlaceDto로 변환합니다.
15+
* @param place 원본 Place 엔티티
16+
* @return 변환된 DTO
17+
*/
18+
public static UncertifiedPlaceDto from(Place place) {
19+
return new UncertifiedPlaceDto(
20+
place.getId(),
21+
place.getName()
22+
// place.getAddress(),
23+
// place.getLatitude(),
24+
// place.getLongitude()
25+
);
26+
}
27+
}

greatjourney/src/main/java/backend/greatjourney/domain/certification/service/CertificationService.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
import backend.greatjourney.domain.certification.dto.CertificationRequest;
55
import backend.greatjourney.domain.certification.dto.CertificationStatusDto;
66
import backend.greatjourney.domain.certification.dto.CourseCertificationStatusResponse;
7+
import backend.greatjourney.domain.certification.dto.UncertifiedPlaceDto;
78
import backend.greatjourney.domain.certification.repository.UserCertificationRepository;
89
import backend.greatjourney.domain.course.domain.Place;
10+
import backend.greatjourney.domain.course.dto.CertificationCenterDto;
911
import backend.greatjourney.domain.course.repository.PlaceRepository;
12+
import backend.greatjourney.domain.course.service.CourseInfoService;
1013
import backend.greatjourney.domain.user.entity.User;
1114
import backend.greatjourney.domain.user.repository.UserRepository;
1215
import backend.greatjourney.global.exception.CustomException;
@@ -17,6 +20,7 @@
1720
import org.springframework.transaction.annotation.Transactional;
1821

1922
import java.util.List;
23+
import java.util.Set;
2024
import java.util.stream.Collectors;
2125

2226
@Service
@@ -27,6 +31,7 @@ public class CertificationService {
2731
private final PlaceRepository placeRepository;
2832
private final UserRepository userRepository;
2933
private final UserCertificationRepository userCertificationRepository;
34+
private final CourseInfoService courseInfoService;
3035

3136
public void certify(CustomOAuth2User customOAuth2User, CertificationRequest request) {
3237
// 1. 요청받은 placeId로 인증센터를 조회합니다.
@@ -65,6 +70,11 @@ public void certify(CustomOAuth2User customOAuth2User, CertificationRequest requ
6570
public CourseCertificationStatusResponse getUserCertificationsForCourse(CustomOAuth2User customOAuth2User, Integer courseId) {
6671
Long userId = Long.parseLong(customOAuth2User.getUserId());
6772

73+
// 1. CourseInfoService를 통해 코스의 전체 인증센터 DTO 목록을 가져옵니다.
74+
List<CertificationCenterDto> allCenterDtos = courseInfoService.getCertificationCentersForCourse(courseId);
75+
long totalCertificationsCount = allCenterDtos.size();
76+
77+
6878
// 1. 해당 코스의 전체 인증센터 개수를 조회합니다.
6979
long totalCertificationCenters = placeRepository.countByCategoryAndCourseId("인증센터", courseId);
7080

@@ -82,7 +92,24 @@ public CourseCertificationStatusResponse getUserCertificationsForCourse(CustomOA
8292
.map(CertificationStatusDto::from)
8393
.toList();
8494

95+
// 5. '미인증' 목록('uncertifiedList')을 계산합니다.
96+
// - 먼저, 인증 완료한 장소의 ID만 Set으로 추출합니다.
97+
Set<Long> certifiedPlaceIds = userCertifications.stream()
98+
.map(uc -> uc.getCertificationCenter().getId())
99+
.collect(Collectors.toSet());
100+
101+
// - 전체 인증센터 DTO 목록에서, 인증된 ID를 포함하지 않는 것들만 필터링합니다.
102+
List<UncertifiedPlaceDto> uncertifiedDtos = allCenterDtos.stream()
103+
.filter(centerDto -> !certifiedPlaceIds.contains(centerDto.placeId()))
104+
.map(centerDto -> new UncertifiedPlaceDto(
105+
centerDto.placeId(),
106+
centerDto.placeName()
107+
// centerDto.latitude(),
108+
// centerDto.longitude()
109+
))
110+
.toList();
111+
85112
// 5. 최종 응답 DTO를 생성하여 반환합니다.
86-
return new CourseCertificationStatusResponse(isCompleted, totalCertificationCenters, certifiedCount, certificationDtos);
113+
return new CourseCertificationStatusResponse(isCompleted, totalCertificationCenters, certifiedCount, certificationDtos, uncertifiedDtos);
87114
}
88115
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package backend.greatjourney.domain.course.dto;
2+
3+
import backend.greatjourney.domain.course.domain.Place;
4+
5+
// 이 DTO는 이전에 만들었던 UncertifiedPlaceDto와 거의 동일할 수 있습니다.
6+
public record CertificationCenterDto(
7+
long placeId,
8+
String placeName,
9+
Double latitude,
10+
Double longitude
11+
) {
12+
public static CertificationCenterDto from(Place place) {
13+
return new CertificationCenterDto(
14+
place.getId(),
15+
place.getName(),
16+
place.getLatitude(),
17+
place.getLongitude()
18+
);
19+
}
20+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package backend.greatjourney.domain.course.service;
2+
3+
import backend.greatjourney.domain.course.domain.Place;
4+
import backend.greatjourney.domain.course.dto.CertificationCenterDto;
5+
import backend.greatjourney.domain.course.repository.CourseRepository;
6+
import backend.greatjourney.domain.course.repository.PlaceRepository;
7+
import backend.greatjourney.global.exception.CustomException;
8+
import backend.greatjourney.global.exception.ErrorCode;
9+
import jakarta.transaction.Transactional;
10+
import lombok.RequiredArgsConstructor;
11+
import org.springframework.stereotype.Service;
12+
13+
import java.util.List;
14+
15+
@Service
16+
@RequiredArgsConstructor
17+
@Transactional // 정보 조회이므로 readOnly = true 설정
18+
public class CourseInfoService {
19+
20+
private final PlaceRepository placeRepository;
21+
private final CourseRepository courseRepository;
22+
23+
/**
24+
* 특정 코스에 포함된 모든 인증센터 목록을 조회합니다.
25+
* @param courseId 조회할 코스의 ID
26+
* @return 인증센터 DTO 리스트
27+
*/
28+
public List<CertificationCenterDto> getCertificationCentersForCourse(Integer courseId) {
29+
// 1. 코스가 실제로 존재하는지 확인 (안정성)
30+
if (!courseRepository.existsById(courseId)) {
31+
throw new CustomException(ErrorCode.COURSE_NOT_FOUND);
32+
}
33+
34+
// 2. PlaceRepository를 사용해 해당 코스의 '인증센터'들을 모두 조회
35+
List<Place> centers = placeRepository.findByCategoryAndCourseId("인증센터", courseId);
36+
37+
// 3. 조회된 Place 엔티티 리스트를 CertificationCenterDto 리스트로 변환하여 반환
38+
return centers.stream()
39+
.map(CertificationCenterDto::from)
40+
.toList();
41+
}
42+
}

0 commit comments

Comments
 (0)