Skip to content

Commit

Permalink
Merge pull request #41 from kakao-tech-campus-2nd-step3/feat/#40-Vide…
Browse files Browse the repository at this point in the history
…oMyInfluencer

[Feat] #40 좋아요한 인플루언서에 대한 동작을 구현해보아요
  • Loading branch information
sanghee0820 authored Oct 9, 2024
2 parents 5017bf4 + e318c18 commit 38e5617
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,49 @@
package team7.inplace.influencer.application;

import java.util.List;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import team7.inplace.global.exception.InplaceException;
import team7.inplace.global.exception.code.AuthorizationErrorCode;
import team7.inplace.influencer.application.dto.InfluencerInfo;
import team7.inplace.influencer.domain.Influencer;
import team7.inplace.influencer.persistence.InfluencerRepository;
import team7.inplace.influencer.presentation.dto.InfluencerRequestParam;
import team7.inplace.userFavoriteInfluencer.domain.UserFavoriteInfluencer;
import team7.inplace.userFavoriteInfluencer.persistent.UserFavoriteInfluencerRepository;
import team7.inplace.security.util.AuthorizationUtil;
import team7.inplace.user.domain.User;
import team7.inplace.user.persistence.UserRepository;

@RequiredArgsConstructor
@Service
public class InfluencerService {

private final InfluencerRepository influencerRepository;
private final UserFavoriteInfluencerRepository favoriteRepository;
private final UserRepository userRepository;

@Transactional(readOnly = true)
public List<InfluencerInfo> getAllInfluencers() {
return influencerRepository.findAll().stream()
.map(InfluencerInfo::from)
.toList();
}

public void likeToInfluencer(InfluencerRequestParam param){
String username = AuthorizationUtil.getUsername();
if(StringUtils.hasText(username)){
throw InplaceException.of(AuthorizationErrorCode.TOKEN_IS_EMPTY);
}

User user = userRepository.findByUsername(username).orElseThrow();
Influencer influencer = influencerRepository.findById(param.influencerId()).orElseThrow();

UserFavoriteInfluencer favorite = new UserFavoriteInfluencer(user, influencer);
favorite.check(param.likes());
favoriteRepository.save(favorite);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import team7.inplace.influencer.application.InfluencerService;
import team7.inplace.influencer.application.dto.InfluencerInfo;
import team7.inplace.influencer.presentation.dto.InfluencerListResponse;
import team7.inplace.influencer.presentation.dto.InfluencerRequestParam;
import team7.inplace.influencer.presentation.dto.InfluencerResponse;

@RequiredArgsConstructor
@RestController
@RequestMapping("/influencers")
public class InfluencerController {

private final InfluencerService influencerService;

@GetMapping("/influencers")
@GetMapping()
public ResponseEntity<InfluencerListResponse> getAllInfluencers() {
List<InfluencerInfo> influencersDtoList = influencerService.getAllInfluencers();
List<InfluencerResponse> influencers = influencersDtoList.stream()
Expand All @@ -28,4 +29,11 @@ public ResponseEntity<InfluencerListResponse> getAllInfluencers() {
return new ResponseEntity<>(response, HttpStatus.OK);
}

@PostMapping("/likes")
public ResponseEntity<Void> likeToInfluencer(
@ModelAttribute InfluencerRequestParam param
) {
influencerService.likeToInfluencer(param);
return new ResponseEntity<>(HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package team7.inplace.influencer.presentation.dto;

public record InfluencerRequestParam(
Long influencerId,
Boolean likes
) {
}
18 changes: 14 additions & 4 deletions src/main/java/team7/inplace/user/application/UserService.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package team7.inplace.user.application;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import team7.inplace.influencer.domain.Influencer;
import team7.inplace.userFavoriteInfluencer.domain.UserFavoriteInfluencer;
import team7.inplace.userFavoriteInfluencer.persistent.UserFavoriteInfluencerRepository;
import team7.inplace.user.application.dto.UserCommand;
import team7.inplace.user.domain.User;
import team7.inplace.user.persistence.UserRepository;

import java.util.List;

@Service
@RequiredArgsConstructor
public class UserService {

private final UserRepository userRepository;

public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
private final UserFavoriteInfluencerRepository userFavoriteInfluencerRepository;

@Transactional
public void registerUser(UserCommand.Create userCreate) {
Expand All @@ -30,4 +34,10 @@ public boolean isExistUser(String username) {
public UserCommand.Info getUserByUsername(String username) {
return UserCommand.Info.of(userRepository.findByUsername(username).orElseThrow());
}

@Transactional(readOnly = true)
public List<Long> getInfluencerIdsByUsername(Long userId) {
List<UserFavoriteInfluencer> likes = userFavoriteInfluencerRepository.findByUserId(userId);
return likes.stream().map(UserFavoriteInfluencer::getInfluencer).map(Influencer::getId).toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package team7.inplace.userFavoriteInfluencer.domain;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import team7.inplace.influencer.domain.Influencer;
import team7.inplace.user.domain.User;

import static jakarta.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;

@Getter
@RequiredArgsConstructor
@NoArgsConstructor(access = PROTECTED)
@Entity
public class UserFavoriteInfluencer {
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
@ManyToOne
@NonNull
@JoinColumn(name = "user_id")
private User user;
@ManyToOne
@NonNull
@JoinColumn(name = "influencer_id")
private Influencer influencer;
@Column
private boolean like = false;

public void check(boolean check) {
if (check) {
like();
return;
}
dislike();
}

private void like() {
this.like = true;
}

private void dislike() {
this.like = false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package team7.inplace.userFavoriteInfluencer.persistent;

import org.springframework.data.jpa.repository.JpaRepository;
import team7.inplace.userFavoriteInfluencer.domain.UserFavoriteInfluencer;
import team7.inplace.user.domain.User;

import java.util.List;

public interface UserFavoriteInfluencerRepository extends JpaRepository<UserFavoriteInfluencer, Long> {
List<UserFavoriteInfluencer> findByUserId(Long userId);
}
22 changes: 21 additions & 1 deletion src/main/java/team7/inplace/video/application/VideoService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import team7.inplace.global.exception.InplaceException;
import team7.inplace.global.exception.code.AuthorizationErrorCode;
import team7.inplace.global.exception.code.VideoErrorCode;
import team7.inplace.place.application.dto.PlaceForVideo;
import team7.inplace.place.domain.Place;
import team7.inplace.place.persistence.PlaceRepository;
import team7.inplace.security.util.AuthorizationUtil;
import team7.inplace.user.application.UserService;
import team7.inplace.video.application.dto.VideoInfo;
import team7.inplace.video.domain.Video;
import team7.inplace.video.persistence.VideoRepository;
Expand All @@ -24,6 +29,7 @@ public class VideoService {

private final VideoRepository videoRepository;
private final PlaceRepository placeRepository;
private final UserService userService;

public Page<VideoInfo> getVideosBySurround(VideoSearchParams videoSearchParams, Pageable pageable) {
Page<Place> places = placeRepository.getPlacesByDistance(
Expand All @@ -37,7 +43,7 @@ public Page<VideoInfo> getVideosBySurround(VideoSearchParams videoSearchParams,
if (videos.size() == places.getSize())
break;
videos.add(videoRepository.findTopByPlaceOrderByIdDesc(place)
.orElseThrow(()-> InplaceException.of(AuthorizationErrorCode.NO_SUCH_VIDEO)));
.orElseThrow(()-> InplaceException.of(VideoErrorCode.NO_SUCH_VIDEO)));
}
return new PageImpl<>(videos).map(this::videoToInfo);
}
Expand All @@ -50,6 +56,20 @@ public Page<VideoInfo> getAllVideosDesc(Pageable pageable) {
return videos.map(this::videoToInfo);
}

public Page<VideoInfo> getVideosByMyInfluencer(Pageable pageable){
// User 정보를 쿠키에서 추출
Long userId = AuthorizationUtil.getUserId();
// 토큰 정보에 대한 검증
if(ObjectUtils.isEmpty(userId)) {
throw InplaceException.of(AuthorizationErrorCode.TOKEN_IS_EMPTY);
}
// 유저 정보를 이용하여 유저가 좋아요를 누른 인플루언서 id 리스트를 조회
List<Long> influencerIds = userService.getInfluencerIdsByUsername(userId);
// 인플루언서 id 리스트를 이용하여 해당 인플루언서의 비디오들을 조회
Page<Video> videos = videoRepository.findVideosByInfluencerIdIn(influencerIds, pageable);
return videos.map(this::videoToInfo);
}

private VideoInfo videoToInfo(Video savedVideo) {
Place place = savedVideo.getPlace();
String alias = AliasUtil.makeAlias(
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/team7/inplace/video/domain/Video.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@Entity
@Getter
@NoArgsConstructor(access = PROTECTED)
@RequiredArgsConstructor // 테스팅을 위한 부분 추가, 협의 하에 다른 방식 채택 가능
@RequiredArgsConstructor
public class Video {

@Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,14 @@ public ResponseEntity<Page<VideoResponse>> readByCool(
List<VideoResponse> videoResponses = new ArrayList<>();
return new ResponseEntity<>(new PageImpl<>(videoResponses), HttpStatus.OK);
}

// 토큰 필요 메서드
@GetMapping("/my")
public ResponseEntity<Page<VideoResponse>> readByInfluencer(
@PageableDefault(page = 0, size = 10) Pageable pageable
) {
Page<VideoResponse> videoResponses = videoService.getVideosByMyInfluencer(pageable)
.map(VideoResponse::from);
return new ResponseEntity<>(videoResponses, HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestParam;
import team7.inplace.video.presentation.dto.VideoResponse;
import team7.inplace.video.presentation.dto.VideoSearchParams;

Expand Down Expand Up @@ -34,4 +35,12 @@ ResponseEntity<Page<VideoResponse>> readByNew(
ResponseEntity<Page<VideoResponse>> readByCool(
@PageableDefault(page = 0, size = 10) Pageable pageable
);

@Operation(
summary = "내 인플루언서의 비디오 반환",
description = "내가 좋아요를 누른 인플루언서의 Video 정보를 조회합니다."
)
ResponseEntity<Page<VideoResponse>> readByInfluencer(
@PageableDefault(page = 0, size = 10) Pageable pageable
);
}

0 comments on commit 38e5617

Please sign in to comment.