diff --git a/src/main/java/com/gam/api/ApiApplication.java b/src/main/java/com/gam/api/ApiApplication.java index 1394475d..6a03f8e6 100644 --- a/src/main/java/com/gam/api/ApiApplication.java +++ b/src/main/java/com/gam/api/ApiApplication.java @@ -2,7 +2,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @SpringBootApplication public class ApiApplication { diff --git a/src/main/java/com/gam/api/domain/user/controller/UserController.java b/src/main/java/com/gam/api/domain/user/controller/UserController.java index 887f0ce0..e970b96c 100644 --- a/src/main/java/com/gam/api/domain/user/controller/UserController.java +++ b/src/main/java/com/gam/api/domain/user/controller/UserController.java @@ -62,7 +62,7 @@ ResponseEntity getPortfolio( @AuthenticationPrincipal GamUserDetails userDetails, @PathVariable Long userId) { - val response = userService.getPortfolio(userDetails.getId(), userId); + val response = userService.getPortfolio(userDetails.getUser(), userId); return ResponseEntity.ok(ApiResponse.success(ResponseMessage.SUCCESS_GET_PROTFOLIO_LIST.getMessage(), response)); } diff --git a/src/main/java/com/gam/api/domain/user/entity/GamUserDetails.java b/src/main/java/com/gam/api/domain/user/entity/GamUserDetails.java index 28d4f39d..7f4c5a9a 100644 --- a/src/main/java/com/gam/api/domain/user/entity/GamUserDetails.java +++ b/src/main/java/com/gam/api/domain/user/entity/GamUserDetails.java @@ -11,7 +11,9 @@ @Getter public class GamUserDetails implements UserDetails { + // TODO: User 객체 이전 이후 삭제 필요 private final Long id; + private final User user; private final String username; private final String authUserId; private List authorities; @@ -21,6 +23,11 @@ public List getAuthorities() { return authorities; } + public User getUser() { + return user; + } + + // TODO: User 객체 이전 이후 삭제 필요 public Long getId() { return id; } diff --git a/src/main/java/com/gam/api/domain/user/repository/UserRepository.java b/src/main/java/com/gam/api/domain/user/repository/UserRepository.java index 7032368b..eaa362ed 100644 --- a/src/main/java/com/gam/api/domain/user/repository/UserRepository.java +++ b/src/main/java/com/gam/api/domain/user/repository/UserRepository.java @@ -15,6 +15,9 @@ public interface UserRepository extends JpaRepository { Optional getUserById(Long userId); boolean existsByUserName(String userName); + @Query("SELECT u FROM User u JOIN FETCH u.works WHERE u.id = :userId") + Optional getUserByIdWithWorks(@Param("userId") Long userId); + List findByUserStatusAndFirstWorkIdIsNotNullOrderByScrapCountDesc(UserStatus userStatus); @Query(value = "SELECT u FROM User u WHERE LOWER(u.userName) LIKE %:keyword% ORDER BY u.createdAt DESC") diff --git a/src/main/java/com/gam/api/domain/user/repository/UserScrapRepository.java b/src/main/java/com/gam/api/domain/user/repository/UserScrapRepository.java index 6b8877a0..5331c7cd 100644 --- a/src/main/java/com/gam/api/domain/user/repository/UserScrapRepository.java +++ b/src/main/java/com/gam/api/domain/user/repository/UserScrapRepository.java @@ -1,5 +1,6 @@ package com.gam.api.domain.user.repository; +import com.gam.api.domain.user.entity.User; import com.gam.api.domain.user.entity.UserScrap; import com.gam.api.domain.user.dto.query.UserScrapQueryDto; import org.springframework.data.jpa.repository.JpaRepository; @@ -9,8 +10,11 @@ import org.springframework.data.repository.query.Param; public interface UserScrapRepository extends JpaRepository { + List findUserScrapsByUserId(Long userId); UserScrap findByUser_idAndTargetId(Long userId, Long targetId); + UserScrap findByUserAndTargetId(User user, Long targetId); + @Query("SELECT DISTINCT NEW com.gam.api.domain.user.dto.query.UserScrapQueryDto(us.id, us.modifiedAt, us.targetId) "+ "FROM UserScrap us " + "LEFT JOIN FETCH User tu ON us.targetId = tu.id " + diff --git a/src/main/java/com/gam/api/domain/user/service/UserDetailsServiceImpl.java b/src/main/java/com/gam/api/domain/user/service/UserDetailsServiceImpl.java index 4c993b2c..138ca937 100644 --- a/src/main/java/com/gam/api/domain/user/service/UserDetailsServiceImpl.java +++ b/src/main/java/com/gam/api/domain/user/service/UserDetailsServiceImpl.java @@ -11,7 +11,6 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Service; - import javax.persistence.EntityNotFoundException; import java.util.ArrayList; import java.util.List; @@ -41,6 +40,7 @@ public UserDetails loadUserByUsername(String userId) { return GamUserDetails.builder() .id(user.getId()) + .user(user) .authUserId(authUserId) .username(user.getUserName()) .authorities(authorities) diff --git a/src/main/java/com/gam/api/domain/user/service/UserService.java b/src/main/java/com/gam/api/domain/user/service/UserService.java index 1af98f81..25bf7cc5 100644 --- a/src/main/java/com/gam/api/domain/user/service/UserService.java +++ b/src/main/java/com/gam/api/domain/user/service/UserService.java @@ -4,6 +4,7 @@ import com.gam.api.domain.user.dto.response.UserResponseDTO; import com.gam.api.domain.user.dto.response.UserScrapsResponseDTO; import com.gam.api.domain.user.dto.response.SearchUserWorkDTO; +import com.gam.api.domain.user.entity.User; import com.gam.api.domain.work.dto.response.WorkPortfolioGetResponseDTO; import com.gam.api.domain.work.dto.response.WorkPortfolioListResponseDTO; @@ -32,7 +33,7 @@ public interface UserService { List getUserScraps(Long userId); List getPopularDesigners(Long userId); WorkPortfolioListResponseDTO getMyPortfolio(Long userId); - WorkPortfolioGetResponseDTO getPortfolio(Long requestUserId, Long userId); + WorkPortfolioGetResponseDTO getPortfolio(User requestUser, Long userId); List getDiscoveryUsers(Long userId, int[] tags); void updateInstagramLink(Long userId, UserUpdateLinkRequestDTO request); void updateBehanceLink(Long userId, UserUpdateLinkRequestDTO request); diff --git a/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java b/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java index faf3c806..833dab39 100644 --- a/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java +++ b/src/main/java/com/gam/api/domain/user/service/UserServiceImpl.java @@ -264,18 +264,19 @@ public WorkPortfolioListResponseDTO getMyPortfolio(Long userId) { @Transactional @Override - public WorkPortfolioGetResponseDTO getPortfolio(Long requestUserId, Long userId) { - val requestUser = findUser(requestUserId); - val user = findUser(userId); + public WorkPortfolioGetResponseDTO getPortfolio(User requestUser, Long userId) { + val user = findUserWithWorks(userId); user.setViewCount(user.getViewCount() + 1); - val works = getUserPortfolios(userId); - works.forEach(w -> w.viewCountUp()); + val works = refineWorkList(user.getWorks()); + + val workIds = works.stream() + .map(Work::getId) + .toList(); - val scrapList = requestUser.getUserScraps().stream() - .map(UserScrap::getTargetId) - .toList(); + workRepository.updateWorksViewCount(workIds); - val isScraped = scrapList.contains(user.getId()); + val userScrap = userScrapRepository.findByUserAndTargetId(requestUser, user.getId()); + val isScraped = Objects.isNull(userScrap); return WorkPortfolioGetResponseDTO.of(isScraped, user, works); } @@ -365,11 +366,25 @@ private List getUserPortfolios(Long userId) { return works; } + private List refineWorkList(List works) { + return works + .stream() + .filter(Work::isActive) + .sorted(Comparator.comparing(Work::isFirst, Comparator.reverseOrder()) + .thenComparing(Comparator.comparing(Work::getCreatedAt).reversed())) + .collect(Collectors.toList()); + } + private User findUser(Long userId) { return userRepository.findById(userId) .orElseThrow(() -> new EntityNotFoundException(ExceptionMessage.NOT_FOUND_USER.getMessage())); } + private User findUserWithWorks(Long userId) { + return userRepository.getUserByIdWithWorks(userId) + .orElseThrow(() -> new EntityNotFoundException(ExceptionMessage.NOT_FOUND_USER.getMessage())); + } + private void createUserScrap(User user, Long targetId, User targetUser){ userScrapRepository.save(UserScrap.builder() diff --git a/src/main/java/com/gam/api/domain/work/repository/WorkRepository.java b/src/main/java/com/gam/api/domain/work/repository/WorkRepository.java index df74679e..c0ad41fe 100644 --- a/src/main/java/com/gam/api/domain/work/repository/WorkRepository.java +++ b/src/main/java/com/gam/api/domain/work/repository/WorkRepository.java @@ -1,7 +1,9 @@ package com.gam.api.domain.work.repository; import com.gam.api.domain.work.entity.Work; +import io.lettuce.core.dynamic.annotation.Param; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import java.util.List; @@ -18,4 +20,8 @@ public interface WorkRepository extends JpaRepository { @Query(value = "SELECT w FROM Work w WHERE LOWER(w.title) LIKE LOWER(CONCAT('%', :keyword, '%')) ORDER BY w.createdAt DESC") List findByKeyword(String keyword); Optional findFirstByUserIdAndIsActiveOrderByCreatedAtDesc(Long userId, boolean isActive); + + @Modifying + @Query("UPDATE Work w SET w.viewCount = w.viewCount + 1 WHERE w.id IN :ids") + void updateWorksViewCount(@Param("ids") List ids); }