diff --git a/src/main/java/goorm/back/zo6/attend/application/AttendDtoConverter.java b/src/main/java/goorm/back/zo6/attend/application/AttendDtoConverter.java new file mode 100644 index 0000000..0ba4c0e --- /dev/null +++ b/src/main/java/goorm/back/zo6/attend/application/AttendDtoConverter.java @@ -0,0 +1,63 @@ +package goorm.back.zo6.attend.application; + +import goorm.back.zo6.attend.dto.ConferenceInfoResponse; +import goorm.back.zo6.attend.dto.SessionInfo; +import goorm.back.zo6.conference.infrastructure.S3FileService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@RequiredArgsConstructor +public class AttendDtoConverter { + + private final S3FileService s3FileService; + + public ConferenceInfoResponse convertConferenceInfoResponse(ConferenceInfoResponse original) { + String presignedConferenceImageUrl = s3FileService.generatePresignedUrl(original.getImageUrl(), 60); + + List sessionsWithUrl = null; + + if (original.getSessions() != null) { + sessionsWithUrl = original.getSessions().stream() + .map(this::convertSessionInfo) + .collect(Collectors.toList()); + } + + return new ConferenceInfoResponse( + original.getId(), + original.getName(), + original.getDescription(), + original.getLocation(), + original.getStartTime(), + original.getEndTime(), + original.getCapacity(), + original.getHasSessions(), + presignedConferenceImageUrl, + original.getIsActive(), + original.isAttend(), + sessionsWithUrl + ); + } + + private SessionInfo convertSessionInfo(SessionInfo original) { + String speakerImagePresignedUrl = s3FileService.generatePresignedUrl(original.getSpeakerImageKey(), 60); + + return new SessionInfo( + original.getId(), + original.getName(), + original.getCapacity(), + original.getLocation(), + original.getStartTime(), + original.getEndTime(), + original.getSummary(), + original.getSpeakerName(), + original.getSpeakerOrganization(), + speakerImagePresignedUrl, + original.isActive(), + original.isAttend() + ); + } +} diff --git a/src/main/java/goorm/back/zo6/attend/application/AttendService.java b/src/main/java/goorm/back/zo6/attend/application/AttendService.java index b94e067..40b41ac 100644 --- a/src/main/java/goorm/back/zo6/attend/application/AttendService.java +++ b/src/main/java/goorm/back/zo6/attend/application/AttendService.java @@ -21,6 +21,7 @@ public class AttendService { private final AttendRepository attendRepository; private final UserRepository userRepository; private final AttendRedisService attendRedisService; + private final AttendDtoConverter attendDtoConverter; // 참석 정보 저장 @Transactional @@ -45,7 +46,7 @@ public AttendanceSummaryResponse getAttendanceSummary(Long conferenceId, Long se // 해당 유저의 컨퍼런스/세션 참석 데이터를 조회 public ConferenceInfoResponse findAllByToken(Long userId, Long conferenceId) { ConferenceInfoResponse conferenceInfoDto = attendRepository.findAttendInfoByUserAndConference(userId, conferenceId); - return conferenceInfoDto; + return attendDtoConverter.convertConferenceInfoResponse(conferenceInfoDto); } // 참석 객체로 변환 private Attend convertToAttend(Long id, AttendData attendDataDto) { diff --git a/src/main/java/goorm/back/zo6/conference/application/shared/ConferenceFactory.java b/src/main/java/goorm/back/zo6/conference/application/shared/ConferenceFactory.java index 4e4cb29..94c2473 100644 --- a/src/main/java/goorm/back/zo6/conference/application/shared/ConferenceFactory.java +++ b/src/main/java/goorm/back/zo6/conference/application/shared/ConferenceFactory.java @@ -25,7 +25,7 @@ public Conference createConference(ConferenceCreateRequest request) { } private String parseS3ImageKeyFromUrl(String imageUrl) { - if (imageUrl == null || !imageUrl.contains("/conference/images/")) { + if (imageUrl == null || !imageUrl.contains("/conference/images")) { throw new IllegalArgumentException("Invalid image url"); } return imageUrl.substring(imageUrl.indexOf("conference/images")); diff --git a/src/main/java/goorm/back/zo6/conference/application/shared/SessionFactory.java b/src/main/java/goorm/back/zo6/conference/application/shared/SessionFactory.java index a7d96c6..7df8ba3 100644 --- a/src/main/java/goorm/back/zo6/conference/application/shared/SessionFactory.java +++ b/src/main/java/goorm/back/zo6/conference/application/shared/SessionFactory.java @@ -47,10 +47,10 @@ public Session createSession(SessionCreateRequest request, Conference conference .build(); } - private String parseSpeakerImageKey(String speakerImage) { - if (speakerImage == null || !speakerImage.contains("/conference/speaker/")) { + private String parseSpeakerImageKey(String speakerImageUrl) { + if (speakerImageUrl == null || !speakerImageUrl.contains("/conference/images")) { throw new IllegalArgumentException("Invalid speaker image url"); } - return speakerImage.substring(speakerImage.indexOf("conference/speaker/")); + return speakerImageUrl.substring(speakerImageUrl.indexOf("conference/images")); } } diff --git a/src/main/java/goorm/back/zo6/conference/infrastructure/S3FileService.java b/src/main/java/goorm/back/zo6/conference/infrastructure/S3FileService.java index e3e8af3..794fcfa 100644 --- a/src/main/java/goorm/back/zo6/conference/infrastructure/S3FileService.java +++ b/src/main/java/goorm/back/zo6/conference/infrastructure/S3FileService.java @@ -3,18 +3,13 @@ import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; -import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.GetObjectRequest; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest; import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest; -import java.io.IOException; import java.time.Duration; -import java.util.UUID; @Service @RequiredArgsConstructor diff --git a/src/test/java/goorm/back/zo6/attend/application/AttendServiceTest.java b/src/test/java/goorm/back/zo6/attend/application/AttendServiceTest.java index fb76335..45de43c 100644 --- a/src/test/java/goorm/back/zo6/attend/application/AttendServiceTest.java +++ b/src/test/java/goorm/back/zo6/attend/application/AttendServiceTest.java @@ -6,6 +6,7 @@ import goorm.back.zo6.attend.infrastructure.AttendRedisService; import goorm.back.zo6.common.exception.CustomException; import goorm.back.zo6.common.exception.ErrorCode; +import goorm.back.zo6.conference.domain.Conference; import goorm.back.zo6.user.domain.User; import goorm.back.zo6.user.domain.UserRepository; import org.junit.jupiter.api.DisplayName; @@ -35,6 +36,8 @@ class AttendServiceTest { private UserRepository userRepository; @Mock private AttendRedisService attendRedisService; + @Mock + private AttendDtoConverter attendDtoConverter; @Test @DisplayName("컨퍼런스/세션 기반 예매자들 조회 와 참석 여부 및 행사 메타데이터를 조회 - 성공") @@ -175,10 +178,29 @@ void findAllByToken_AttendSuccess() { when(attendRepository.findAttendInfoByUserAndConference(userId, conferenceId)) .thenReturn(mockResponse); + when(attendDtoConverter.convertConferenceInfoResponse(any(ConferenceInfoResponse.class))) + .thenAnswer(invocation -> { + ConferenceInfoResponse arg = invocation.getArgument(0); + return new ConferenceInfoResponse( + arg.getId(), + arg.getName(), + arg.getDescription(), + arg.getLocation(), + arg.getStartTime(), + arg.getEndTime(), + arg.getCapacity(), + arg.getHasSessions(), + "https://mockimage.com/" + arg.getImageUrl(), + arg.getIsActive(), + arg.isAttend(), + arg.getSessions() + ); + }); // when ConferenceInfoResponse result = attendService.findAllByToken(userId, conferenceId); + // then assertNotNull(result); assertEquals(conferenceId, result.getId()); @@ -222,6 +244,24 @@ void findAllByToken_NoneAttendSuccess() { when(attendRepository.findAttendInfoByUserAndConference(userId, conferenceId)) .thenReturn(mockResponse); + when(attendDtoConverter.convertConferenceInfoResponse(any(ConferenceInfoResponse.class))) + .thenAnswer(invocation -> { + ConferenceInfoResponse arg = invocation.getArgument(0); + return new ConferenceInfoResponse( + arg.getId(), + arg.getName(), + arg.getDescription(), + arg.getLocation(), + arg.getStartTime(), + arg.getEndTime(), + arg.getCapacity(), + arg.getHasSessions(), + "https://mockimage.com/" + arg.getImageUrl(), + arg.getIsActive(), + arg.isAttend(), + arg.getSessions() + ); + }); // when ConferenceInfoResponse result = attendService.findAllByToken(userId, conferenceId); diff --git a/src/test/java/goorm/back/zo6/attend/presentation/AttendControllerTest.java b/src/test/java/goorm/back/zo6/attend/presentation/AttendControllerTest.java index 808e99a..b341245 100644 --- a/src/test/java/goorm/back/zo6/attend/presentation/AttendControllerTest.java +++ b/src/test/java/goorm/back/zo6/attend/presentation/AttendControllerTest.java @@ -1,6 +1,7 @@ package goorm.back.zo6.attend.presentation; import com.fasterxml.jackson.databind.ObjectMapper; +import goorm.back.zo6.attend.application.AttendDtoConverter; import goorm.back.zo6.attend.application.AttendService; import goorm.back.zo6.attend.domain.Attend; import goorm.back.zo6.attend.dto.AttendanceSummaryResponse; @@ -13,6 +14,7 @@ import goorm.back.zo6.conference.domain.Conference; import goorm.back.zo6.conference.domain.Session; import goorm.back.zo6.conference.infrastructure.ConferenceJpaRepository; +import goorm.back.zo6.conference.infrastructure.S3FileService; import goorm.back.zo6.conference.infrastructure.SessionJpaRepository; import goorm.back.zo6.reservation.domain.Reservation; import goorm.back.zo6.reservation.domain.ReservationSession; @@ -42,6 +44,8 @@ import java.util.Optional; import static org.hamcrest.Matchers.hasSize; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; @@ -86,6 +90,12 @@ class AttendControllerTest { @Autowired private AttendJpaRepository attendJpaRepository; + @Autowired + private AttendDtoConverter attendDtoConverter; + + @MockitoBean + private S3FileService s3FileService; + @MockitoBean private AttendRedisService attendRedisService; @@ -193,10 +203,13 @@ void getAttendanceSummary_NoAttendance_Fails() throws Exception { void findByToken_ConferenceSessionSuccess() throws Exception { // given // when & then + when(s3FileService.generatePresignedUrl(any(String.class), eq(60))).thenReturn("test.png"); + mockMvc.perform(get("/api/v1/attend") .cookie(new Cookie("Authorization", accessToken)) .param("conferenceId", String.valueOf(testConferenceA.getId())) .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) .andExpectAll( jsonPath("$.data.id").value(1),