Skip to content

Commit

Permalink
Merge pull request #21 from kakao-tech-campus-2nd-step3/feat/#6-video…
Browse files Browse the repository at this point in the history
…Filter

[Feat] #6 로그인 없이 공통으로 조회할 수 있는 다양한 조건의 비디오 조회 기능을 구현했어요!
  • Loading branch information
sanghee0820 authored Oct 2, 2024
2 parents 1369557 + 579dbab commit 2e1f22f
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 34 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dependencies {
implementation 'io.jsonwebtoken:jjwt-api:0.12.3'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.3'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.3'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.3'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
runtimeOnly 'com.mysql:mysql-connector-j'
Expand Down
37 changes: 34 additions & 3 deletions src/main/java/team7/inplace/video/application/VideoService.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
package team7.inplace.video.application;

import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import team7.inplace.influencer.domain.Influencer;
import team7.inplace.influencer.persistence.InfluencerRepository;
import team7.inplace.place.application.dto.PlaceForVideo;
import team7.inplace.place.domain.Place;
import team7.inplace.place.application.dto.PlaceForVideo;
import team7.inplace.place.persistence.PlaceRepository;
import team7.inplace.video.application.dto.VideoInfo;
import team7.inplace.video.domain.Video;
import team7.inplace.video.persistence.VideoRepository;
import team7.inplace.video.presentation.dto.VideoSearchParams;

import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class VideoService {
private final VideoRepository videoRepository;
private final InfluencerRepository influencerRepository;
private final PlaceRepository placeRepository;

public List<VideoInfo> findByInfluencer(List<String> influencers) {
// 인플루언서 정보 처리
Expand All @@ -31,6 +37,31 @@ public List<VideoInfo> findByInfluencer(List<String> influencers) {
return videoToInfo(savedVideos);
}

public List<VideoInfo> findAllDesc() {
// id를 기준으로 내림차순 정렬하여 비디오 정보 불러오기
List<Video> savedVideos = videoRepository.findAllByOrderByIdDesc();

// DTO 형식에 맞게 대입
return videoToInfo(savedVideos);
}

public List<VideoInfo> findBySurround(VideoSearchParams videoSearchParams, Pageable pageable) {
Page<Place> placesByDistance = placeRepository.getPlacesByDistance(
videoSearchParams.longitude(),
videoSearchParams.latitude(),
pageable
);

List<Place> places = placesByDistance.getContent();
List<Video> videos = new ArrayList<>();
for (Place place : places) {
if(videos.size() == places.size())
break;
videos.add(videoRepository.findTopByPlaceOrderByIdDesc(place));
}
return videoToInfo(videos);
}

private List<VideoInfo> videoToInfo(List<Video> savedVideos) {
List<VideoInfo> videoInfos = new ArrayList<>();
for (Video savedVideo : savedVideos) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package team7.inplace.video.persistence;

import org.springframework.data.jpa.repository.JpaRepository;
import team7.inplace.place.domain.Place;
import team7.inplace.video.domain.Video;

import java.util.List;

public interface VideoRepository extends JpaRepository<Video, Long> {
List<Video> findVideosByInfluencerIdIn(List<Long> influencerIds);

List<Video> findAllByOrderByIdDesc();

Video findTopByPlaceOrderByIdDesc(Place place);
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,81 @@
package team7.inplace.video.presentation;

import java.util.List;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import team7.inplace.video.application.VideoService;
import org.springframework.web.bind.annotation.*;
import team7.inplace.video.application.dto.VideoInfo;
import team7.inplace.video.presentation.dto.VideoResponse;
import team7.inplace.video.application.VideoService;
import team7.inplace.video.presentation.dto.VideoSearchParams;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/videos")
public class VideoController {
private final VideoService videoService;

// 내 인플루언서가 방문한 그 곳 ( 토큰 0 )
@GetMapping("/video")
public ResponseEntity<List<VideoResponse>> readByInfluencer(
@RequestParam(name = "influencer", required = false) List<String> influencers
// 토큰 필요 메서드
@GetMapping()
@Operation(
summary = "내 인플루언서가 방문한 or 내 주변 그곳 ",
description = "토큰의 유무에 따라 다른 동작을 수행합니다."
)
public ResponseEntity<List<VideoResponse>> readVideos(
HttpServletRequest request,
@RequestParam(name = "influencer", required = false) List<String> influencers,
@ModelAttribute VideoSearchParams searchParams,
@RequestParam(defaultValue = "0", required = false) int page,
@RequestParam(defaultValue = "10", required = false) int size
) {
// Authorization 헤더 추출
String authHeader = request.getHeader("Authorization");
// 토큰 존재 여부 검사
if(authHeader != null && authHeader.startsWith("Bearer ")) {
// 토큰 유효성 검사

// 토큰이 있는 경우
return readByInfluencer(influencers);
}

// 토큰이 없는 경우
return readBySurround(searchParams, page, size);
}

private ResponseEntity<List<VideoResponse>> readByInfluencer(List<String> influencers){
List<VideoInfo> videoInfos = videoService.findByInfluencer(influencers);
List<VideoResponse> videoResponses = videoInfos.stream().map(VideoResponse::from).toList();
return new ResponseEntity<>(videoResponses, HttpStatus.OK);
}

private ResponseEntity<List<VideoResponse>> readBySurround(VideoSearchParams searchParams, int page, int size) {
Pageable pageable = PageRequest.of(page, size);
List<VideoInfo> videoInfos = videoService.findBySurround(searchParams, pageable);
List<VideoResponse> videoResponses = videoInfos.stream().map(VideoResponse::from).toList();
return new ResponseEntity<>(videoResponses, HttpStatus.OK);
}

@GetMapping("/new")
@Operation(summary = "새로 등록된 그 곳", description = "id를 기준으로 내림차순 정렬한 Video 정보를 조회합니다.")
public ResponseEntity<List<VideoResponse>> readByNew() {
List<VideoInfo> videoInfos = videoService.findAllDesc();
List<VideoResponse> videoResponses = videoInfos.stream().map(VideoResponse::from).toList();
return new ResponseEntity<>(videoResponses, HttpStatus.OK);
}

// 조회수 반환 기능 개발 시 개발
@GetMapping("/cool")
@Operation(summary = "쿨한 그 곳", description = "조회수를 기준으로 내림차순 정렬한 Video 정보를 조회합니다.")
public ResponseEntity<List<VideoResponse>> readByCool() {
List<VideoResponse> videoResponses = new ArrayList<>();
return new ResponseEntity<>(videoResponses, HttpStatus.OK);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package team7.inplace.video.presentation.dto;

public record VideoSearchParams(
String longitude,
String latitude
) {
}
2 changes: 1 addition & 1 deletion src/main/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
spring:
config:
import: classpath:application-security.yaml, classpath:application-youtube.yaml
import: classpath:application-security.yaml, classpath:application-youtube.yaml, optional:file:.env[.properties]
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package team7.inplace.VideoTest.domain;
package team7.inplace.video.domain;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import team7.inplace.influencer.domain.Influencer;
import team7.inplace.place.domain.Place;
import team7.inplace.video.domain.Video;

public class VideoTest {
@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package team7.inplace.VideoTest.repository;
package team7.inplace.video.repository;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -13,8 +13,7 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.annotation.DirtiesContext;
import team7.inplace.influencer.domain.Influencer;
import team7.inplace.place.domain.Category;
import team7.inplace.place.domain.Place;
import team7.inplace.place.domain.*;
import team7.inplace.video.domain.Video;
import team7.inplace.video.persistence.VideoRepository;

Expand All @@ -25,25 +24,30 @@ public class VideoRepositoryTest {
EntityManager entityManager;
@Autowired
private VideoRepository videoRepository;
private Place place;

@BeforeEach
@Transactional
void init() {
Place place = Place.builder()
place = Place.builder()
.name("Test Place")
.pet(false)
.wifi(true)
.parking(false)
.fordisabled(true)
.nursery(false)
.smokingroom(false)
.address1("Address 1")
.address2("Address 2")
.address3("Address 3")
.address(new Address("Address 1", "Address 2", "Address 3"))
.menuImgUrl("menu.jpg")
.category(Category.CAFE)
.longitude("127.0")
.latitude("37.0")
.coordinate(new Coordinate("127.0", "37.0"))
.timeList(Arrays.asList(
new PlaceTime("Opening Hours", "9:00 AM", "Monday"),
new PlaceTime("Closing Hours", "10:00 PM", "Monday")
))
.menuList(Arrays.asList(
new Menu(5000L, true, "Coffee"),
new Menu(7000L, false, "Cake")
))
.build();
entityManager.persist(place);

Expand All @@ -69,6 +73,7 @@ void init() {
void test1() {
// given
/* Before Each */

// when
List<Long> influencerIds = new ArrayList<>();
influencerIds.add(1L);
Expand All @@ -77,4 +82,33 @@ void test1() {
// then
Assertions.assertThat(savedVideos.size()).isEqualTo(3);
}

@Test
@DisplayName("findAllByOrderByIdDesc Test")
void test2() {
// given
/* Before Each */

// when
List<Video> videos = videoRepository.findAllByOrderByIdDesc();

// then
Long number = 5L;
for (Video video : videos) {
Assertions.assertThat(video.getId()).isEqualTo(number);
number -= 1L;
}
}

@Test
@DisplayName("findTopByPlaceOrderByIdDesc Test")
void test3() {
// given

// when
Video video = videoRepository.findTopByPlaceOrderByIdDesc(place);

// then
Assertions.assertThat(video.getId()).isEqualTo(5L);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package team7.inplace.VideoTest.service;
package team7.inplace.video.service;

import static org.mockito.BDDMockito.given;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
Expand All @@ -14,8 +15,7 @@
import org.mockito.junit.jupiter.MockitoExtension;
import team7.inplace.influencer.domain.Influencer;
import team7.inplace.influencer.persistence.InfluencerRepository;
import team7.inplace.place.domain.Category;
import team7.inplace.place.domain.Place;
import team7.inplace.place.domain.*;
import team7.inplace.video.application.VideoService;
import team7.inplace.video.application.dto.VideoInfo;
import team7.inplace.video.domain.Video;
Expand Down Expand Up @@ -45,13 +45,18 @@ void test1() {
.fordisabled(true)
.nursery(false)
.smokingroom(false)
.address1("Address 1")
.address2("Address 2")
.address3("Address 3")
.address(new Address("Address 1", "Address 2", "Address 3"))
.menuImgUrl("menu.jpg")
.category(Category.CAFE)
.longitude("127.0")
.latitude("37.0")
.coordinate(new Coordinate("127.0", "37.0"))
.timeList(Arrays.asList(
new PlaceTime("Opening Hours", "9:00 AM", "Monday"),
new PlaceTime("Closing Hours", "10:00 PM", "Monday")
))
.menuList(Arrays.asList(
new Menu(5000L, true, "Coffee"),
new Menu(7000L, false, "Cake")
))
.build();
Influencer influencer = new Influencer("성시경", "가수", "imgUrl");
Video video = new Video("url", influencer, place);
Expand Down

0 comments on commit 2e1f22f

Please sign in to comment.