Skip to content

Commit a5b2e32

Browse files
authored
Merge pull request #111 from Team-Festimate/feat/#110
[feat] #110 매칭 상세조회 API 기능 구현
2 parents 28eea30 + 8ac5fb3 commit a5b2e32

File tree

6 files changed

+97
-1
lines changed

6 files changed

+97
-1
lines changed

src/main/java/org/festimate/team/api/matching/MatchingController.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.festimate.team.api.matching;
22

33
import lombok.RequiredArgsConstructor;
4+
import org.festimate.team.api.matching.dto.MatchingDetailInfo;
45
import org.festimate.team.api.matching.dto.MatchingListResponse;
56
import org.festimate.team.api.matching.dto.MatchingStatusResponse;
67
import org.festimate.team.domain.matching.service.MatchingService;
@@ -38,4 +39,16 @@ public ResponseEntity<ApiResponse<MatchingListResponse>> getMatching(
3839
MatchingListResponse response = matchingService.getMatchingList(userId, festivalId);
3940
return ResponseBuilder.ok(response);
4041
}
42+
43+
@GetMapping("/{festivalId}/matchings/{matchingId}")
44+
public ResponseEntity<ApiResponse<MatchingDetailInfo>> getMatchingDetail(
45+
@RequestHeader("Authorization") String accessToken,
46+
@PathVariable("festivalId") Long festivalId,
47+
@PathVariable("matchingId") Long matchingId
48+
) {
49+
Long userId = jwtService.parseTokenAndGetUserId(accessToken);
50+
51+
MatchingDetailInfo response = matchingService.getMatchingDetail(userId, festivalId, matchingId);
52+
return ResponseBuilder.ok(response);
53+
}
4154
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.festimate.team.api.matching.dto;
2+
3+
import org.festimate.team.domain.matching.entity.Matching;
4+
import org.festimate.team.domain.participant.entity.Participant;
5+
import org.festimate.team.domain.participant.entity.TypeResult;
6+
import org.festimate.team.domain.user.entity.AppearanceType;
7+
import org.festimate.team.domain.user.entity.Gender;
8+
import org.festimate.team.domain.user.entity.Mbti;
9+
10+
public record MatchingDetailInfo(
11+
String nickname,
12+
Gender gender,
13+
Integer birthYear,
14+
Mbti mbti,
15+
AppearanceType appearance,
16+
String introduction,
17+
String message,
18+
TypeResult typeResult
19+
) {
20+
public static MatchingDetailInfo from(Matching matching) {
21+
Participant participant = matching.getTargetParticipant();
22+
return new MatchingDetailInfo(
23+
participant.getUser().getNickname(),
24+
participant.getUser().getGender(),
25+
participant.getUser().getBirthYear(),
26+
participant.getUser().getMbti(),
27+
participant.getUser().getAppearanceType(),
28+
participant.getIntroduction(),
29+
participant.getMessage(),
30+
participant.getTypeResult()
31+
);
32+
}
33+
}

src/main/java/org/festimate/team/domain/matching/repository/MatchingRepository.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,6 @@ boolean existsCompletedMatching(
7575
""")
7676
List<Matching> findAllMatchingsByApplicantParticipant(Participant participant);
7777

78+
Optional<Matching> findByMatchingId(Long matchingId);
7879
}
7980

src/main/java/org/festimate/team/domain/matching/service/MatchingService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.festimate.team.domain.matching.service;
22

3+
import org.festimate.team.api.matching.dto.MatchingDetailInfo;
34
import org.festimate.team.api.matching.dto.MatchingListResponse;
45
import org.festimate.team.api.matching.dto.MatchingStatusResponse;
56
import org.festimate.team.domain.participant.entity.Participant;
@@ -11,6 +12,8 @@ public interface MatchingService {
1112

1213
MatchingListResponse getMatchingList(Long userId, Long festivalId);
1314

15+
MatchingDetailInfo getMatchingDetail(Long userId, Long festivalId, Long matchingId);
16+
1417
Optional<Participant> findBestCandidateByPriority(long festivalId, Participant participant);
1518

1619
void matchPendingParticipants(Participant newParticipant);

src/main/java/org/festimate/team/domain/matching/service/impl/MatchingServiceImpl.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import lombok.RequiredArgsConstructor;
44
import lombok.extern.slf4j.Slf4j;
5+
import org.festimate.team.api.matching.dto.MatchingDetailInfo;
56
import org.festimate.team.api.matching.dto.MatchingInfo;
67
import org.festimate.team.api.matching.dto.MatchingListResponse;
78
import org.festimate.team.api.matching.dto.MatchingStatusResponse;
@@ -17,6 +18,8 @@
1718
import org.festimate.team.domain.point.service.PointService;
1819
import org.festimate.team.domain.user.entity.Gender;
1920
import org.festimate.team.domain.user.service.UserService;
21+
import org.festimate.team.global.exception.FestimateException;
22+
import org.festimate.team.global.response.ResponseError;
2023
import org.springframework.stereotype.Service;
2124
import org.springframework.transaction.annotation.Transactional;
2225

@@ -66,6 +69,19 @@ public MatchingListResponse getMatchingList(Long userId, Long festivalId) {
6669
return MatchingListResponse.from(matchings);
6770
}
6871

72+
@Transactional(readOnly = true)
73+
@Override
74+
public MatchingDetailInfo getMatchingDetail(Long userId, Long festivalId, Long matchingId) {
75+
Festival festival = festivalService.getFestivalByIdOrThrow(festivalId);
76+
participantService.getParticipantOrThrow(userService.getUserByIdOrThrow(userId), festival);
77+
Matching matching = matchingRepository.findByMatchingId(matchingId)
78+
.orElseThrow(() -> new FestimateException(ResponseError.TARGET_NOT_FOUND));
79+
if (!matching.getFestival().getFestivalId().equals(festivalId)) {
80+
throw new FestimateException(ResponseError.FORBIDDEN_RESOURCE);
81+
}
82+
return MatchingDetailInfo.from(matching);
83+
}
84+
6985
@Transactional
7086
protected Matching saveMatching(Festival festival, Optional<Participant> targetParticipantOptional, Participant participant) {
7187
Matching matching;

src/test/java/org/festimate/team/domain/matching/service/impl/MatchingServiceImplTest.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import org.festimate.team.domain.user.entity.Gender;
1414
import org.festimate.team.domain.user.entity.User;
1515
import org.festimate.team.domain.user.service.UserService;
16+
import org.festimate.team.global.exception.FestimateException;
17+
import org.festimate.team.global.response.ResponseError;
1618
import org.junit.jupiter.api.BeforeEach;
1719
import org.junit.jupiter.api.DisplayName;
1820
import org.junit.jupiter.api.Test;
@@ -26,11 +28,12 @@
2628
import java.util.List;
2729
import java.util.Optional;
2830

31+
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
2932
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
3033
import static org.festimate.team.common.mock.MockFactory.*;
3134
import static org.mockito.Mockito.when;
3235

33-
public class MatchingServiceImplTest {
36+
class MatchingServiceImplTest {
3437
@Mock
3538
private MatchingRepository matchingRepository;
3639

@@ -240,4 +243,31 @@ void findBestCandidateByPriority_empty() {
240243
assertThat(result).isEmpty();
241244
}
242245

246+
@Test
247+
@DisplayName("매칭 상세 조회 - 매칭과 페스티벌이 일치하지 않는 경우 예외 발생")
248+
void getMatchingDetail_invalidFestival_throwsException() {
249+
// given
250+
User user = mockUser("사용자", Gender.MAN, 1L);
251+
Festival requestedFestival = mockFestival(user, 1L, LocalDate.now().minusDays(1), LocalDate.now().plusDays(1));
252+
Festival otherFestival = mockFestival(user, 2L, LocalDate.now().minusDays(1), LocalDate.now().plusDays(1));
253+
254+
Participant participant = mockParticipant(user, requestedFestival, TypeResult.INFLUENCER, 1L);
255+
Matching mismatchedMatching = Matching.builder()
256+
.festival(otherFestival)
257+
.applicantParticipant(participant)
258+
.targetParticipant(null)
259+
.status(MatchingStatus.PENDING)
260+
.matchDate(LocalDateTime.now())
261+
.build();
262+
263+
when(userService.getUserByIdOrThrow(user.getUserId())).thenReturn(user);
264+
when(festivalService.getFestivalByIdOrThrow(requestedFestival.getFestivalId())).thenReturn(requestedFestival);
265+
when(participantService.getParticipantOrThrow(user, requestedFestival)).thenReturn(participant);
266+
when(matchingRepository.findByMatchingId(1L)).thenReturn(Optional.of(mismatchedMatching));
267+
268+
// when & then
269+
assertThatThrownBy(() -> matchingService.getMatchingDetail(user.getUserId(), requestedFestival.getFestivalId(), 1L))
270+
.isInstanceOf(FestimateException.class)
271+
.hasMessage(ResponseError.FORBIDDEN_RESOURCE.getMessage());
272+
}
243273
}

0 commit comments

Comments
 (0)