Skip to content

Commit

Permalink
Merge pull request #143 from kakao-tech-campus-2nd-step3/feat/#142-my…
Browse files Browse the repository at this point in the history
…page

[Feat] #142 마이페이지에 필요한 정보를 반환해요
  • Loading branch information
BaeJunH0 authored Nov 13, 2024
2 parents f021468 + 72b2dd3 commit 8177a8b
Show file tree
Hide file tree
Showing 21 changed files with 414 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

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 org.springframework.transaction.annotation.Transactional;
import team7.inplace.favoriteInfluencer.application.dto.FavoriteInfluencerCommand;
Expand All @@ -10,38 +12,31 @@
import team7.inplace.favoriteInfluencer.persistent.FavoriteInfluencerRepository;
import team7.inplace.global.exception.InplaceException;
import team7.inplace.global.exception.code.AuthorizationErrorCode;
import team7.inplace.global.exception.code.UserErrorCode;
import team7.inplace.influencer.application.dto.InfluencerInfo;
import team7.inplace.influencer.domain.Influencer;
import team7.inplace.influencer.persistence.InfluencerRepository;
import team7.inplace.security.application.CurrentUserProvider;
import team7.inplace.security.util.AuthorizationUtil;
import team7.inplace.user.domain.User;
import team7.inplace.user.persistence.UserRepository;

@RequiredArgsConstructor
@Service
public class FavoriteInfluencerService {

private final InfluencerRepository influencerRepository;
private final FavoriteInfluencerRepository favoriteRepository;
private final UserRepository userRepository;
private final CurrentUserProvider currentUserProvider;

@Transactional
public void likeToInfluencer(FavoriteInfluencerCommand command) {
if (AuthorizationUtil.isNotLoginUser()) {
throw InplaceException.of(AuthorizationErrorCode.TOKEN_IS_EMPTY);
}

Long userId = AuthorizationUtil.getUserId();
User user = userRepository.findById(userId)
.orElseThrow(() -> InplaceException.of(UserErrorCode.NOT_FOUND));
User user = currentUserProvider.getCurrentUser();
Influencer influencer = influencerRepository.findById(command.influencerId()).orElseThrow();

FavoriteInfluencer favorite = favoriteRepository.findByUserIdAndInfluencerId(userId,
influencer.getId())
.orElseGet(() -> new FavoriteInfluencer(user, influencer)); // 존재하지 않으면 새로 생성

favorite.updateLike(command.likes());
favoriteRepository.save(favorite);
processFavoriteInfluencer(user, influencer, command.likes());
}

@Transactional
Expand All @@ -50,20 +45,32 @@ public void likeToManyInfluencer(FavoriteInfluencerListCommand command) {
throw InplaceException.of(AuthorizationErrorCode.TOKEN_IS_EMPTY);
}

Long userId = AuthorizationUtil.getUserId();
User user = userRepository.findById(userId)
.orElseThrow(() -> InplaceException.of(UserErrorCode.NOT_FOUND));

User user = currentUserProvider.getCurrentUser();
List<Influencer> influencers = influencerRepository.findAllById(command.influencerIds());

for (Influencer influencer : influencers) {
processFavoriteInfluencer(user, influencer, command.likes());
}
}

FavoriteInfluencer favorite = favoriteRepository.findByUserIdAndInfluencerId(userId,
influencer.getId())
.orElseGet(() -> new FavoriteInfluencer(user, influencer)); // 존재하지 않으면 새로 생성
private void processFavoriteInfluencer(User user, Influencer influencer, Boolean likes) {
FavoriteInfluencer favorite = favoriteRepository
.findByUserIdAndInfluencerId(user.getId(), influencer.getId())
.orElseGet(() -> new FavoriteInfluencer(user, influencer)); // 존재하지 않으면 새로 생성

favorite.updateLike(command.likes());
favorite.updateLike(likes);
if (favorite.getId() == null) {
favoriteRepository.save(favorite);
}
}

@Transactional(readOnly = true)
public Page<InfluencerInfo> getFavoriteInfluencers(Long userId, Pageable pageable) {
Page<FavoriteInfluencer> influencerPage = favoriteRepository.findByUserIdAndIsLikedTrue(
userId, pageable);

return influencerPage.map(
favorite -> InfluencerInfo.from(favorite.getInfluencer(), favorite.isLiked()));
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
Expand All @@ -12,6 +14,8 @@ public interface FavoriteInfluencerRepository extends JpaRepository<FavoriteInfl

List<FavoriteInfluencer> findByUserId(Long userId);

Page<FavoriteInfluencer> findByUserIdAndIsLikedTrue(Long userId, Pageable pageable);

Optional<FavoriteInfluencer> findByUserIdAndInfluencerId(Long userId, Long influencerId);

@Query("SELECT f.influencer.id FROM FavoriteInfluencer f WHERE f.user.id = :userId AND f.isLiked = true")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package team7.inplace.likedPlace.persistence;

import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import team7.inplace.likedPlace.domain.LikedPlace;

public interface LikedPlaceRepository extends JpaRepository<LikedPlace, Long> {

Optional<LikedPlace> findByUserIdAndPlaceId(Long userId, Long placeId);

Page<LikedPlace> findByUserIdAndIsLikedTrue(Long userId, Pageable pageable);
}
20 changes: 20 additions & 0 deletions src/main/java/team7/inplace/place/application/PlaceService.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import team7.inplace.global.exception.InplaceException;
import team7.inplace.global.exception.code.AuthorizationErrorCode;
Expand All @@ -21,6 +22,7 @@
import team7.inplace.place.application.command.PlacesCommand.Create;
import team7.inplace.place.application.command.PlacesCommand.PlacesCoordinateCommand;
import team7.inplace.place.application.command.PlacesCommand.PlacesFilterParamsCommand;
import team7.inplace.place.application.dto.LikedPlaceInfo;
import team7.inplace.place.application.dto.PlaceDetailInfo;
import team7.inplace.place.application.dto.PlaceInfo;
import team7.inplace.place.domain.Place;
Expand Down Expand Up @@ -214,4 +216,22 @@ public PlaceMessageCommand getPlaceMessageCommand(Long placeId) {

return PlaceMessageCommand.of(place, influencer, video);
}

public Page<LikedPlaceInfo> getLikedPlaceInfo(Long userId, Pageable pageable) {
Page<LikedPlace> placePage = likedPlaceRepository.findByUserIdAndIsLikedTrue(userId,
pageable);
List<Long> placeIds = placePage.map(likedPlace -> likedPlace.getPlace().getId()).toList();
List<Video> videos = videoRepository.findByPlaceIdIn(placeIds);
Map<Long, String> placeIdToInfluencerName = getMapPlaceIdToInfluencerName(videos);

List<LikedPlaceInfo> likedPlaceInfos = placePage.getContent().stream()
.map(likedPlace -> {
String influencerName = placeIdToInfluencerName.getOrDefault(
likedPlace.getPlace().getId(), null);
return LikedPlaceInfo.of(likedPlace, influencerName);
})
.toList();

return new PageImpl<>(likedPlaceInfos, pageable, placePage.getTotalElements());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package team7.inplace.place.application.dto;


import team7.inplace.likedPlace.domain.LikedPlace;

public record LikedPlaceInfo(
Long placeId,
String placeName,
String imageUrl,
String influencerName,
boolean likes
) {

public static LikedPlaceInfo of(LikedPlace likedPlace, String influencerName) {
return new LikedPlaceInfo(
likedPlace.getPlace().getId(),
likedPlace.getPlace().getName(),
likedPlace.getPlace().getMenuImgUrl(),
influencerName,
likedPlace.isLiked()
);
}
}
19 changes: 12 additions & 7 deletions src/main/java/team7/inplace/review/application/ReviewService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,36 @@
import team7.inplace.global.exception.code.AuthorizationErrorCode;
import team7.inplace.global.exception.code.PlaceErrorCode;
import team7.inplace.global.exception.code.ReviewErrorCode;
import team7.inplace.global.exception.code.UserErrorCode;
import team7.inplace.place.domain.Place;
import team7.inplace.place.persistence.PlaceRepository;
import team7.inplace.review.application.dto.MyReviewInfo;
import team7.inplace.review.application.dto.ReviewCommand;
import team7.inplace.review.application.dto.ReviewInfo;
import team7.inplace.review.domain.Review;
import team7.inplace.review.persistence.ReviewRepository;
import team7.inplace.security.application.CurrentUserProvider;
import team7.inplace.security.util.AuthorizationUtil;
import team7.inplace.user.domain.User;
import team7.inplace.user.persistence.UserRepository;

@RequiredArgsConstructor
@Service
public class ReviewService {

private final ReviewRepository reviewRepository;
private final UserRepository userRepository;
private final PlaceRepository placeRepository;
private final CurrentUserProvider currentUserProvider;

@Transactional
public void createReview(Long placeId, ReviewCommand command) {
if (AuthorizationUtil.isNotLoginUser()) {
throw InplaceException.of(AuthorizationErrorCode.TOKEN_IS_EMPTY);
}

Long userId = AuthorizationUtil.getUserId();
User user = userRepository.findById(userId)
.orElseThrow(() -> InplaceException.of(UserErrorCode.NOT_FOUND));
User user = currentUserProvider.getCurrentUser();
Place place = placeRepository.findById(placeId)
.orElseThrow(() -> InplaceException.of(PlaceErrorCode.NOT_FOUND));

if (reviewRepository.existsByUserIdAndPlaceId(userId, placeId)) {
if (reviewRepository.existsByUserIdAndPlaceId(user.getId(), placeId)) {
throw InplaceException.of(ReviewErrorCode.REVIEW_ALREADY_EXISTS);
}
Review review = ReviewCommand.toEntity(user, place, command);
Expand Down Expand Up @@ -80,4 +78,11 @@ public void deleteReview(Long reviewId) {

reviewRepository.delete(review);
}

@Transactional(readOnly = true)
public Page<MyReviewInfo> getMyReviews(Long userId, Pageable pageable) {
Page<Review> reviewPage = reviewRepository.findByUserId(userId, pageable);

return reviewPage.map(MyReviewInfo::from);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package team7.inplace.review.application.dto;

import java.util.Date;
import team7.inplace.place.application.dto.PlaceInfo.AddressInfo;
import team7.inplace.place.domain.Place;
import team7.inplace.review.domain.Review;


public record MyReviewInfo(
Long reviewId,
boolean likes,
String comment,
Date createdDate,
ReviewPlaceInfo placeInfo
) {

public record ReviewPlaceInfo(
Long placeId,
String imgUrl,
AddressInfo address
) {

public static ReviewPlaceInfo from(Place place) {
return new ReviewPlaceInfo(
place.getId(),
place.getMenuImgUrl(),
AddressInfo.of(place.getAddress())
);
}
}

public static MyReviewInfo from(Review review) {
return new MyReviewInfo(
review.getId(),
review.isLiked(),
review.getComment(),
review.getCreatedDate(),
ReviewPlaceInfo.from(review.getPlace())
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ public interface ReviewRepository extends JpaRepository<Review, Long> {
boolean existsByUserIdAndPlaceId(Long userId, Long placeId);

Page<Review> findByPlaceId(Long placeId, Pageable pageable);

Page<Review> findByUserId(Long userId, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
@RequiredArgsConstructor
@RestController
@RequestMapping("/reviews")
public class ReviewController {
public class ReviewController implements ReviewControllerApiSpec {

private final ReviewService reviewService;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package team7.inplace.review.presentation;

import io.swagger.v3.oas.annotations.Operation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;

public interface ReviewControllerApiSpec {

@Operation(summary = "리뷰 삭제", description = "본인이 작성한 리뷰를 삭제합니다.")
ResponseEntity<Void> deleteReview(@PathVariable Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package team7.inplace.security.application;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import team7.inplace.global.exception.InplaceException;
import team7.inplace.global.exception.code.AuthorizationErrorCode;
import team7.inplace.global.exception.code.UserErrorCode;
import team7.inplace.security.util.AuthorizationUtil;
import team7.inplace.user.domain.User;
import team7.inplace.user.persistence.UserRepository;

@Component
@RequiredArgsConstructor
public class CurrentUserProvider {

private final UserRepository userRepository;

public User getCurrentUser() {
Long userId = AuthorizationUtil.getUserId();
if (userId == null) {
throw InplaceException.of(AuthorizationErrorCode.TOKEN_IS_EMPTY);
}
return userRepository.findById(userId)
.orElseThrow(() -> InplaceException.of(UserErrorCode.NOT_FOUND));
}
}
48 changes: 48 additions & 0 deletions src/main/java/team7/inplace/user/application/UserFacade.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package team7.inplace.user.application;

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import team7.inplace.favoriteInfluencer.application.FavoriteInfluencerService;
import team7.inplace.global.annotation.Facade;
import team7.inplace.global.exception.InplaceException;
import team7.inplace.global.exception.code.AuthorizationErrorCode;
import team7.inplace.influencer.application.dto.InfluencerInfo;
import team7.inplace.place.application.PlaceService;
import team7.inplace.place.application.dto.LikedPlaceInfo;
import team7.inplace.review.application.ReviewService;
import team7.inplace.review.application.dto.MyReviewInfo;
import team7.inplace.security.util.AuthorizationUtil;

@Facade
@RequiredArgsConstructor
public class UserFacade {

private final FavoriteInfluencerService favoriteInfluencerService;
private final PlaceService placeService;
private final ReviewService reviewService;

public Page<InfluencerInfo> getMyFavoriteInfluencers(Pageable pageable) {
if (AuthorizationUtil.isNotLoginUser()) {
throw InplaceException.of(AuthorizationErrorCode.TOKEN_IS_EMPTY);
}
Long userId = AuthorizationUtil.getUserId();
return favoriteInfluencerService.getFavoriteInfluencers(userId, pageable);
}

public Page<LikedPlaceInfo> getMyFavoritePlaces(Pageable pageable) {
if (AuthorizationUtil.isNotLoginUser()) {
throw InplaceException.of(AuthorizationErrorCode.TOKEN_IS_EMPTY);
}
Long userId = AuthorizationUtil.getUserId();
return placeService.getLikedPlaceInfo(userId, pageable);
}

public Page<MyReviewInfo> getMyReviews(Pageable pageable) {
if (AuthorizationUtil.isNotLoginUser()) {
throw InplaceException.of(AuthorizationErrorCode.TOKEN_IS_EMPTY);
}
Long userId = AuthorizationUtil.getUserId();
return reviewService.getMyReviews(userId, pageable);
}
}
Loading

0 comments on commit 8177a8b

Please sign in to comment.