From 461f37bdaa4d1ca17ba6e81520d44f982218b80a Mon Sep 17 00:00:00 2001 From: ohhamma Date: Fri, 6 Sep 2024 17:56:02 +0900 Subject: [PATCH 01/35] KL-166/refactor: use getCurrentUser --- .../domain/comment/service/CommentService.java | 2 +- .../domain/image/service/ImageServiceImpl.java | 4 ++-- .../klkl/domain/like/service/LikeServiceImpl.java | 2 +- .../service/NotificationServiceImpl.java | 2 +- .../domain/product/service/ProductServiceImpl.java | 2 +- .../klkl/domain/user/service/UserServiceImpl.java | 4 ++-- src/main/java/taco/klkl/global/util/UserUtil.java | 14 +++++++------- .../domain/comment/service/CommentServiceTest.java | 2 +- .../domain/like/service/LikeServiceImplTest.java | 12 ++++++------ .../service/NotificationServiceTest.java | 6 +++--- .../product/service/ProductServiceImplTest.java | 2 +- .../domain/user/service/UserServiceImplTest.java | 2 +- 12 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/main/java/taco/klkl/domain/comment/service/CommentService.java b/src/main/java/taco/klkl/domain/comment/service/CommentService.java index 96401e16..ddf70315 100644 --- a/src/main/java/taco/klkl/domain/comment/service/CommentService.java +++ b/src/main/java/taco/klkl/domain/comment/service/CommentService.java @@ -81,7 +81,7 @@ private Comment createCommentEntity( final CommentCreateUpdateRequest commentCreateUpdateRequest ) { //TODO: getCurrentUser() 함수로 교채 - final User user = userUtil.findTestUser(); + final User user = userUtil.getCurrentUser(); final Product product = productUtil.findProductEntityById(productId); return Comment.of( product, diff --git a/src/main/java/taco/klkl/domain/image/service/ImageServiceImpl.java b/src/main/java/taco/klkl/domain/image/service/ImageServiceImpl.java index b7903499..ed319743 100644 --- a/src/main/java/taco/klkl/domain/image/service/ImageServiceImpl.java +++ b/src/main/java/taco/klkl/domain/image/service/ImageServiceImpl.java @@ -58,7 +58,7 @@ public class ImageServiceImpl implements ImageService { @Override @Transactional public PresignedUrlResponse createUserImageUploadUrl(final SingleImageUploadRequest uploadRequest) { - final User currentUser = userUtil.findCurrentUser(); + final User currentUser = userUtil.getCurrentUser(); final FileExtension fileExtension = FileExtension.from(uploadRequest.fileExtension()); return createImageUploadUrl(ImageType.USER_IMAGE, currentUser.getId(), fileExtension); } @@ -80,7 +80,7 @@ public List createProductImageUploadUrls( public SingleUploadCompleteResponse uploadCompleteUserImage( final SingleImageUpdateRequest updateRequest ) { - final User currentUser = userUtil.findCurrentUser(); + final User currentUser = userUtil.getCurrentUser(); expireOldImages(ImageType.USER_IMAGE, currentUser.getId()); Image updatedImage = imageUtil.findImageEntityByImageTypeAndId(ImageType.USER_IMAGE, updateRequest.imageId()); diff --git a/src/main/java/taco/klkl/domain/like/service/LikeServiceImpl.java b/src/main/java/taco/klkl/domain/like/service/LikeServiceImpl.java index 447a66ef..02801eeb 100644 --- a/src/main/java/taco/klkl/domain/like/service/LikeServiceImpl.java +++ b/src/main/java/taco/klkl/domain/like/service/LikeServiceImpl.java @@ -60,7 +60,7 @@ private Product findProductById(final Long productId) { } private User findCurrentUser() { - return userUtil.findCurrentUser(); + return userUtil.getCurrentUser(); } @Override diff --git a/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java b/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java index 536070a9..9b6af69d 100644 --- a/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java +++ b/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java @@ -92,6 +92,6 @@ public void createNotificationByComment(final Comment comment) { // TODO: 토큰으로 유저 가져오는 방식으로 수정하기 private User findReceiver() { - return userUtil.findTestUser(); + return userUtil.getCurrentUser(); } } diff --git a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java index 44636873..f7db448e 100644 --- a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java +++ b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java @@ -248,7 +248,7 @@ private Set createTagsByTagIds(final Set filterIds) { private Product createProductEntity(final ProductCreateUpdateRequest createRequest) { final Rating rating = Rating.from(createRequest.rating()); - final User user = userUtil.findTestUser(); + final User user = userUtil.getCurrentUser(); final City city = findCityById(createRequest.cityId()); final Subcategory subcategory = findSubcategoryById(createRequest.subcategoryId()); final Currency currency = findCurrencyById(createRequest.currencyId()); diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index 537732fb..991c1794 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -31,7 +31,7 @@ public class UserServiceImpl implements UserService { */ @Override public UserDetailResponse getCurrentUser() { - final User currentUser = userUtil.findCurrentUser(); + final User currentUser = userUtil.getCurrentUser(); return UserDetailResponse.from(currentUser); } @@ -45,7 +45,7 @@ public User createUser(final UserCreateRequest createRequest) { @Override @Transactional public UserDetailResponse updateUser(final UserUpdateRequest updateRequest) { - User user = userUtil.findCurrentUser(); + User user = userUtil.getCurrentUser(); updateUserEntity(user, updateRequest); return UserDetailResponse.from(user); } diff --git a/src/main/java/taco/klkl/global/util/UserUtil.java b/src/main/java/taco/klkl/global/util/UserUtil.java index b0120c6d..5f36cae3 100644 --- a/src/main/java/taco/klkl/global/util/UserUtil.java +++ b/src/main/java/taco/klkl/global/util/UserUtil.java @@ -21,18 +21,13 @@ public class UserUtil { private final UserRepository userRepository; - public User findTestUser() { - return userRepository.findById(1L) - .orElseThrow(UserNotFoundException::new); - } - /** * TODO: 인증정보를 확인해 유저 엔티티를 리턴한다. * 현재 유저 조회 * @return */ - public User findCurrentUser() { - return findTestUser(); + public User getCurrentUser() { + return getTestUser(); } public String createUsername(final String name, final Long oauthMemberId) { @@ -52,6 +47,11 @@ public static String generateProfileUrlByUser(final User user) { .orElse(null); } + private User getTestUser() { + return userRepository.findById(1L) + .orElseThrow(UserNotFoundException::new); + } + private String generateUsername(final String name, final Long oauthMemberId) { final Long currentTimeMillis = Instant.now().toEpochMilli(); diff --git a/src/test/java/taco/klkl/domain/comment/service/CommentServiceTest.java b/src/test/java/taco/klkl/domain/comment/service/CommentServiceTest.java index 19d63559..39388f9d 100644 --- a/src/test/java/taco/klkl/domain/comment/service/CommentServiceTest.java +++ b/src/test/java/taco/klkl/domain/comment/service/CommentServiceTest.java @@ -105,7 +105,7 @@ public void testCreateComment() { final Long productId = 1L; final Comment comment = Comment.of(product, user, "이거 진짜에요?"); - when(userUtil.findTestUser()).thenReturn(user); + when(userUtil.getCurrentUser()).thenReturn(user); when(commentRepository.save(any(Comment.class))).thenReturn(comment); //when diff --git a/src/test/java/taco/klkl/domain/like/service/LikeServiceImplTest.java b/src/test/java/taco/klkl/domain/like/service/LikeServiceImplTest.java index 9f836954..58367646 100644 --- a/src/test/java/taco/klkl/domain/like/service/LikeServiceImplTest.java +++ b/src/test/java/taco/klkl/domain/like/service/LikeServiceImplTest.java @@ -57,7 +57,7 @@ void testCreateLike() { Long productId = 1L; when(productUtil.findProductEntityById(productId)).thenReturn(product); - when(userUtil.findCurrentUser()).thenReturn(user); + when(userUtil.getCurrentUser()).thenReturn(user); when(likeRepository.existsByProductAndUser(product, user)).thenReturn(false); when(productService.increaseLikeCount(product)).thenReturn(1); LikeResponse likeResponse = LikeResponse.of(true, 1); @@ -79,7 +79,7 @@ void testCreateWhenAlreadyExists() { Long productId = 1L; when(productUtil.findProductEntityById(productId)).thenReturn(product); - when(userUtil.findCurrentUser()).thenReturn(user); + when(userUtil.getCurrentUser()).thenReturn(user); when(likeRepository.existsByProductAndUser(product, user)).thenReturn(true); when(product.getLikeCount()).thenReturn(1); LikeResponse likeResponse = LikeResponse.of(true, product.getLikeCount()); @@ -104,7 +104,7 @@ void testDeleteLike() { Long productId = 1L; when(productUtil.findProductEntityById(productId)).thenReturn(product); - when(userUtil.findCurrentUser()).thenReturn(user); + when(userUtil.getCurrentUser()).thenReturn(user); when(likeRepository.existsByProductAndUser(product, user)).thenReturn(true); when(productService.decreaseLikeCount(product)).thenReturn(0); when(product.getLikeCount()).thenReturn(0); @@ -126,7 +126,7 @@ void testDeleteLikeWhenNotExists() { Long productId = 1L; when(productUtil.findProductEntityById(productId)).thenReturn(product); - when(userUtil.findCurrentUser()).thenReturn(user); + when(userUtil.getCurrentUser()).thenReturn(user); when(likeRepository.existsByProductAndUser(product, user)).thenReturn(false); when(product.getLikeCount()).thenReturn(1); LikeResponse likeResponse = LikeResponse.of(false, product.getLikeCount()); @@ -151,7 +151,7 @@ void testCreateLikeMaximumError() { Long productId = 1L; when(productUtil.findProductEntityById(productId)).thenReturn(product); - when(userUtil.findCurrentUser()).thenReturn(user); + when(userUtil.getCurrentUser()).thenReturn(user); when(likeRepository.existsByProductAndUser(product, user)).thenReturn(false); when(productService.increaseLikeCount(product)).thenThrow(LikeCountOverMaximumException.class); doThrow(LikeCountOverMaximumException.class).when(product).increaseLikeCount(); @@ -169,7 +169,7 @@ void testCreateLikeMinimumError() { Long productId = 1L; when(productUtil.findProductEntityById(productId)).thenReturn(product); - when(userUtil.findCurrentUser()).thenReturn(user); + when(userUtil.getCurrentUser()).thenReturn(user); when(likeRepository.existsByProductAndUser(product, user)).thenReturn(true); when(productService.decreaseLikeCount(product)).thenThrow(LikeCountBelowMinimumException.class); doThrow(LikeCountBelowMinimumException.class).when(product).decreaseLikeCount(); diff --git a/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java b/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java index 09ea8b7c..9750dae3 100644 --- a/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java +++ b/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java @@ -127,7 +127,7 @@ public void testFindAllNotifications() { QNotification notification = QNotification.notification; QUser user = QUser.user; - when(userUtil.findTestUser()).thenReturn(mockUser); + when(userUtil.getCurrentUser()).thenReturn(mockUser); when(mockNotification.getId()).thenReturn(1L); when(mockNotification.getIsRead()).thenReturn(false); when(mockNotification.getCreatedAt()).thenReturn(LocalDateTime.now()); @@ -157,7 +157,7 @@ public void testGetBlankNotifications() { QNotification notification = QNotification.notification; QUser user = QUser.user; - when(userUtil.findTestUser()).thenReturn(mockUser); + when(userUtil.getCurrentUser()).thenReturn(mockUser); when(queryFactory.selectFrom(any(QNotification.class))).thenReturn(mockQuery); when(mockQuery.join(notification.comment.product.user, user)).thenReturn(mockQuery); @@ -181,7 +181,7 @@ public void testReadAllNotifications() { List notificationList = List.of(notification1, notification2); - when(userUtil.findTestUser()).thenReturn(mockUser); + when(userUtil.getCurrentUser()).thenReturn(mockUser); when(notificationRepository.findAllByComment_Product_User(mockUser)).thenReturn(notificationList); when(notificationRepository.count()).thenReturn(2L); diff --git a/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java b/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java index 2b9e9227..d3076630 100644 --- a/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java +++ b/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java @@ -376,7 +376,7 @@ void testFindProductById_NotFound() { @DisplayName("상품 생성 - 성공") void testCreateProduct() { // Given - when(userUtil.findTestUser()).thenReturn(user); + when(userUtil.getCurrentUser()).thenReturn(user); when(cityUtil.findCityEntityById(1L)).thenReturn(city); when(subcategoryUtil.findSubcategoryEntityById(1L)).thenReturn(subcategory); when(currencyUtil.findCurrencyEntityById(1L)).thenReturn(currency); diff --git a/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java b/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java index 5bc3084d..cb33114d 100644 --- a/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java +++ b/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java @@ -39,7 +39,7 @@ public void testGetCurrentUser() { // given User user = mock(User.class); - when(userUtil.findCurrentUser()).thenReturn(user); + when(userUtil.getCurrentUser()).thenReturn(user); when(user.getId()).thenReturn(1L); when(user.getName()).thenReturn("testUser"); when(user.getDescription()).thenReturn("테스트입니다."); From 15f7ebbfef933808859fd9c158e426fbc8c93636 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Fri, 6 Sep 2024 18:20:34 +0900 Subject: [PATCH 02/35] KL-166/refactor: add private constructor --- .../global/common/constants/CommentValidationMessages.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/taco/klkl/global/common/constants/CommentValidationMessages.java b/src/main/java/taco/klkl/global/common/constants/CommentValidationMessages.java index 8547ae81..1e9c2655 100644 --- a/src/main/java/taco/klkl/global/common/constants/CommentValidationMessages.java +++ b/src/main/java/taco/klkl/global/common/constants/CommentValidationMessages.java @@ -5,4 +5,7 @@ public final class CommentValidationMessages { public static final String CONTENT_NOT_NULL = "댓글 내용은 필수 항목입니다."; public static final String CONTENT_NOT_BLANK = "댓글 내용은 비어있을 수 없습니다."; public static final String CONTENT_SIZE = "댓글 내용은 400자 이하여야 합니다."; + + private CommentValidationMessages() { + } } From ede533f2478377bdfd07af94312793a8d65ab68d Mon Sep 17 00:00:00 2001 From: ohhamma Date: Fri, 6 Sep 2024 18:20:48 +0900 Subject: [PATCH 03/35] KL-166/chore: remove unused import --- .../taco/klkl/global/common/constants/ProductConstants.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/taco/klkl/global/common/constants/ProductConstants.java b/src/main/java/taco/klkl/global/common/constants/ProductConstants.java index 4e07fe80..c5211698 100644 --- a/src/main/java/taco/klkl/global/common/constants/ProductConstants.java +++ b/src/main/java/taco/klkl/global/common/constants/ProductConstants.java @@ -1,7 +1,5 @@ package taco.klkl.global.common.constants; -import java.util.Set; - public final class ProductConstants { public static final int DEFAULT_PAGE_SIZE = 9; From 5a15bf7a70ed839f9886bb581fec3bf37463b386 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Fri, 6 Sep 2024 18:22:00 +0900 Subject: [PATCH 04/35] KL-166/refactor: add user validation messages --- .../user/dto/request/UserUpdateRequest.java | 15 +++++++++++---- .../common/constants/UserValidationMessages.java | 11 +++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java diff --git a/src/main/java/taco/klkl/domain/user/dto/request/UserUpdateRequest.java b/src/main/java/taco/klkl/domain/user/dto/request/UserUpdateRequest.java index 42bede10..99475873 100644 --- a/src/main/java/taco/klkl/domain/user/dto/request/UserUpdateRequest.java +++ b/src/main/java/taco/klkl/domain/user/dto/request/UserUpdateRequest.java @@ -1,12 +1,19 @@ package taco.klkl.domain.user.dto.request; -import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.PositiveOrZero; +import taco.klkl.global.common.constants.UserValidationMessages; public record UserUpdateRequest( - @NotNull(message = "이름은 필수 항목입니다.") String name, - @NotNull(message = "성별은 필수 항목입니다.") String gender, - @PositiveOrZero(message = "나이는 0 이상이어야 합니다.") Integer age, + @NotBlank(message = UserValidationMessages.NAME_NOT_BLANK) + String name, + + @NotBlank(message = UserValidationMessages.GENDER_NOT_BLANK) + String gender, + + @PositiveOrZero(message = UserValidationMessages.AGE_POSITIVE_OR_ZERO) + Integer age, + String description ) { } diff --git a/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java b/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java new file mode 100644 index 00000000..d7f85c25 --- /dev/null +++ b/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java @@ -0,0 +1,11 @@ +package taco.klkl.global.common.constants; + +public final class UserValidationMessages { + + public static final String NAME_NOT_BLANK = "이름은 비워둘 수 없습니다."; + public static final String GENDER_NOT_BLANK = "성별은 비워둘 수 없습니다."; + public static final String AGE_POSITIVE_OR_ZERO = "나이는 0 이상이어야 합니다."; + + private UserValidationMessages() { + } +} From 21562be534597e9093fbcc94718b6944e70285e7 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Fri, 6 Sep 2024 18:22:47 +0900 Subject: [PATCH 05/35] KL-166/chore: change service method sequence --- .../taco/klkl/domain/user/service/UserService.java | 4 +++- .../klkl/domain/user/service/UserServiceImpl.java | 14 +++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/taco/klkl/domain/user/service/UserService.java b/src/main/java/taco/klkl/domain/user/service/UserService.java index 25017e81..5da364a0 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserService.java +++ b/src/main/java/taco/klkl/domain/user/service/UserService.java @@ -9,9 +9,11 @@ @Service public interface UserService { + UserDetailResponse getCurrentUser(); + UserDetailResponse updateUser(final UserUpdateRequest updateRequest); + User createUser(final UserCreateRequest createRequest); - UserDetailResponse updateUser(final UserUpdateRequest updateRequest); } diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index 991c1794..4f03cb35 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -35,13 +35,6 @@ public UserDetailResponse getCurrentUser() { return UserDetailResponse.from(currentUser); } - @Override - @Transactional - public User createUser(final UserCreateRequest createRequest) { - final User user = createUserEntity(createRequest); - return userRepository.save(user); - } - @Override @Transactional public UserDetailResponse updateUser(final UserUpdateRequest updateRequest) { @@ -50,6 +43,13 @@ public UserDetailResponse updateUser(final UserUpdateRequest updateRequest) { return UserDetailResponse.from(user); } + @Override + @Transactional + public User createUser(final UserCreateRequest createRequest) { + final User user = createUserEntity(createRequest); + return userRepository.save(user); + } + private User createUserEntity(final UserCreateRequest createRequest) { final String name = createRequest.name(); final Gender gender = Gender.from(createRequest.gender()); From 3f1e88a1fbc76b422328ebb39d61f125c5b602bc Mon Sep 17 00:00:00 2001 From: ohhamma Date: Fri, 6 Sep 2024 18:40:36 +0900 Subject: [PATCH 06/35] KL-166/refactor: remove gender and age --- .../service/OauthKakaoLoginServiceImpl.java | 3 --- .../taco/klkl/domain/user/domain/User.java | 25 +------------------ .../user/dto/request/UserCreateRequest.java | 14 +++++------ .../user/dto/request/UserUpdateRequest.java | 7 ------ .../domain/user/service/UserServiceImpl.java | 9 ------- .../common/constants/UserConstants.java | 11 -------- .../constants/UserValidationMessages.java | 2 -- src/main/resources/database/data.sql | 4 +-- .../controller/CommentControllerTest.java | 5 ---- .../comment/service/CommentServiceTest.java | 5 ---- .../NotificationControllerTest.java | 3 +-- .../service/NotificationServiceTest.java | 3 --- .../service/ProductServiceImplTest.java | 3 +-- .../user/controller/UserControllerTest.java | 3 +-- .../user/dto/request/UserRequestDtoTest.java | 17 ++----------- .../dto/response/UserDetailResponseTest.java | 5 +--- .../dto/response/UserSimpleResponseTest.java | 5 +--- .../user/service/UserServiceImplTest.java | 5 ---- 18 files changed, 16 insertions(+), 113 deletions(-) diff --git a/src/main/java/taco/klkl/domain/oauth/service/OauthKakaoLoginServiceImpl.java b/src/main/java/taco/klkl/domain/oauth/service/OauthKakaoLoginServiceImpl.java index a46bf50a..a15c77d4 100644 --- a/src/main/java/taco/klkl/domain/oauth/service/OauthKakaoLoginServiceImpl.java +++ b/src/main/java/taco/klkl/domain/oauth/service/OauthKakaoLoginServiceImpl.java @@ -9,7 +9,6 @@ import taco.klkl.domain.oauth.dao.OauthRepository; import taco.klkl.domain.oauth.domain.Oauth; import taco.klkl.domain.oauth.dto.request.KakaoUserInfoRequest; -import taco.klkl.domain.user.domain.Gender; import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserCreateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; @@ -58,8 +57,6 @@ private User registerUser(final KakaoUserInfoRequest userInfoRequest) { // TODO: 성별, 나이는 기본값으로 넣고 있습니다. final UserCreateRequest userCreateRequest = UserCreateRequest.of( name, - Gender.MALE.getValue(), - 0, "" ); diff --git a/src/main/java/taco/klkl/domain/user/domain/User.java b/src/main/java/taco/klkl/domain/user/domain/User.java index 46b54abf..65fbfd17 100644 --- a/src/main/java/taco/klkl/domain/user/domain/User.java +++ b/src/main/java/taco/klkl/domain/user/domain/User.java @@ -35,19 +35,6 @@ public class User { ) private String name; - @Column( - name = "gender", - length = 1, - nullable = false - ) - private Gender gender; - - @Column( - name = "age", - nullable = false - ) - private Integer age; - @Column( name = "description", length = 100 @@ -63,35 +50,25 @@ public class User { private User( final String name, - final Gender gender, - final Integer age, final String description ) { this.name = name; - this.gender = gender; - this.age = age; this.description = description; this.createdAt = LocalDateTime.now(); } public static User of( final String name, - final Gender gender, - final Integer age, final String description ) { - return new User(name, gender, age, description); + return new User(name, description); } public void update( final String name, - final Gender gender, - final Integer age, final String description ) { this.name = name; - this.gender = gender; - this.age = age; this.description = description; } diff --git a/src/main/java/taco/klkl/domain/user/dto/request/UserCreateRequest.java b/src/main/java/taco/klkl/domain/user/dto/request/UserCreateRequest.java index 072467a8..359e5253 100644 --- a/src/main/java/taco/klkl/domain/user/dto/request/UserCreateRequest.java +++ b/src/main/java/taco/klkl/domain/user/dto/request/UserCreateRequest.java @@ -1,20 +1,18 @@ package taco.klkl.domain.user.dto.request; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.PositiveOrZero; +import jakarta.validation.constraints.NotBlank; +import taco.klkl.global.common.constants.UserValidationMessages; public record UserCreateRequest( - @NotNull(message = "이름은 필수 항목입니다.") String name, - @NotNull(message = "성별은 필수 항목입니다.") String gender, - @PositiveOrZero(message = "나이는 0 이상이어야 합니다.") Integer age, + @NotBlank(message = UserValidationMessages.NAME_NOT_BLANK) + String name, + String description ) { public static UserCreateRequest of( final String name, - final String gender, - final Integer age, final String description ) { - return new UserCreateRequest(name, gender, age, description); + return new UserCreateRequest(name, description); } } diff --git a/src/main/java/taco/klkl/domain/user/dto/request/UserUpdateRequest.java b/src/main/java/taco/klkl/domain/user/dto/request/UserUpdateRequest.java index 99475873..4e7a0dcd 100644 --- a/src/main/java/taco/klkl/domain/user/dto/request/UserUpdateRequest.java +++ b/src/main/java/taco/klkl/domain/user/dto/request/UserUpdateRequest.java @@ -1,19 +1,12 @@ package taco.klkl.domain.user.dto.request; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.PositiveOrZero; import taco.klkl.global.common.constants.UserValidationMessages; public record UserUpdateRequest( @NotBlank(message = UserValidationMessages.NAME_NOT_BLANK) String name, - @NotBlank(message = UserValidationMessages.GENDER_NOT_BLANK) - String gender, - - @PositiveOrZero(message = UserValidationMessages.AGE_POSITIVE_OR_ZERO) - Integer age, - String description ) { } diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index 4f03cb35..ee143aa0 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -7,7 +7,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import taco.klkl.domain.user.dao.UserRepository; -import taco.klkl.domain.user.domain.Gender; import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserCreateRequest; import taco.klkl.domain.user.dto.request.UserUpdateRequest; @@ -52,28 +51,20 @@ public User createUser(final UserCreateRequest createRequest) { private User createUserEntity(final UserCreateRequest createRequest) { final String name = createRequest.name(); - final Gender gender = Gender.from(createRequest.gender()); - final Integer age = createRequest.age(); final String description = createRequest.description(); return User.of( name, - gender, - age, description ); } private void updateUserEntity(final User user, final UserUpdateRequest updateRequest) { final String name = updateRequest.name(); - final Gender gender = Gender.from(updateRequest.gender()); - final Integer age = updateRequest.age(); final String description = updateRequest.description(); user.update( name, - gender, - age, description ); } diff --git a/src/main/java/taco/klkl/global/common/constants/UserConstants.java b/src/main/java/taco/klkl/global/common/constants/UserConstants.java index 85527612..70e768a0 100644 --- a/src/main/java/taco/klkl/global/common/constants/UserConstants.java +++ b/src/main/java/taco/klkl/global/common/constants/UserConstants.java @@ -1,18 +1,7 @@ package taco.klkl.global.common.constants; -import taco.klkl.domain.user.domain.Gender; -import taco.klkl.domain.user.domain.User; - public final class UserConstants { - public static final String TEST_USER_NAME = "testUser"; - public static final User TEST_USER = User.of( - TEST_USER_NAME, - Gender.MALE, - 20, - "테스트입니다." - ); - public static final int DEFAULT_TOTAL_LIKE_COUNT = 0; public static final int USERNAME_SUFFIX_MOD = 9973; diff --git a/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java b/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java index d7f85c25..0991ad97 100644 --- a/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java +++ b/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java @@ -3,8 +3,6 @@ public final class UserValidationMessages { public static final String NAME_NOT_BLANK = "이름은 비워둘 수 없습니다."; - public static final String GENDER_NOT_BLANK = "성별은 비워둘 수 없습니다."; - public static final String AGE_POSITIVE_OR_ZERO = "나이는 0 이상이어야 합니다."; private UserValidationMessages() { } diff --git a/src/main/resources/database/data.sql b/src/main/resources/database/data.sql index 93b01920..0af3fd6d 100644 --- a/src/main/resources/database/data.sql +++ b/src/main/resources/database/data.sql @@ -1,6 +1,6 @@ /* User */ -INSERT INTO klkl_user(user_id, name, gender, age, description, created_at) -VALUES (1, 'testUser', '남', 20, '테스트입니다.', now()); +INSERT INTO klkl_user(user_id, name, description, created_at) +VALUES (1, 'testUser', '테스트입니다.', now()); /* Like */ diff --git a/src/test/java/taco/klkl/domain/comment/controller/CommentControllerTest.java b/src/test/java/taco/klkl/domain/comment/controller/CommentControllerTest.java index b6321890..484e8071 100644 --- a/src/test/java/taco/klkl/domain/comment/controller/CommentControllerTest.java +++ b/src/test/java/taco/klkl/domain/comment/controller/CommentControllerTest.java @@ -41,7 +41,6 @@ import taco.klkl.domain.region.domain.currency.CurrencyType; import taco.klkl.domain.region.domain.region.Region; import taco.klkl.domain.region.domain.region.RegionType; -import taco.klkl.domain.user.domain.Gender; import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserCreateRequest; import taco.klkl.global.error.exception.ErrorCode; @@ -66,14 +65,10 @@ public class CommentControllerTest { private final UserCreateRequest requestDto = new UserCreateRequest( "이상화", - "남", - 19, "저는 이상화입니다." ); private final User user = User.of( requestDto.name(), - Gender.from(requestDto.gender()), - requestDto.age(), requestDto.description() ); diff --git a/src/test/java/taco/klkl/domain/comment/service/CommentServiceTest.java b/src/test/java/taco/klkl/domain/comment/service/CommentServiceTest.java index 39388f9d..61ae240b 100644 --- a/src/test/java/taco/klkl/domain/comment/service/CommentServiceTest.java +++ b/src/test/java/taco/klkl/domain/comment/service/CommentServiceTest.java @@ -24,7 +24,6 @@ import taco.klkl.domain.notification.service.NotificationService; import taco.klkl.domain.product.domain.Product; import taco.klkl.domain.product.exception.ProductNotFoundException; -import taco.klkl.domain.user.domain.Gender; import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserCreateRequest; import taco.klkl.global.util.ProductUtil; @@ -50,15 +49,11 @@ public class CommentServiceTest { private final UserCreateRequest userRequestDto = new UserCreateRequest( "이상화", - "남", - 19, "저는 이상화입니다." ); private final User user = User.of( userRequestDto.name(), - Gender.from(userRequestDto.gender()), - userRequestDto.age(), userRequestDto.description() ); diff --git a/src/test/java/taco/klkl/domain/notification/controller/NotificationControllerTest.java b/src/test/java/taco/klkl/domain/notification/controller/NotificationControllerTest.java index 1c7650b5..7f2006ab 100644 --- a/src/test/java/taco/klkl/domain/notification/controller/NotificationControllerTest.java +++ b/src/test/java/taco/klkl/domain/notification/controller/NotificationControllerTest.java @@ -35,7 +35,6 @@ import taco.klkl.domain.region.domain.currency.Currency; import taco.klkl.domain.region.domain.region.Region; import taco.klkl.domain.user.domain.User; -import taco.klkl.global.common.constants.UserConstants; @WebMvcTest(NotificationController.class) class NotificationControllerTest { @@ -55,7 +54,7 @@ class NotificationControllerTest { @MockBean NotificationService notificationService; - private final User user = UserConstants.TEST_USER; + private final User user = User.of("testUser", "테스트입니다."); private final Country country = Country.of(CountryType.MALAYSIA, region, "photo", currency); private final City city = City.of(CityType.BORACAY, country); private final Category category = Category.of(CategoryType.CLOTHES); diff --git a/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java b/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java index 9750dae3..f6e5dd9e 100644 --- a/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java +++ b/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java @@ -44,7 +44,6 @@ import taco.klkl.domain.region.domain.currency.CurrencyType; import taco.klkl.domain.region.domain.region.Region; import taco.klkl.domain.region.domain.region.RegionType; -import taco.klkl.domain.user.domain.Gender; import taco.klkl.domain.user.domain.QUser; import taco.klkl.domain.user.domain.User; import taco.klkl.global.util.UserUtil; @@ -79,8 +78,6 @@ public class NotificationServiceTest { public void setUp() { commentUser = User.of( "윤상정", - Gender.FEMALE, - 26, "나는 해적왕이 될 사나이다."); Region region = Region.from(RegionType.SOUTHEAST_ASIA); diff --git a/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java b/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java index d3076630..2e47dc57 100644 --- a/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java +++ b/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java @@ -62,7 +62,6 @@ import taco.klkl.domain.region.domain.region.Region; import taco.klkl.domain.region.domain.region.RegionType; import taco.klkl.domain.user.domain.User; -import taco.klkl.global.common.constants.UserConstants; import taco.klkl.global.common.response.PagedResponseDto; import taco.klkl.global.util.CityUtil; import taco.klkl.global.util.CurrencyUtil; @@ -109,7 +108,7 @@ class ProductServiceImplTest { void setUp() { MockitoAnnotations.openMocks(this); - user = UserConstants.TEST_USER; + user = User.of("testUser", "테스트입니다."); Region region = Region.from(RegionType.SOUTHEAST_ASIA); currency = Currency.of( diff --git a/src/test/java/taco/klkl/domain/user/controller/UserControllerTest.java b/src/test/java/taco/klkl/domain/user/controller/UserControllerTest.java index 7a0c16bf..12f9fa52 100644 --- a/src/test/java/taco/klkl/domain/user/controller/UserControllerTest.java +++ b/src/test/java/taco/klkl/domain/user/controller/UserControllerTest.java @@ -14,7 +14,6 @@ import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; -import taco.klkl.domain.user.domain.Gender; import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.response.UserDetailResponse; import taco.klkl.domain.user.service.UserService; @@ -33,7 +32,7 @@ class UserControllerTest { @BeforeEach public void setUp() { - final User user = User.of("name", Gender.MALE, 20, "description"); + final User user = User.of("name", "description"); userDetailResponse = UserDetailResponse.from(user); } diff --git a/src/test/java/taco/klkl/domain/user/dto/request/UserRequestDtoTest.java b/src/test/java/taco/klkl/domain/user/dto/request/UserRequestDtoTest.java index 599db180..d4aa28e4 100644 --- a/src/test/java/taco/klkl/domain/user/dto/request/UserRequestDtoTest.java +++ b/src/test/java/taco/klkl/domain/user/dto/request/UserRequestDtoTest.java @@ -24,7 +24,7 @@ public UserRequestDtoTest() { @DisplayName("유효한 UserCreateRequestDto에 대한 유효성 검사") public void testValidUserCreateRequestDto() { // given - UserCreateRequest requestDto = new UserCreateRequest("이름", "남", 20, "자기소개"); + UserCreateRequest requestDto = new UserCreateRequest("이름", "자기소개"); // when Set> violations = validator.validate(requestDto); @@ -37,20 +37,7 @@ public void testValidUserCreateRequestDto() { @DisplayName("이름이 null인 UserCreateRequest 유효성 검사") public void testInvalidUserCreateRequestDto_NameRequired() { // given - UserCreateRequest requestDto = new UserCreateRequest(null, "남", 20, "자기소개"); - - // when - Set> violations = validator.validate(requestDto); - - // then - assertThat(violations).isNotEmpty(); - } - - @Test - @DisplayName("나이가 음수인 UserCreateRequest 유효성 검사") - public void testInvalidUserCreateRequestDto_AgeNegative() { - // given - UserCreateRequest requestDto = new UserCreateRequest("이름", "남", -1, "자기소개"); + UserCreateRequest requestDto = new UserCreateRequest(null, "자기소개"); // when Set> violations = validator.validate(requestDto); diff --git a/src/test/java/taco/klkl/domain/user/dto/response/UserDetailResponseTest.java b/src/test/java/taco/klkl/domain/user/dto/response/UserDetailResponseTest.java index d8bcfa72..49d3b906 100644 --- a/src/test/java/taco/klkl/domain/user/dto/response/UserDetailResponseTest.java +++ b/src/test/java/taco/klkl/domain/user/dto/response/UserDetailResponseTest.java @@ -5,7 +5,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import taco.klkl.domain.user.domain.Gender; import taco.klkl.domain.user.domain.User; import taco.klkl.global.common.constants.UserConstants; @@ -36,12 +35,10 @@ public void testUserDetailResponseDto() { public void testFrom() { // given String name = "이름"; - Gender gender = Gender.MALE; - int age = 20; String description = "자기소개"; // when - User user = User.of(name, gender, age, description); + User user = User.of(name, description); UserDetailResponse userDetail = UserDetailResponse.from(user); // then diff --git a/src/test/java/taco/klkl/domain/user/dto/response/UserSimpleResponseTest.java b/src/test/java/taco/klkl/domain/user/dto/response/UserSimpleResponseTest.java index 64e93c5a..a1e4243d 100644 --- a/src/test/java/taco/klkl/domain/user/dto/response/UserSimpleResponseTest.java +++ b/src/test/java/taco/klkl/domain/user/dto/response/UserSimpleResponseTest.java @@ -5,7 +5,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import taco.klkl.domain.user.domain.Gender; import taco.klkl.domain.user.domain.User; class UserSimpleResponseTest { @@ -31,12 +30,10 @@ public void testUserSimpleResponseDto() { public void testFrom() { // given String name = "이름"; - Gender gender = Gender.MALE; - int age = 20; String description = "자기소개"; // when - User user = User.of(name, gender, age, description); + User user = User.of(name, description); UserSimpleResponse userSimple = UserSimpleResponse.from(user); // then diff --git a/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java b/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java index cb33114d..3d05c80b 100644 --- a/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java +++ b/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java @@ -13,7 +13,6 @@ import org.slf4j.LoggerFactory; import taco.klkl.domain.user.dao.UserRepository; -import taco.klkl.domain.user.domain.Gender; import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserCreateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; @@ -60,14 +59,10 @@ public void testCreateUser() { // given UserCreateRequest requestDto = new UserCreateRequest( "이상화", - "남", - 19, "저는 이상화입니다." ); User user = User.of( requestDto.name(), - Gender.from(requestDto.gender()), - requestDto.age(), requestDto.description() ); when(userRepository.save(any(User.class))).thenReturn(user); From 09c510f943d3336b771bd5816d78f6e89850d4ec Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 14:28:39 +0900 Subject: [PATCH 07/35] KL-166/feat: get my products --- .../domain/product/dao/ProductRepository.java | 3 +++ .../user/controller/UserController.java | 16 +++++++++++++- .../klkl/domain/user/service/UserService.java | 7 +++++- .../domain/user/service/UserServiceImpl.java | 22 ++++++++++++++++--- .../taco/klkl/global/util/ProductUtil.java | 4 ++++ 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java b/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java index 79991fb7..8cda4c09 100644 --- a/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java +++ b/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java @@ -1,5 +1,7 @@ package taco.klkl.domain.product.dao; +import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -7,4 +9,5 @@ @Repository public interface ProductRepository extends JpaRepository { + List findAllByUserId(final Long userId); } diff --git a/src/main/java/taco/klkl/domain/user/controller/UserController.java b/src/main/java/taco/klkl/domain/user/controller/UserController.java index 696131d1..c06930e3 100644 --- a/src/main/java/taco/klkl/domain/user/controller/UserController.java +++ b/src/main/java/taco/klkl/domain/user/controller/UserController.java @@ -1,5 +1,7 @@ package taco.klkl.domain.user.controller; +import java.util.List; + import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -11,9 +13,12 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import taco.klkl.domain.product.dto.response.ProductSimpleResponse; +import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserUpdateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; import taco.klkl.domain.user.service.UserService; +import taco.klkl.global.util.UserUtil; @Slf4j @RestController @@ -23,11 +28,13 @@ public class UserController { private final UserService userService; + private final UserUtil userUtil; @Operation(summary = "내 정보 조회", description = "내 정보를 조회합니다. (테스트용)") @GetMapping("/me") public UserDetailResponse getMe() { - return userService.getCurrentUser(); + final User me = userUtil.getCurrentUser(); + return userService.getUserById(me.getId()); } @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") @@ -35,4 +42,11 @@ public UserDetailResponse getMe() { public UserDetailResponse updateMe(@Valid @RequestBody UserUpdateRequest request) { return userService.updateUser(request); } + + @Operation(summary = "내 상품 목록 조회", description = "내 상품 목록을 조회합니다.") + @GetMapping("/me/products") + public List getMyProducts() { + final User me = userUtil.getCurrentUser(); + return userService.getUserProductsById(me.getId()); + } } diff --git a/src/main/java/taco/klkl/domain/user/service/UserService.java b/src/main/java/taco/klkl/domain/user/service/UserService.java index 5da364a0..3b8a4e2e 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserService.java +++ b/src/main/java/taco/klkl/domain/user/service/UserService.java @@ -1,7 +1,10 @@ package taco.klkl.domain.user.service; +import java.util.List; + import org.springframework.stereotype.Service; +import taco.klkl.domain.product.dto.response.ProductSimpleResponse; import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserCreateRequest; import taco.klkl.domain.user.dto.request.UserUpdateRequest; @@ -10,7 +13,9 @@ @Service public interface UserService { - UserDetailResponse getCurrentUser(); + UserDetailResponse getUserById(final Long id); + + List getUserProductsById(final Long id); UserDetailResponse updateUser(final UserUpdateRequest updateRequest); diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index ee143aa0..7cc1f111 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -1,16 +1,21 @@ package taco.klkl.domain.user.service; +import java.util.List; + import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import taco.klkl.domain.product.dto.response.ProductSimpleResponse; import taco.klkl.domain.user.dao.UserRepository; import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserCreateRequest; import taco.klkl.domain.user.dto.request.UserUpdateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; +import taco.klkl.domain.user.exception.UserNotFoundException; +import taco.klkl.global.util.ProductUtil; import taco.klkl.global.util.UserUtil; @Slf4j @@ -22,6 +27,7 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; + private final ProductUtil productUtil; private final UserUtil userUtil; /** @@ -29,9 +35,19 @@ public class UserServiceImpl implements UserService { * name 속성이 "testUser"인 유저를 반환합니다. */ @Override - public UserDetailResponse getCurrentUser() { - final User currentUser = userUtil.getCurrentUser(); - return UserDetailResponse.from(currentUser); + public UserDetailResponse getUserById(final Long id) { + final User user = userRepository.findById(id) + .orElseThrow(UserNotFoundException::new); + return UserDetailResponse.from(user); + } + + @Override + public List getUserProductsById(final Long id) { + userRepository.findById(id) + .orElseThrow(UserNotFoundException::new); + return productUtil.findProductsByUserId(id).stream() + .map(ProductSimpleResponse::from) + .toList(); } @Override diff --git a/src/main/java/taco/klkl/global/util/ProductUtil.java b/src/main/java/taco/klkl/global/util/ProductUtil.java index ef17316a..eaca67e1 100644 --- a/src/main/java/taco/klkl/global/util/ProductUtil.java +++ b/src/main/java/taco/klkl/global/util/ProductUtil.java @@ -29,6 +29,10 @@ public Product findProductEntityById(final Long id) { .orElseThrow(ProductNotFoundException::new); } + public List findProductsByUserId(final Long userId) { + return productRepository.findAllByUserId(userId); + } + public void validateProductId(final Long id) { final boolean existsById = productRepository.existsById(id); if (!existsById) { From 0b7c5f87357d076d29cacf166ba5ff5b1f676d24 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 14:47:12 +0900 Subject: [PATCH 08/35] KL-166/test: fix test errors --- .../domain/user/controller/UserControllerTest.java | 12 +++++++++--- .../domain/user/integration/UserIntegrationTest.java | 7 ++++++- .../domain/user/service/UserServiceImplTest.java | 4 ++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/test/java/taco/klkl/domain/user/controller/UserControllerTest.java b/src/test/java/taco/klkl/domain/user/controller/UserControllerTest.java index 12f9fa52..047aea50 100644 --- a/src/test/java/taco/klkl/domain/user/controller/UserControllerTest.java +++ b/src/test/java/taco/klkl/domain/user/controller/UserControllerTest.java @@ -1,13 +1,13 @@ package taco.klkl.domain.user.controller; import static org.hamcrest.Matchers.*; +import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -18,6 +18,7 @@ import taco.klkl.domain.user.dto.response.UserDetailResponse; import taco.klkl.domain.user.service.UserService; import taco.klkl.global.common.constants.UserConstants; +import taco.klkl.global.util.UserUtil; @WebMvcTest(UserController.class) class UserControllerTest { @@ -28,11 +29,15 @@ class UserControllerTest { @MockBean UserService userService; + @MockBean + UserUtil userUtil; + + private User user; private UserDetailResponse userDetailResponse; @BeforeEach public void setUp() { - final User user = User.of("name", "description"); + user = User.of("name", "description"); userDetailResponse = UserDetailResponse.from(user); } @@ -40,7 +45,8 @@ public void setUp() { @DisplayName("내 정보 조회 API 테스트") public void testGetMe() throws Exception { // given - Mockito.when(userService.getCurrentUser()).thenReturn(userDetailResponse); + when(userUtil.getCurrentUser()).thenReturn(user); + when(userService.getUserById(any())).thenReturn(userDetailResponse); // when & then mockMvc.perform(get("/v1/users/me") diff --git a/src/test/java/taco/klkl/domain/user/integration/UserIntegrationTest.java b/src/test/java/taco/klkl/domain/user/integration/UserIntegrationTest.java index ece3cee4..928c84db 100644 --- a/src/test/java/taco/klkl/domain/user/integration/UserIntegrationTest.java +++ b/src/test/java/taco/klkl/domain/user/integration/UserIntegrationTest.java @@ -12,8 +12,10 @@ import org.springframework.transaction.annotation.Transactional; import taco.klkl.domain.user.dao.UserRepository; +import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.response.UserDetailResponse; import taco.klkl.domain.user.service.UserService; +import taco.klkl.global.util.UserUtil; @SpringBootTest @AutoConfigureMockMvc @@ -28,10 +30,13 @@ public class UserIntegrationTest { @Autowired UserRepository userRepository; + UserUtil userUtil; + @Test public void testUserMe() throws Exception { // given, when - UserDetailResponse currentUser = userService.getCurrentUser(); + User me = userUtil.getCurrentUser(); + UserDetailResponse currentUser = userService.getUserById(me.getId()); // then mockMvc.perform(get("/v1/users/me")) diff --git a/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java b/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java index 3d05c80b..de97210e 100644 --- a/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java +++ b/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java @@ -34,7 +34,7 @@ class UserServiceImplTest { @Test @DisplayName("내 정보 조회 서비스 테스트") - public void testGetCurrentUser() { + public void testGetUserById() { // given User user = mock(User.class); @@ -44,7 +44,7 @@ public void testGetCurrentUser() { when(user.getDescription()).thenReturn("테스트입니다."); // when - UserDetailResponse userDto = userServiceImpl.getCurrentUser(); + UserDetailResponse userDto = userServiceImpl.getUserById(1L); // then assertThat(userDto.id()).isEqualTo(user.getId()); From 1d836128ed94e4732704959e173c6a1bd3622d12 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 14:50:11 +0900 Subject: [PATCH 09/35] KL-166/feat: get user info --- .../taco/klkl/domain/user/controller/UserController.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/taco/klkl/domain/user/controller/UserController.java b/src/main/java/taco/klkl/domain/user/controller/UserController.java index c06930e3..0d0e393a 100644 --- a/src/main/java/taco/klkl/domain/user/controller/UserController.java +++ b/src/main/java/taco/klkl/domain/user/controller/UserController.java @@ -3,6 +3,7 @@ import java.util.List; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -30,13 +31,19 @@ public class UserController { private final UserService userService; private final UserUtil userUtil; - @Operation(summary = "내 정보 조회", description = "내 정보를 조회합니다. (테스트용)") + @Operation(summary = "내 정보 조회", description = "내 정보를 조회합니다.") @GetMapping("/me") public UserDetailResponse getMe() { final User me = userUtil.getCurrentUser(); return userService.getUserById(me.getId()); } + @Operation(summary = "유저 정보 조회", description = "유저 정보를 조회합니다.") + @GetMapping("/{userId}") + public UserDetailResponse getUser(@PathVariable Long userId) { + return userService.getUserById(userId); + } + @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") @PutMapping("/me") public UserDetailResponse updateMe(@Valid @RequestBody UserUpdateRequest request) { From 9edf2abb1e464ff5b61f7fb471ae0afc2507e327 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 14:52:04 +0900 Subject: [PATCH 10/35] KL-166/feat: get user products --- .../user/controller/UserController.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/java/taco/klkl/domain/user/controller/UserController.java b/src/main/java/taco/klkl/domain/user/controller/UserController.java index 0d0e393a..1e819fa0 100644 --- a/src/main/java/taco/klkl/domain/user/controller/UserController.java +++ b/src/main/java/taco/klkl/domain/user/controller/UserController.java @@ -40,20 +40,26 @@ public UserDetailResponse getMe() { @Operation(summary = "유저 정보 조회", description = "유저 정보를 조회합니다.") @GetMapping("/{userId}") - public UserDetailResponse getUser(@PathVariable Long userId) { + public UserDetailResponse getUser(@PathVariable final Long userId) { return userService.getUserById(userId); } - @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") - @PutMapping("/me") - public UserDetailResponse updateMe(@Valid @RequestBody UserUpdateRequest request) { - return userService.updateUser(request); - } - @Operation(summary = "내 상품 목록 조회", description = "내 상품 목록을 조회합니다.") @GetMapping("/me/products") public List getMyProducts() { final User me = userUtil.getCurrentUser(); return userService.getUserProductsById(me.getId()); } + + @Operation(summary = "유저의 상품 목록 조회", description = "유저의 상품 목록을 조회합니다.") + @GetMapping("/{userId}/products") + public List getUserProducts(@PathVariable final Long userId) { + return userService.getUserProductsById(userId); + } + + @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") + @PutMapping("/me") + public UserDetailResponse updateMe(@Valid @RequestBody final UserUpdateRequest request) { + return userService.updateUser(request); + } } From 11df6871fa864bcc90db055062c423c908d63037 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 15:00:52 +0900 Subject: [PATCH 11/35] KL-166/feat: get my likes --- .../klkl/domain/like/dao/LikeRepository.java | 7 +++++-- .../user/controller/UserController.java | 7 +++++++ .../klkl/domain/user/service/UserService.java | 2 ++ .../domain/user/service/UserServiceImpl.java | 13 ++++++++++++ .../java/taco/klkl/global/util/LikeUtil.java | 20 +++++++++++++++++++ 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 src/main/java/taco/klkl/global/util/LikeUtil.java diff --git a/src/main/java/taco/klkl/domain/like/dao/LikeRepository.java b/src/main/java/taco/klkl/domain/like/dao/LikeRepository.java index 57a4eee1..4859c616 100644 --- a/src/main/java/taco/klkl/domain/like/dao/LikeRepository.java +++ b/src/main/java/taco/klkl/domain/like/dao/LikeRepository.java @@ -1,5 +1,7 @@ package taco.klkl.domain.like.dao; +import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -9,8 +11,9 @@ @Repository public interface LikeRepository extends JpaRepository { + List findAllByUserId(final Long userId); - void deleteByProductAndUser(Product product, User user); + void deleteByProductAndUser(final Product product, final User user); - boolean existsByProductAndUser(Product product, User user); + boolean existsByProductAndUser(final Product product, final User user); } diff --git a/src/main/java/taco/klkl/domain/user/controller/UserController.java b/src/main/java/taco/klkl/domain/user/controller/UserController.java index 1e819fa0..7342482d 100644 --- a/src/main/java/taco/klkl/domain/user/controller/UserController.java +++ b/src/main/java/taco/klkl/domain/user/controller/UserController.java @@ -57,6 +57,13 @@ public List getUserProducts(@PathVariable final Long user return userService.getUserProductsById(userId); } + @Operation(summary = "내 종아요 목록 조회", description = "내 좋아요 목록을 조회합니다.") + @GetMapping("/me/likes") + public List getMyLikes() { + final User me = userUtil.getCurrentUser(); + return userService.getUserLikesById(me.getId()); + } + @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") @PutMapping("/me") public UserDetailResponse updateMe(@Valid @RequestBody final UserUpdateRequest request) { diff --git a/src/main/java/taco/klkl/domain/user/service/UserService.java b/src/main/java/taco/klkl/domain/user/service/UserService.java index 3b8a4e2e..f991582e 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserService.java +++ b/src/main/java/taco/klkl/domain/user/service/UserService.java @@ -17,6 +17,8 @@ public interface UserService { List getUserProductsById(final Long id); + List getUserLikesById(final Long id); + UserDetailResponse updateUser(final UserUpdateRequest updateRequest); User createUser(final UserCreateRequest createRequest); diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index 7cc1f111..e30d1e64 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -8,6 +8,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import taco.klkl.domain.like.domain.Like; import taco.klkl.domain.product.dto.response.ProductSimpleResponse; import taco.klkl.domain.user.dao.UserRepository; import taco.klkl.domain.user.domain.User; @@ -15,6 +16,7 @@ import taco.klkl.domain.user.dto.request.UserUpdateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; import taco.klkl.domain.user.exception.UserNotFoundException; +import taco.klkl.global.util.LikeUtil; import taco.klkl.global.util.ProductUtil; import taco.klkl.global.util.UserUtil; @@ -29,6 +31,7 @@ public class UserServiceImpl implements UserService { private final ProductUtil productUtil; private final UserUtil userUtil; + private final LikeUtil likeUtil; /** * 임시 나의 정보 조회 @@ -50,6 +53,16 @@ public List getUserProductsById(final Long id) { .toList(); } + @Override + public List getUserLikesById(final Long id) { + userRepository.findById(id) + .orElseThrow(UserNotFoundException::new); + return likeUtil.findLikesByUserId(id).stream() + .map(Like::getProduct) + .map(ProductSimpleResponse::from) + .toList(); + } + @Override @Transactional public UserDetailResponse updateUser(final UserUpdateRequest updateRequest) { diff --git a/src/main/java/taco/klkl/global/util/LikeUtil.java b/src/main/java/taco/klkl/global/util/LikeUtil.java new file mode 100644 index 00000000..d8975dee --- /dev/null +++ b/src/main/java/taco/klkl/global/util/LikeUtil.java @@ -0,0 +1,20 @@ +package taco.klkl.global.util; + +import java.util.List; + +import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; +import taco.klkl.domain.like.dao.LikeRepository; +import taco.klkl.domain.like.domain.Like; + +@Component +@RequiredArgsConstructor +public class LikeUtil { + + private final LikeRepository likeRepository; + + public List findLikesByUserId(final Long userId) { + return likeRepository.findAllByUserId(userId); + } +} From c9dcde6f8cc26cfc8d6cfb9bb05cc4e32023c049 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 15:19:08 +0900 Subject: [PATCH 12/35] KL-166/chore: remove unused method --- src/main/java/taco/klkl/domain/user/dao/UserRepository.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/taco/klkl/domain/user/dao/UserRepository.java b/src/main/java/taco/klkl/domain/user/dao/UserRepository.java index 67d34092..e45a03cd 100644 --- a/src/main/java/taco/klkl/domain/user/dao/UserRepository.java +++ b/src/main/java/taco/klkl/domain/user/dao/UserRepository.java @@ -7,7 +7,6 @@ @Repository public interface UserRepository extends JpaRepository { - User findFirstByName(String name); - boolean existsByName(String name); + boolean existsByName(final String name); } From e1e7b56baad56abcd3099670a3f5d79476d0aeea Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 15:19:28 +0900 Subject: [PATCH 13/35] KL-166/feat: add follow entity --- .../taco/klkl/domain/user/domain/Follow.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/main/java/taco/klkl/domain/user/domain/Follow.java diff --git a/src/main/java/taco/klkl/domain/user/domain/Follow.java b/src/main/java/taco/klkl/domain/user/domain/Follow.java new file mode 100644 index 00000000..30812976 --- /dev/null +++ b/src/main/java/taco/klkl/domain/user/domain/Follow.java @@ -0,0 +1,69 @@ +package taco.klkl.domain.user.domain; + +import java.time.LocalDateTime; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@Entity(name = "follow") +@Table( + uniqueConstraints = { + @UniqueConstraint(columnNames = {"follower_id", "following_id"}) + } +) +public class Follow { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "follow_id") + private Long id; + + @ManyToOne( + fetch = FetchType.LAZY, + optional = false + ) + @JoinColumn( + name = "follower_id", + nullable = false + ) + private User follower; + + @ManyToOne( + fetch = FetchType.LAZY, + optional = false + ) + @JoinColumn( + name = "following_id", + nullable = false + ) + private User following; + + @Column( + name = "created_at", + nullable = false + ) + private LocalDateTime createdAt; + + private Follow(final User follower, final User following) { + this.follower = follower; + this.following = following; + this.createdAt = LocalDateTime.now(); + } + + public static Follow of(final User follower, final User following) { + return new Follow(follower, following); + } + +} From 7b3892461f0773800fa78242ea1892d8f4a2ae59 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 15:19:48 +0900 Subject: [PATCH 14/35] KL-166/feat: get my following --- .../domain/user/controller/UserController.java | 8 ++++++++ .../klkl/domain/user/dao/FollowRepository.java | 13 +++++++++++++ .../taco/klkl/domain/user/service/UserService.java | 3 +++ .../klkl/domain/user/service/UserServiceImpl.java | 14 ++++++++++++++ 4 files changed, 38 insertions(+) create mode 100644 src/main/java/taco/klkl/domain/user/dao/FollowRepository.java diff --git a/src/main/java/taco/klkl/domain/user/controller/UserController.java b/src/main/java/taco/klkl/domain/user/controller/UserController.java index 7342482d..8525df04 100644 --- a/src/main/java/taco/klkl/domain/user/controller/UserController.java +++ b/src/main/java/taco/klkl/domain/user/controller/UserController.java @@ -18,6 +18,7 @@ import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserUpdateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; +import taco.klkl.domain.user.dto.response.UserSimpleResponse; import taco.klkl.domain.user.service.UserService; import taco.klkl.global.util.UserUtil; @@ -64,6 +65,13 @@ public List getMyLikes() { return userService.getUserLikesById(me.getId()); } + @Operation(summary = "내 팔로잉 목록 조회", description = "내 팔로잉 목록을 조회합니다.") + @GetMapping("/me/following") + public List getMyFollowings() { + final User me = userUtil.getCurrentUser(); + return userService.getUserFollowingsById(me.getId()); + } + @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") @PutMapping("/me") public UserDetailResponse updateMe(@Valid @RequestBody final UserUpdateRequest request) { diff --git a/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java b/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java new file mode 100644 index 00000000..e78da72d --- /dev/null +++ b/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java @@ -0,0 +1,13 @@ +package taco.klkl.domain.user.dao; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import taco.klkl.domain.user.domain.Follow; + +@Repository +public interface FollowRepository extends JpaRepository { + List findAllByFollowerId(final Long followerId); +} diff --git a/src/main/java/taco/klkl/domain/user/service/UserService.java b/src/main/java/taco/klkl/domain/user/service/UserService.java index f991582e..b3242b92 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserService.java +++ b/src/main/java/taco/klkl/domain/user/service/UserService.java @@ -9,6 +9,7 @@ import taco.klkl.domain.user.dto.request.UserCreateRequest; import taco.klkl.domain.user.dto.request.UserUpdateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; +import taco.klkl.domain.user.dto.response.UserSimpleResponse; @Service public interface UserService { @@ -19,6 +20,8 @@ public interface UserService { List getUserLikesById(final Long id); + List getUserFollowingsById(final Long id); + UserDetailResponse updateUser(final UserUpdateRequest updateRequest); User createUser(final UserCreateRequest createRequest); diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index e30d1e64..c53aa674 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -10,11 +10,14 @@ import lombok.extern.slf4j.Slf4j; import taco.klkl.domain.like.domain.Like; import taco.klkl.domain.product.dto.response.ProductSimpleResponse; +import taco.klkl.domain.user.dao.FollowRepository; import taco.klkl.domain.user.dao.UserRepository; +import taco.klkl.domain.user.domain.Follow; import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserCreateRequest; import taco.klkl.domain.user.dto.request.UserUpdateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; +import taco.klkl.domain.user.dto.response.UserSimpleResponse; import taco.klkl.domain.user.exception.UserNotFoundException; import taco.klkl.global.util.LikeUtil; import taco.klkl.global.util.ProductUtil; @@ -28,6 +31,7 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; + private final FollowRepository followRepository; private final ProductUtil productUtil; private final UserUtil userUtil; @@ -63,6 +67,16 @@ public List getUserLikesById(final Long id) { .toList(); } + @Override + public List getUserFollowingsById(final Long id) { + userRepository.findById(id) + .orElseThrow(UserNotFoundException::new); + return followRepository.findAllByFollowerId(id).stream() + .map(Follow::getFollowing) + .map(UserSimpleResponse::from) + .toList(); + } + @Override @Transactional public UserDetailResponse updateUser(final UserUpdateRequest updateRequest) { From 3b0558a3d57ec4c3331fe135f4d59a43d7159fb2 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 15:50:48 +0900 Subject: [PATCH 15/35] KL-166/refactor: rename to PagedResponse --- .../domain/product/controller/ProductController.java | 6 +++--- .../klkl/domain/product/service/ProductService.java | 6 +++--- .../domain/product/service/ProductServiceImpl.java | 10 +++++----- .../{PagedResponseDto.java => PagedResponse.java} | 6 +++--- .../product/controller/ProductControllerTest.java | 6 +++--- .../domain/product/service/ProductServiceImplTest.java | 6 +++--- 6 files changed, 20 insertions(+), 20 deletions(-) rename src/main/java/taco/klkl/global/common/response/{PagedResponseDto.java => PagedResponse.java} (75%) diff --git a/src/main/java/taco/klkl/domain/product/controller/ProductController.java b/src/main/java/taco/klkl/domain/product/controller/ProductController.java index 2007287a..259a4dc9 100644 --- a/src/main/java/taco/klkl/domain/product/controller/ProductController.java +++ b/src/main/java/taco/klkl/domain/product/controller/ProductController.java @@ -29,7 +29,7 @@ import taco.klkl.domain.product.dto.response.ProductSimpleResponse; import taco.klkl.domain.product.service.ProductService; import taco.klkl.global.common.constants.ProductConstants; -import taco.klkl.global.common.response.PagedResponseDto; +import taco.klkl.global.common.response.PagedResponse; @RestController @RequestMapping("/v1/products") @@ -41,7 +41,7 @@ public class ProductController { @GetMapping @Operation(summary = "상품 목록 조회", description = "상품 목록을 조회합니다.") - public PagedResponseDto findProductsByFilteringAndSorting( + public PagedResponse findProductsByFilteringAndSorting( @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable, @RequestParam(name = "city_id", required = false) Set cityIds, @RequestParam(name = "subcategory_id", required = false) Set subcategoryIds, @@ -63,7 +63,7 @@ public PagedResponseDto findProductsByFilteringAndSorting @GetMapping("/search") @Operation(summary = "제목으로 상품 목록 조회", description = "제목으로 상품 목록을 조회합니다.") - public PagedResponseDto findProductsByPartialNameAndSorting( + public PagedResponse findProductsByPartialNameAndSorting( @RequestParam(value = "name") @NotBlank String partialName, @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable, @RequestParam(name = "sort_by", required = false, defaultValue = "created_at") String sortBy, diff --git a/src/main/java/taco/klkl/domain/product/service/ProductService.java b/src/main/java/taco/klkl/domain/product/service/ProductService.java index ee5fbb09..19f0d334 100644 --- a/src/main/java/taco/klkl/domain/product/service/ProductService.java +++ b/src/main/java/taco/klkl/domain/product/service/ProductService.java @@ -10,12 +10,12 @@ import taco.klkl.domain.product.dto.response.ProductDetailResponse; import taco.klkl.domain.product.dto.response.ProductSimpleResponse; import taco.klkl.domain.product.exception.ProductNotFoundException; -import taco.klkl.global.common.response.PagedResponseDto; +import taco.klkl.global.common.response.PagedResponse; @Service public interface ProductService { - PagedResponseDto findProductsByFilterOptionsAndSortOptions( + PagedResponse findProductsByFilterOptionsAndSortOptions( final Pageable pageable, final ProductFilterOptions filterOptions, final ProductSortOptions sortOptions @@ -33,7 +33,7 @@ PagedResponseDto findProductsByFilterOptionsAndSortOption void deleteProduct(final Long id) throws ProductNotFoundException; - PagedResponseDto findProductsByPartialName(String partialName, Pageable pageable, + PagedResponse findProductsByPartialName(String partialName, Pageable pageable, ProductSortOptions sortOptions); } diff --git a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java index f7db448e..b069fd87 100644 --- a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java +++ b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java @@ -50,7 +50,7 @@ import taco.klkl.domain.region.exception.city.CityNotFoundException; import taco.klkl.domain.region.exception.currency.CurrencyNotFoundException; import taco.klkl.domain.user.domain.User; -import taco.klkl.global.common.response.PagedResponseDto; +import taco.klkl.global.common.response.PagedResponse; import taco.klkl.global.util.CityUtil; import taco.klkl.global.util.CurrencyUtil; import taco.klkl.global.util.SubcategoryUtil; @@ -74,7 +74,7 @@ public class ProductServiceImpl implements ProductService { private final CurrencyUtil currencyUtil; @Override - public PagedResponseDto findProductsByFilterOptionsAndSortOptions( + public PagedResponse findProductsByFilterOptionsAndSortOptions( final Pageable pageable, final ProductFilterOptions filterOptions, final ProductSortOptions sortOptions @@ -86,7 +86,7 @@ public PagedResponseDto findProductsByFilterOptionsAndSor final List products = fetchProducts(baseQuery, pageable, sortOptions); final Page productPage = new PageImpl<>(products, pageable, total); - return PagedResponseDto.of(productPage, ProductSimpleResponse::from); + return PagedResponse.of(productPage, ProductSimpleResponse::from); } @Override @@ -140,7 +140,7 @@ public void deleteProduct(final Long id) throws ProductNotFoundException { } @Override - public PagedResponseDto findProductsByPartialName( + public PagedResponse findProductsByPartialName( final String partialName, final Pageable pageable, final ProductSortOptions sortOptions @@ -165,7 +165,7 @@ public PagedResponseDto findProductsByPartialName( final List products = fetchProducts(baseQuery, pageable, sortOptions); final Page productPage = new PageImpl<>(products, pageable, total); - return PagedResponseDto.of(productPage, ProductSimpleResponse::from); + return PagedResponse.of(productPage, ProductSimpleResponse::from); } private JPAQuery createBaseQuery(final ProductFilterOptions filterOptions) { diff --git a/src/main/java/taco/klkl/global/common/response/PagedResponseDto.java b/src/main/java/taco/klkl/global/common/response/PagedResponse.java similarity index 75% rename from src/main/java/taco/klkl/global/common/response/PagedResponseDto.java rename to src/main/java/taco/klkl/global/common/response/PagedResponse.java index 22cdf8c5..15c95264 100644 --- a/src/main/java/taco/klkl/global/common/response/PagedResponseDto.java +++ b/src/main/java/taco/klkl/global/common/response/PagedResponse.java @@ -5,7 +5,7 @@ import org.springframework.data.domain.Page; -public record PagedResponseDto( +public record PagedResponse( List content, int pageNumber, int pageSize, @@ -14,12 +14,12 @@ public record PagedResponseDto( boolean last ) { - public static PagedResponseDto of(Page page, Function mapper) { + public static PagedResponse of(Page page, Function mapper) { List content = page.getContent().stream() .map(mapper) .toList(); - return new PagedResponseDto<>( + return new PagedResponse<>( content, page.getNumber(), page.getSize(), diff --git a/src/test/java/taco/klkl/domain/product/controller/ProductControllerTest.java b/src/test/java/taco/klkl/domain/product/controller/ProductControllerTest.java index 3084da8d..a0e472d6 100644 --- a/src/test/java/taco/klkl/domain/product/controller/ProductControllerTest.java +++ b/src/test/java/taco/klkl/domain/product/controller/ProductControllerTest.java @@ -38,7 +38,7 @@ import taco.klkl.domain.region.dto.response.city.CityResponse; import taco.klkl.domain.region.dto.response.currency.CurrencyResponse; import taco.klkl.domain.user.dto.response.UserDetailResponse; -import taco.klkl.global.common.response.PagedResponseDto; +import taco.klkl.global.common.response.PagedResponse; @WebMvcTest(ProductController.class) public class ProductControllerTest { @@ -132,7 +132,7 @@ void setUp() { void testFindProducts_ShouldReturnPagedProductsByFilteringAndSorting() throws Exception { // Given List products = List.of(productSimpleResponse); - PagedResponseDto pagedResponse = new PagedResponseDto<>( + PagedResponse pagedResponse = new PagedResponse<>( products, 0, 10, 1, 1, true ); when(productService.findProductsByFilterOptionsAndSortOptions( @@ -200,7 +200,7 @@ void testFindProducts_ShouldReturnPagedProductsByFilteringAndSorting() throws Ex void testFindProductsByPartialNameAndSortOption() throws Exception { // Given List products = List.of(productSimpleResponse); - PagedResponseDto pagedResponse = new PagedResponseDto<>( + PagedResponse pagedResponse = new PagedResponse<>( products, 0, 10, 1, 1, true ); when(productService.findProductsByPartialName( diff --git a/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java b/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java index 2e47dc57..9d3b8b26 100644 --- a/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java +++ b/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java @@ -62,7 +62,7 @@ import taco.klkl.domain.region.domain.region.Region; import taco.klkl.domain.region.domain.region.RegionType; import taco.klkl.domain.user.domain.User; -import taco.klkl.global.common.response.PagedResponseDto; +import taco.klkl.global.common.response.PagedResponse; import taco.klkl.global.util.CityUtil; import taco.klkl.global.util.CurrencyUtil; import taco.klkl.global.util.SubcategoryUtil; @@ -212,7 +212,7 @@ void testFindProductsByFilterOptionsAndSortOptions() { when(tagUtil.findTagEntityById(anyLong())).thenReturn(mockTag); // When - PagedResponseDto result = productService + PagedResponse result = productService .findProductsByFilterOptionsAndSortOptions(pageable, filterOptions, sortOptions); // Then @@ -293,7 +293,7 @@ void testFindProductsByPartialNameAndSortOption() { when(productQuery.orderBy(any(OrderSpecifier.class))).thenReturn(productQuery); // When - PagedResponseDto result = productService + PagedResponse result = productService .findProductsByPartialName("name", pageable, sortOptions); // Then From 677b1bc53b9afaa2188fb5d407194a3033f8d024 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 15:59:28 +0900 Subject: [PATCH 16/35] KL-166/feat: apply pageable to user products and likes --- .../klkl/domain/like/dao/LikeRepository.java | 6 ++--- .../domain/product/dao/ProductRepository.java | 6 ++--- .../user/controller/UserController.java | 27 +++++++++++++------ .../klkl/domain/user/service/UserService.java | 8 +++--- .../domain/user/service/UserServiceImpl.java | 22 ++++++++------- .../java/taco/klkl/global/util/LikeUtil.java | 8 +++--- .../taco/klkl/global/util/ProductUtil.java | 6 +++-- 7 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/main/java/taco/klkl/domain/like/dao/LikeRepository.java b/src/main/java/taco/klkl/domain/like/dao/LikeRepository.java index 4859c616..014d2c93 100644 --- a/src/main/java/taco/klkl/domain/like/dao/LikeRepository.java +++ b/src/main/java/taco/klkl/domain/like/dao/LikeRepository.java @@ -1,7 +1,7 @@ package taco.klkl.domain.like.dao; -import java.util.List; - +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -11,7 +11,7 @@ @Repository public interface LikeRepository extends JpaRepository { - List findAllByUserId(final Long userId); + Page findByUserId(final Long userId, final Pageable pageable); void deleteByProductAndUser(final Product product, final User user); diff --git a/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java b/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java index 8cda4c09..74e614a1 100644 --- a/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java +++ b/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java @@ -1,7 +1,7 @@ package taco.klkl.domain.product.dao; -import java.util.List; - +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -9,5 +9,5 @@ @Repository public interface ProductRepository extends JpaRepository { - List findAllByUserId(final Long userId); + Page findByUserId(final Long userId, final Pageable pageable); } diff --git a/src/main/java/taco/klkl/domain/user/controller/UserController.java b/src/main/java/taco/klkl/domain/user/controller/UserController.java index 8525df04..982ab3ff 100644 --- a/src/main/java/taco/klkl/domain/user/controller/UserController.java +++ b/src/main/java/taco/klkl/domain/user/controller/UserController.java @@ -2,6 +2,8 @@ import java.util.List; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; @@ -20,6 +22,8 @@ import taco.klkl.domain.user.dto.response.UserDetailResponse; import taco.klkl.domain.user.dto.response.UserSimpleResponse; import taco.klkl.domain.user.service.UserService; +import taco.klkl.global.common.constants.ProductConstants; +import taco.klkl.global.common.response.PagedResponse; import taco.klkl.global.util.UserUtil; @Slf4j @@ -47,29 +51,36 @@ public UserDetailResponse getUser(@PathVariable final Long userId) { @Operation(summary = "내 상품 목록 조회", description = "내 상품 목록을 조회합니다.") @GetMapping("/me/products") - public List getMyProducts() { + public PagedResponse getMyProducts( + @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable + ) { final User me = userUtil.getCurrentUser(); - return userService.getUserProductsById(me.getId()); + return userService.getUserProductsById(me.getId(), pageable); } @Operation(summary = "유저의 상품 목록 조회", description = "유저의 상품 목록을 조회합니다.") @GetMapping("/{userId}/products") - public List getUserProducts(@PathVariable final Long userId) { - return userService.getUserProductsById(userId); + public PagedResponse getUserProducts( + @PathVariable final Long userId, + @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable + ) { + return userService.getUserProductsById(userId, pageable); } @Operation(summary = "내 종아요 목록 조회", description = "내 좋아요 목록을 조회합니다.") @GetMapping("/me/likes") - public List getMyLikes() { + public PagedResponse getMyLikes( + @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable + ) { final User me = userUtil.getCurrentUser(); - return userService.getUserLikesById(me.getId()); + return userService.getUserLikesById(me.getId(), pageable); } @Operation(summary = "내 팔로잉 목록 조회", description = "내 팔로잉 목록을 조회합니다.") @GetMapping("/me/following") - public List getMyFollowings() { + public List getMyFollowing() { final User me = userUtil.getCurrentUser(); - return userService.getUserFollowingsById(me.getId()); + return userService.getUserFollowingById(me.getId()); } @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") diff --git a/src/main/java/taco/klkl/domain/user/service/UserService.java b/src/main/java/taco/klkl/domain/user/service/UserService.java index b3242b92..dd15e0ca 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserService.java +++ b/src/main/java/taco/klkl/domain/user/service/UserService.java @@ -2,6 +2,7 @@ import java.util.List; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import taco.klkl.domain.product.dto.response.ProductSimpleResponse; @@ -10,17 +11,18 @@ import taco.klkl.domain.user.dto.request.UserUpdateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; import taco.klkl.domain.user.dto.response.UserSimpleResponse; +import taco.klkl.global.common.response.PagedResponse; @Service public interface UserService { UserDetailResponse getUserById(final Long id); - List getUserProductsById(final Long id); + PagedResponse getUserProductsById(final Long id, final Pageable pageable); - List getUserLikesById(final Long id); + PagedResponse getUserLikesById(final Long id, final Pageable pageable); - List getUserFollowingsById(final Long id); + List getUserFollowingById(final Long id); UserDetailResponse updateUser(final UserUpdateRequest updateRequest); diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index c53aa674..7dab08a1 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -3,12 +3,15 @@ import java.util.List; import org.springframework.context.annotation.Primary; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import taco.klkl.domain.like.domain.Like; +import taco.klkl.domain.product.domain.Product; import taco.klkl.domain.product.dto.response.ProductSimpleResponse; import taco.klkl.domain.user.dao.FollowRepository; import taco.klkl.domain.user.dao.UserRepository; @@ -19,6 +22,7 @@ import taco.klkl.domain.user.dto.response.UserDetailResponse; import taco.klkl.domain.user.dto.response.UserSimpleResponse; import taco.klkl.domain.user.exception.UserNotFoundException; +import taco.klkl.global.common.response.PagedResponse; import taco.klkl.global.util.LikeUtil; import taco.klkl.global.util.ProductUtil; import taco.klkl.global.util.UserUtil; @@ -49,26 +53,24 @@ public UserDetailResponse getUserById(final Long id) { } @Override - public List getUserProductsById(final Long id) { + public PagedResponse getUserProductsById(final Long id, final Pageable pageable) { userRepository.findById(id) .orElseThrow(UserNotFoundException::new); - return productUtil.findProductsByUserId(id).stream() - .map(ProductSimpleResponse::from) - .toList(); + final Page userProducts = productUtil.findProductsByUserId(id, pageable); + return PagedResponse.of(userProducts, ProductSimpleResponse::from); } @Override - public List getUserLikesById(final Long id) { + public PagedResponse getUserLikesById(final Long id, final Pageable pageable) { userRepository.findById(id) .orElseThrow(UserNotFoundException::new); - return likeUtil.findLikesByUserId(id).stream() - .map(Like::getProduct) - .map(ProductSimpleResponse::from) - .toList(); + final Page likes = likeUtil.findLikesByUserId(id, pageable); + final Page likedProducts = likes.map(Like::getProduct); + return PagedResponse.of(likedProducts, ProductSimpleResponse::from); } @Override - public List getUserFollowingsById(final Long id) { + public List getUserFollowingById(final Long id) { userRepository.findById(id) .orElseThrow(UserNotFoundException::new); return followRepository.findAllByFollowerId(id).stream() diff --git a/src/main/java/taco/klkl/global/util/LikeUtil.java b/src/main/java/taco/klkl/global/util/LikeUtil.java index d8975dee..6b52dbf4 100644 --- a/src/main/java/taco/klkl/global/util/LikeUtil.java +++ b/src/main/java/taco/klkl/global/util/LikeUtil.java @@ -1,7 +1,7 @@ package taco.klkl.global.util; -import java.util.List; - +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Component; import lombok.RequiredArgsConstructor; @@ -14,7 +14,7 @@ public class LikeUtil { private final LikeRepository likeRepository; - public List findLikesByUserId(final Long userId) { - return likeRepository.findAllByUserId(userId); + public Page findLikesByUserId(final Long userId, final Pageable pageable) { + return likeRepository.findByUserId(userId, pageable); } } diff --git a/src/main/java/taco/klkl/global/util/ProductUtil.java b/src/main/java/taco/klkl/global/util/ProductUtil.java index eaca67e1..e0642cf3 100644 --- a/src/main/java/taco/klkl/global/util/ProductUtil.java +++ b/src/main/java/taco/klkl/global/util/ProductUtil.java @@ -7,6 +7,8 @@ import java.util.Set; import java.util.stream.Collectors; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Component; import lombok.RequiredArgsConstructor; @@ -29,8 +31,8 @@ public Product findProductEntityById(final Long id) { .orElseThrow(ProductNotFoundException::new); } - public List findProductsByUserId(final Long userId) { - return productRepository.findAllByUserId(userId); + public Page findProductsByUserId(final Long userId, final Pageable pageable) { + return productRepository.findByUserId(userId, pageable); } public void validateProductId(final Long id) { From 1b27d6985eb9746beed4f5c4256dc0fb2d4accbe Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 16:23:10 +0900 Subject: [PATCH 17/35] Kl-166/feat: sort user products and likes by createdAt desc --- .../domain/user/service/UserServiceImpl.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index 7dab08a1..07fb3a7c 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -4,7 +4,9 @@ import org.springframework.context.annotation.Primary; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -56,7 +58,8 @@ public UserDetailResponse getUserById(final Long id) { public PagedResponse getUserProductsById(final Long id, final Pageable pageable) { userRepository.findById(id) .orElseThrow(UserNotFoundException::new); - final Page userProducts = productUtil.findProductsByUserId(id, pageable); + final Pageable sortedPageable = createPageableSortedByCreatedAtDesc(pageable); + final Page userProducts = productUtil.findProductsByUserId(id, sortedPageable); return PagedResponse.of(userProducts, ProductSimpleResponse::from); } @@ -64,7 +67,8 @@ public PagedResponse getUserProductsById(final Long id, f public PagedResponse getUserLikesById(final Long id, final Pageable pageable) { userRepository.findById(id) .orElseThrow(UserNotFoundException::new); - final Page likes = likeUtil.findLikesByUserId(id, pageable); + final Pageable sortedPageable = createPageableSortedByCreatedAtDesc(pageable); + final Page likes = likeUtil.findLikesByUserId(id, sortedPageable); final Page likedProducts = likes.map(Like::getProduct); return PagedResponse.of(likedProducts, ProductSimpleResponse::from); } @@ -113,4 +117,12 @@ private void updateUserEntity(final User user, final UserUpdateRequest updateReq description ); } + + private Pageable createPageableSortedByCreatedAtDesc(final Pageable pageable) { + return PageRequest.of( + pageable.getPageNumber(), + pageable.getPageSize(), + Sort.by(Sort.Direction.DESC, "createdAt") + ); + } } From bbd22e112a0434a67ef8027d73e2c1fbc4002141 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 16:56:55 +0900 Subject: [PATCH 18/35] KL-166/feat: get my following products --- .../product/controller/ProductController.java | 8 ++ .../domain/product/dao/ProductRepository.java | 6 ++ .../product/service/ProductService.java | 11 ++- .../product/service/ProductServiceImpl.java | 75 ++++++++++++------- .../domain/user/dao/FollowRepository.java | 2 +- .../domain/user/service/UserServiceImpl.java | 2 +- 6 files changed, 70 insertions(+), 34 deletions(-) diff --git a/src/main/java/taco/klkl/domain/product/controller/ProductController.java b/src/main/java/taco/klkl/domain/product/controller/ProductController.java index 259a4dc9..f97a0db6 100644 --- a/src/main/java/taco/klkl/domain/product/controller/ProductController.java +++ b/src/main/java/taco/klkl/domain/product/controller/ProductController.java @@ -76,6 +76,14 @@ public PagedResponse findProductsByPartialNameAndSorting( return productService.findProductsByPartialName(partialName, pageable, sortOptions); } + @GetMapping("/following") + @Operation(summary = "내 팔로잉의 상품 목록 조회", description = "내 팔로잉 유저들의 상품 목록을 조회합니다.") + public PagedResponse findFollowingProducts( + @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable + ) { + return productService.findMyFollowingProducts(pageable); + } + @GetMapping("/{productId}") @Operation(summary = "상품 상세 조회", description = "상품 상세 정보를 조회합니다.") public ProductDetailResponse findProductById( diff --git a/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java b/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java index 74e614a1..92252aa1 100644 --- a/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java +++ b/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java @@ -3,11 +3,17 @@ 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; import org.springframework.stereotype.Repository; import taco.klkl.domain.product.domain.Product; +import taco.klkl.domain.user.domain.User; @Repository public interface ProductRepository extends JpaRepository { Page findByUserId(final Long userId, final Pageable pageable); + + @Query("SELECT p FROM product p WHERE p.user IN (SELECT f.following FROM follow f WHERE f.follower = :user)") + Page findProductsOfFollowedUsers(@Param("user") final User user, final Pageable pageable); } diff --git a/src/main/java/taco/klkl/domain/product/service/ProductService.java b/src/main/java/taco/klkl/domain/product/service/ProductService.java index 19f0d334..04d3d70f 100644 --- a/src/main/java/taco/klkl/domain/product/service/ProductService.java +++ b/src/main/java/taco/klkl/domain/product/service/ProductService.java @@ -21,6 +21,14 @@ PagedResponse findProductsByFilterOptionsAndSortOptions( final ProductSortOptions sortOptions ); + PagedResponse findProductsByPartialName( + String partialName, + Pageable pageable, + ProductSortOptions sortOptions + ); + + PagedResponse findMyFollowingProducts(final Pageable pageable); + ProductDetailResponse findProductById(final Long id) throws ProductNotFoundException; ProductDetailResponse createProduct(final ProductCreateUpdateRequest createRequest); @@ -33,7 +41,4 @@ PagedResponse findProductsByFilterOptionsAndSortOptions( void deleteProduct(final Long id) throws ProductNotFoundException; - PagedResponse findProductsByPartialName(String partialName, Pageable pageable, - ProductSortOptions sortOptions); - } diff --git a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java index b069fd87..33237883 100644 --- a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java +++ b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java @@ -8,6 +8,7 @@ import org.springframework.context.annotation.Primary; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; @@ -89,6 +90,43 @@ public PagedResponse findProductsByFilterOptionsAndSortOp return PagedResponse.of(productPage, ProductSimpleResponse::from); } + @Override + public PagedResponse findProductsByPartialName( + final String partialName, + final Pageable pageable, + final ProductSortOptions sortOptions + ) { + final QProduct product = QProduct.product; + final QCity city = QCity.city; + final QCountry country = QCountry.country; + final QSubcategory subcategory = QSubcategory.subcategory; + final QCategory category = QCategory.category; + + final JPAQuery baseQuery = queryFactory + .from(product) + .where(product.name.contains(partialName)); + + final long total = getCount(baseQuery); + + baseQuery.join(product.city, city).fetchJoin() + .join(product.subcategory, subcategory).fetchJoin() + .join(city.country, country).fetchJoin() + .join(subcategory.category, category).fetchJoin(); + + final List products = fetchProducts(baseQuery, pageable, sortOptions); + final Page productPage = new PageImpl<>(products, pageable, total); + + return PagedResponse.of(productPage, ProductSimpleResponse::from); + } + + @Override + public PagedResponse findMyFollowingProducts(final Pageable pageable) { + final User me = userUtil.getCurrentUser(); + final Pageable sortedPageable = createPageableSortedByCreatedAtDesc(pageable); + final Page followingProducts = productRepository.findProductsOfFollowedUsers(me, sortedPageable); + return PagedResponse.of(followingProducts, ProductSimpleResponse::from); + } + @Override public ProductDetailResponse findProductById(final Long id) throws ProductNotFoundException { final Product product = productRepository.findById(id) @@ -139,35 +177,6 @@ public void deleteProduct(final Long id) throws ProductNotFoundException { productRepository.delete(product); } - @Override - public PagedResponse findProductsByPartialName( - final String partialName, - final Pageable pageable, - final ProductSortOptions sortOptions - ) { - final QProduct product = QProduct.product; - final QCity city = QCity.city; - final QCountry country = QCountry.country; - final QSubcategory subcategory = QSubcategory.subcategory; - final QCategory category = QCategory.category; - - final JPAQuery baseQuery = queryFactory - .from(product) - .where(product.name.contains(partialName)); - - final long total = getCount(baseQuery); - - baseQuery.join(product.city, city).fetchJoin() - .join(product.subcategory, subcategory).fetchJoin() - .join(city.country, country).fetchJoin() - .join(subcategory.category, category).fetchJoin(); - - final List products = fetchProducts(baseQuery, pageable, sortOptions); - final Page productPage = new PageImpl<>(products, pageable, total); - - return PagedResponse.of(productPage, ProductSimpleResponse::from); - } - private JPAQuery createBaseQuery(final ProductFilterOptions filterOptions) { final QProduct product = QProduct.product; final QProductTag productTag = QProductTag.productTag; @@ -299,6 +308,14 @@ private Sort.Direction createSortDirectionByQuery(final String query) throws Sor } } + private Pageable createPageableSortedByCreatedAtDesc(final Pageable pageable) { + return PageRequest.of( + pageable.getPageNumber(), + pageable.getPageSize(), + Sort.by(Sort.Direction.DESC, "createdAt") + ); + } + private City findCityById(final Long cityId) throws CityNotFoundException { return cityUtil.findCityEntityById(cityId); } diff --git a/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java b/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java index e78da72d..435dfc9b 100644 --- a/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java +++ b/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java @@ -9,5 +9,5 @@ @Repository public interface FollowRepository extends JpaRepository { - List findAllByFollowerId(final Long followerId); + List findByFollowerId(final Long followerId); } diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index 07fb3a7c..9083773d 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -77,7 +77,7 @@ public PagedResponse getUserLikesById(final Long id, fina public List getUserFollowingById(final Long id) { userRepository.findById(id) .orElseThrow(UserNotFoundException::new); - return followRepository.findAllByFollowerId(id).stream() + return followRepository.findByFollowerId(id).stream() .map(Follow::getFollowing) .map(UserSimpleResponse::from) .toList(); From 1b794e07090ca3795cef909ceb1f38bf7dba7ebb Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 16:57:08 +0900 Subject: [PATCH 19/35] KL-166/chore: add dummy user --- src/main/resources/database/data.sql | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/resources/database/data.sql b/src/main/resources/database/data.sql index 0af3fd6d..f4641fb1 100644 --- a/src/main/resources/database/data.sql +++ b/src/main/resources/database/data.sql @@ -1,6 +1,7 @@ /* User */ INSERT INTO klkl_user(user_id, name, description, created_at) -VALUES (1, 'testUser', '테스트입니다.', now()); +VALUES (1, 'testUser', '테스트입니다.', now()), + (2, 'dummy', '덤덤댄스', now()); /* Like */ @@ -135,13 +136,13 @@ INSERT INTO product(product_id, user_id, name, description, address, price, like city_id, subcategory_id, currency_id, created_at) VALUES (101, 1, '곤약젤리', '탱글탱글 맛있는 곤약젤리', '신사이바시 메가돈키호테', 1000, 100, 5.0, 414, 311, 438, now()), (102, 1, '여름 원피스', '시원하고 여름 휴양지 느낌의 원피스', '방콕 짜뚜짝 시장', 300, 333, 4.5, 425, 323, 441, now()), - (390, 1, '왕족발 보쌈 과자', '맛있는 왕족발 보쌈 과자', '상하이 장충동', 3000, 10, 3.0, 422, 311, 439, now()); + (390, 2, '왕족발 보쌈 과자', '맛있는 왕족발 보쌈 과자', '상하이 장충동', 3000, 10, 3.0, 422, 311, 439, now()); /* Comment */ INSERT INTO comment(comment_id, product_id, user_id, content, created_at) VALUES (500, 390, 1, '이거 정말 맛있는데 표현할 방법이 읎네.', now()), - (501, 390, 1, '이거 정말 맛없는데 표현할 방법이 읎네.', now()), - (502, 390, 1, '이거 정말 좋은데 표현할 방법이 읎네.', now()); + (501, 390, 2, '이거 정말 맛없는데 표현할 방법이 읎네.', now()), + (502, 390, 2, '이거 정말 좋은데 표현할 방법이 읎네.', now()); /* Notification */ INSERT INTO notification(notification_id, is_read, created_at, comment_id) From 359248639cb6e26086569da356ab44755e4b5b97 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 17:34:21 +0900 Subject: [PATCH 20/35] KL-166/feat: follow user --- .../user/controller/UserController.java | 11 +++++- .../domain/user/dao/FollowRepository.java | 3 ++ .../user/dto/request/UserFollowRequest.java | 10 ++++++ .../user/dto/response/UserFollowResponse.java | 17 ++++++++++ .../klkl/domain/user/service/UserService.java | 8 +++-- .../domain/user/service/UserServiceImpl.java | 34 +++++++++++++++---- .../constants/UserValidationMessages.java | 1 + 7 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 src/main/java/taco/klkl/domain/user/dto/request/UserFollowRequest.java create mode 100644 src/main/java/taco/klkl/domain/user/dto/response/UserFollowResponse.java diff --git a/src/main/java/taco/klkl/domain/user/controller/UserController.java b/src/main/java/taco/klkl/domain/user/controller/UserController.java index 982ab3ff..b493639d 100644 --- a/src/main/java/taco/klkl/domain/user/controller/UserController.java +++ b/src/main/java/taco/klkl/domain/user/controller/UserController.java @@ -6,6 +6,7 @@ import org.springframework.data.web.PageableDefault; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -18,8 +19,10 @@ import lombok.extern.slf4j.Slf4j; import taco.klkl.domain.product.dto.response.ProductSimpleResponse; import taco.klkl.domain.user.domain.User; +import taco.klkl.domain.user.dto.request.UserFollowRequest; import taco.klkl.domain.user.dto.request.UserUpdateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; +import taco.klkl.domain.user.dto.response.UserFollowResponse; import taco.klkl.domain.user.dto.response.UserSimpleResponse; import taco.klkl.domain.user.service.UserService; import taco.klkl.global.common.constants.ProductConstants; @@ -77,12 +80,18 @@ public PagedResponse getMyLikes( } @Operation(summary = "내 팔로잉 목록 조회", description = "내 팔로잉 목록을 조회합니다.") - @GetMapping("/me/following") + @GetMapping("/following") public List getMyFollowing() { final User me = userUtil.getCurrentUser(); return userService.getUserFollowingById(me.getId()); } + @Operation(summary = "유저 팔로우", description = "유저를 팔로우합니다.") + @PostMapping("/following") + public UserFollowResponse followUser(@Valid @RequestBody final UserFollowRequest request) { + return userService.createUserFollow(request); + } + @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") @PutMapping("/me") public UserDetailResponse updateMe(@Valid @RequestBody final UserUpdateRequest request) { diff --git a/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java b/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java index 435dfc9b..ef141f4e 100644 --- a/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java +++ b/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java @@ -6,8 +6,11 @@ import org.springframework.stereotype.Repository; import taco.klkl.domain.user.domain.Follow; +import taco.klkl.domain.user.domain.User; @Repository public interface FollowRepository extends JpaRepository { List findByFollowerId(final Long followerId); + + boolean existsByFollowerAndFollowing(final User Follower, final User Following); } diff --git a/src/main/java/taco/klkl/domain/user/dto/request/UserFollowRequest.java b/src/main/java/taco/klkl/domain/user/dto/request/UserFollowRequest.java new file mode 100644 index 00000000..c87eb47d --- /dev/null +++ b/src/main/java/taco/klkl/domain/user/dto/request/UserFollowRequest.java @@ -0,0 +1,10 @@ +package taco.klkl.domain.user.dto.request; + +import jakarta.validation.constraints.NotNull; +import taco.klkl.global.common.constants.UserValidationMessages; + +public record UserFollowRequest( + @NotNull(message = UserValidationMessages.TARGET_USER_ID_NOT_NULL) + Long targetUserId +) { +} diff --git a/src/main/java/taco/klkl/domain/user/dto/response/UserFollowResponse.java b/src/main/java/taco/klkl/domain/user/dto/response/UserFollowResponse.java new file mode 100644 index 00000000..019ad127 --- /dev/null +++ b/src/main/java/taco/klkl/domain/user/dto/response/UserFollowResponse.java @@ -0,0 +1,17 @@ +package taco.klkl.domain.user.dto.response; + +import taco.klkl.domain.user.domain.User; + +public record UserFollowResponse( + boolean isFollowing, + Long followerId, + Long followingId +) { + public static UserFollowResponse of(final boolean isFollowing, final User follower, final User following) { + return new UserFollowResponse( + isFollowing, + follower.getId(), + following.getId() + ); + } +} diff --git a/src/main/java/taco/klkl/domain/user/service/UserService.java b/src/main/java/taco/klkl/domain/user/service/UserService.java index dd15e0ca..e457ad75 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserService.java +++ b/src/main/java/taco/klkl/domain/user/service/UserService.java @@ -8,8 +8,10 @@ import taco.klkl.domain.product.dto.response.ProductSimpleResponse; import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserCreateRequest; +import taco.klkl.domain.user.dto.request.UserFollowRequest; import taco.klkl.domain.user.dto.request.UserUpdateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; +import taco.klkl.domain.user.dto.response.UserFollowResponse; import taco.klkl.domain.user.dto.response.UserSimpleResponse; import taco.klkl.global.common.response.PagedResponse; @@ -24,8 +26,10 @@ public interface UserService { List getUserFollowingById(final Long id); - UserDetailResponse updateUser(final UserUpdateRequest updateRequest); - User createUser(final UserCreateRequest createRequest); + UserFollowResponse createUserFollow(final UserFollowRequest followRequest); + + UserDetailResponse updateUser(final UserUpdateRequest updateRequest); + } diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index 9083773d..cd21605b 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -20,8 +20,10 @@ import taco.klkl.domain.user.domain.Follow; import taco.klkl.domain.user.domain.User; import taco.klkl.domain.user.dto.request.UserCreateRequest; +import taco.klkl.domain.user.dto.request.UserFollowRequest; import taco.klkl.domain.user.dto.request.UserUpdateRequest; import taco.klkl.domain.user.dto.response.UserDetailResponse; +import taco.klkl.domain.user.dto.response.UserFollowResponse; import taco.klkl.domain.user.dto.response.UserSimpleResponse; import taco.klkl.domain.user.exception.UserNotFoundException; import taco.klkl.global.common.response.PagedResponse; @@ -85,17 +87,31 @@ public List getUserFollowingById(final Long id) { @Override @Transactional - public UserDetailResponse updateUser(final UserUpdateRequest updateRequest) { - User user = userUtil.getCurrentUser(); - updateUserEntity(user, updateRequest); - return UserDetailResponse.from(user); + public User createUser(final UserCreateRequest createRequest) { + final User user = createUserEntity(createRequest); + return userRepository.save(user); } @Override @Transactional - public User createUser(final UserCreateRequest createRequest) { - final User user = createUserEntity(createRequest); - return userRepository.save(user); + public UserFollowResponse createUserFollow(final UserFollowRequest followRequest) { + final User follower = userUtil.getCurrentUser(); + final User following = userRepository.findById(followRequest.targetUserId()) + .orElseThrow(UserNotFoundException::new); + if (isFollowPresent(follower, following)) { + return UserFollowResponse.of(true, follower, following); + } + final Follow follow = Follow.of(follower, following); + followRepository.save(follow); + return UserFollowResponse.of(true, follower, following); + } + + @Override + @Transactional + public UserDetailResponse updateUser(final UserUpdateRequest updateRequest) { + User user = userUtil.getCurrentUser(); + updateUserEntity(user, updateRequest); + return UserDetailResponse.from(user); } private User createUserEntity(final UserCreateRequest createRequest) { @@ -125,4 +141,8 @@ private Pageable createPageableSortedByCreatedAtDesc(final Pageable pageable) { Sort.by(Sort.Direction.DESC, "createdAt") ); } + + private boolean isFollowPresent(final User follower, final User following) { + return followRepository.existsByFollowerAndFollowing(follower, following); + } } diff --git a/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java b/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java index 0991ad97..6dd75e9c 100644 --- a/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java +++ b/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java @@ -3,6 +3,7 @@ public final class UserValidationMessages { public static final String NAME_NOT_BLANK = "이름은 비워둘 수 없습니다."; + public static final String TARGET_USER_ID_NOT_NULL = "대상 유저 ID는 필수 항목입니다."; private UserValidationMessages() { } From 7f25c85fc23a235019bed59465a57fb2bc349d7e Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 17:42:01 +0900 Subject: [PATCH 21/35] KL-166/feat: cancel user follow --- .../klkl/domain/user/controller/UserController.java | 7 +++++++ .../taco/klkl/domain/user/dao/FollowRepository.java | 2 ++ .../taco/klkl/domain/user/service/UserService.java | 2 ++ .../klkl/domain/user/service/UserServiceImpl.java | 12 ++++++++++++ 4 files changed, 23 insertions(+) diff --git a/src/main/java/taco/klkl/domain/user/controller/UserController.java b/src/main/java/taco/klkl/domain/user/controller/UserController.java index b493639d..9946f522 100644 --- a/src/main/java/taco/klkl/domain/user/controller/UserController.java +++ b/src/main/java/taco/klkl/domain/user/controller/UserController.java @@ -4,6 +4,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -92,6 +93,12 @@ public UserFollowResponse followUser(@Valid @RequestBody final UserFollowRequest return userService.createUserFollow(request); } + @Operation(summary = "유저 팔로우 취소", description = "유저 팔로우를 취소합니다.") + @DeleteMapping("/following/{targetUserId}") + public UserFollowResponse cancelUserFollow(@PathVariable final Long targetUserId) { + return userService.removeUserFollow(targetUserId); + } + @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") @PutMapping("/me") public UserDetailResponse updateMe(@Valid @RequestBody final UserUpdateRequest request) { diff --git a/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java b/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java index ef141f4e..ae6fb79e 100644 --- a/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java +++ b/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java @@ -13,4 +13,6 @@ public interface FollowRepository extends JpaRepository { List findByFollowerId(final Long followerId); boolean existsByFollowerAndFollowing(final User Follower, final User Following); + + void deleteByFollowerAndFollowing(final User follower, final User following); } diff --git a/src/main/java/taco/klkl/domain/user/service/UserService.java b/src/main/java/taco/klkl/domain/user/service/UserService.java index e457ad75..d0398b68 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserService.java +++ b/src/main/java/taco/klkl/domain/user/service/UserService.java @@ -30,6 +30,8 @@ public interface UserService { UserFollowResponse createUserFollow(final UserFollowRequest followRequest); + UserFollowResponse removeUserFollow(final Long followerId); + UserDetailResponse updateUser(final UserUpdateRequest updateRequest); } diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index cd21605b..fa782a80 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -106,6 +106,18 @@ public UserFollowResponse createUserFollow(final UserFollowRequest followRequest return UserFollowResponse.of(true, follower, following); } + @Override + @Transactional + public UserFollowResponse removeUserFollow(final Long followerId) { + final User follower = userUtil.getCurrentUser(); + final User following = userRepository.findById(followerId) + .orElseThrow(UserNotFoundException::new); + if (isFollowPresent(follower, following)) { + followRepository.deleteByFollowerAndFollowing(follower, following); + } + return UserFollowResponse.of(false, follower, following); + } + @Override @Transactional public UserDetailResponse updateUser(final UserUpdateRequest updateRequest) { From 27afc2e52f80f3c15f7a92cdace533dd71404eaf Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 18:05:13 +0900 Subject: [PATCH 22/35] KL-166/fix: notification delete error --- .../taco/klkl/domain/comment/domain/Comment.java | 10 ---------- .../notification/dao/NotificationRepository.java | 2 +- .../service/NotificationServiceImpl.java | 14 ++++++++------ .../service/NotificationServiceTest.java | 4 ++-- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/main/java/taco/klkl/domain/comment/domain/Comment.java b/src/main/java/taco/klkl/domain/comment/domain/Comment.java index 7a0b2653..61a01bf5 100644 --- a/src/main/java/taco/klkl/domain/comment/domain/Comment.java +++ b/src/main/java/taco/klkl/domain/comment/domain/Comment.java @@ -2,7 +2,6 @@ import java.time.LocalDateTime; -import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -11,11 +10,9 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToOne; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import taco.klkl.domain.notification.domain.Notification; import taco.klkl.domain.product.domain.Product; import taco.klkl.domain.user.domain.User; @@ -36,13 +33,6 @@ public class Comment { @JoinColumn(name = "user_id", nullable = false) private User user; - @OneToOne( - mappedBy = "comment", - cascade = CascadeType.ALL, - orphanRemoval = true - ) - private Notification notifications; - @Column( name = "content", nullable = false, diff --git a/src/main/java/taco/klkl/domain/notification/dao/NotificationRepository.java b/src/main/java/taco/klkl/domain/notification/dao/NotificationRepository.java index 7f3c7373..2a1e8f20 100644 --- a/src/main/java/taco/klkl/domain/notification/dao/NotificationRepository.java +++ b/src/main/java/taco/klkl/domain/notification/dao/NotificationRepository.java @@ -8,5 +8,5 @@ import taco.klkl.domain.user.domain.User; public interface NotificationRepository extends JpaRepository { - List findAllByComment_Product_User(User user); + List findByComment_Product_User(final User user); } diff --git a/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java b/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java index 9b6af69d..09b8504d 100644 --- a/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java +++ b/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java @@ -60,10 +60,10 @@ public List findAllNotifications() { @Transactional public NotificationUpdateResponse readAllNotifications() { final User receiver = findReceiver(); - final List notifications = notificationRepository.findAllByComment_Product_User(receiver); + final List notifications = notificationRepository.findByComment_Product_User(receiver); notifications.forEach(Notification::read); - final Long notificationCount = notificationRepository.count(); - return NotificationUpdateResponse.of(notificationCount); + final Long updatedCount = (long)notifications.size(); + return NotificationUpdateResponse.of(updatedCount); } @Override @@ -78,9 +78,11 @@ public NotificationUpdateResponse readNotificationById(final Long id) { @Override @Transactional public NotificationDeleteResponse deleteAllNotifications() { - final Long notificationCount = notificationRepository.count(); - notificationRepository.deleteAll(); - return NotificationDeleteResponse.of(notificationCount); + final User receiver = findReceiver(); + final List notifications = notificationRepository.findByComment_Product_User(receiver); + notificationRepository.deleteAll(notifications); + final Long deletedCount = (long)notifications.size(); + return NotificationDeleteResponse.of(deletedCount); } @Override diff --git a/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java b/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java index f6e5dd9e..bcbb135b 100644 --- a/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java +++ b/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java @@ -179,7 +179,7 @@ public void testReadAllNotifications() { List notificationList = List.of(notification1, notification2); when(userUtil.getCurrentUser()).thenReturn(mockUser); - when(notificationRepository.findAllByComment_Product_User(mockUser)).thenReturn(notificationList); + when(notificationRepository.findByComment_Product_User(mockUser)).thenReturn(notificationList); when(notificationRepository.count()).thenReturn(2L); //when @@ -187,7 +187,7 @@ public void testReadAllNotifications() { //then assertThat(response.updatedCount()).isEqualTo(2L); - verify(notificationRepository).findAllByComment_Product_User(mockUser); + verify(notificationRepository).findByComment_Product_User(mockUser); } @Test From 8811619a0dc97f7d5f9bf16591fb079a2ac7fd24 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 18:10:59 +0900 Subject: [PATCH 23/35] KL-166/fix: notification validation error --- .../notification/service/NotificationServiceImpl.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java b/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java index 09b8504d..52232feb 100644 --- a/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java +++ b/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java @@ -71,6 +71,7 @@ public NotificationUpdateResponse readAllNotifications() { public NotificationUpdateResponse readNotificationById(final Long id) { final Notification notification = notificationRepository.findById(id) .orElseThrow(NotificationNotFoundException::new); + validateNotification(notification); notification.read(); return NotificationUpdateResponse.of(1L); } @@ -96,4 +97,11 @@ public void createNotificationByComment(final Comment comment) { private User findReceiver() { return userUtil.getCurrentUser(); } + + private void validateNotification(final Notification notification) { + final User receiver = findReceiver(); + if (!notification.getComment().getProduct().getUser().equals(receiver)) { + throw new NotificationNotFoundException(); + } + } } From 4fd2e4ab76e2e1adf0ed82b28df0c317bc6fa989 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 18:11:10 +0900 Subject: [PATCH 24/35] KL-166/chore: edit dummy date --- src/main/resources/database/data.sql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/database/data.sql b/src/main/resources/database/data.sql index f4641fb1..c613cf4b 100644 --- a/src/main/resources/database/data.sql +++ b/src/main/resources/database/data.sql @@ -134,13 +134,13 @@ VALUES /* Product */ INSERT INTO product(product_id, user_id, name, description, address, price, like_count, rating, city_id, subcategory_id, currency_id, created_at) -VALUES (101, 1, '곤약젤리', '탱글탱글 맛있는 곤약젤리', '신사이바시 메가돈키호테', 1000, 100, 5.0, 414, 311, 438, now()), - (102, 1, '여름 원피스', '시원하고 여름 휴양지 느낌의 원피스', '방콕 짜뚜짝 시장', 300, 333, 4.5, 425, 323, 441, now()), - (390, 2, '왕족발 보쌈 과자', '맛있는 왕족발 보쌈 과자', '상하이 장충동', 3000, 10, 3.0, 422, 311, 439, now()); +VALUES (101, 2, '곤약젤리', '탱글탱글 맛있는 곤약젤리', '신사이바시 메가돈키호테', 1000, 100, 5.0, 414, 311, 438, now()), + (102, 2, '여름 원피스', '시원하고 여름 휴양지 느낌의 원피스', '방콕 짜뚜짝 시장', 300, 333, 4.5, 425, 323, 441, now()), + (390, 1, '왕족발 보쌈 과자', '맛있는 왕족발 보쌈 과자', '상하이 장충동', 3000, 10, 3.0, 422, 311, 439, now()); /* Comment */ INSERT INTO comment(comment_id, product_id, user_id, content, created_at) -VALUES (500, 390, 1, '이거 정말 맛있는데 표현할 방법이 읎네.', now()), +VALUES (500, 101, 1, '이거 정말 맛있는데 표현할 방법이 읎네.', now()), (501, 390, 2, '이거 정말 맛없는데 표현할 방법이 읎네.', now()), (502, 390, 2, '이거 정말 좋은데 표현할 방법이 읎네.', now()); From 657634c0f31e586e7a236fa252507ce5968b3981 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 18:16:20 +0900 Subject: [PATCH 25/35] KL-166/chore: rename validation method --- .../domain/notification/service/NotificationServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java b/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java index 52232feb..5ed4a9cb 100644 --- a/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java +++ b/src/main/java/taco/klkl/domain/notification/service/NotificationServiceImpl.java @@ -71,7 +71,7 @@ public NotificationUpdateResponse readAllNotifications() { public NotificationUpdateResponse readNotificationById(final Long id) { final Notification notification = notificationRepository.findById(id) .orElseThrow(NotificationNotFoundException::new); - validateNotification(notification); + validateMyNotification(notification); notification.read(); return NotificationUpdateResponse.of(1L); } @@ -98,7 +98,7 @@ private User findReceiver() { return userUtil.getCurrentUser(); } - private void validateNotification(final Notification notification) { + private void validateMyNotification(final Notification notification) { final User receiver = findReceiver(); if (!notification.getComment().getProduct().getUser().equals(receiver)) { throw new NotificationNotFoundException(); From 4d3dd5f40a639febb5485c94cec3678e524f37e1 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 18:17:51 +0900 Subject: [PATCH 26/35] KL-166/refactor: add my product validation --- .../klkl/domain/product/service/ProductServiceImpl.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java index 33237883..e121a9e6 100644 --- a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java +++ b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java @@ -164,6 +164,7 @@ public ProductDetailResponse updateProduct(final Long id, final ProductCreateUpd throws ProductNotFoundException { final Product product = productRepository.findById(id) .orElseThrow(ProductNotFoundException::new); + validateMyProduct(product); updateProductEntity(product, updateRequest); updateProductEntityTags(product, updateRequest.tagIds()); return ProductDetailResponse.from(product); @@ -174,6 +175,7 @@ public ProductDetailResponse updateProduct(final Long id, final ProductCreateUpd public void deleteProduct(final Long id) throws ProductNotFoundException { final Product product = productRepository.findById(id) .orElseThrow(ProductNotFoundException::new); + validateMyProduct(product); productRepository.delete(product); } @@ -354,4 +356,11 @@ private void validateSubcategoryIds(final Set subcategoryIds) { private void validateTagIds(final Set tagIds) { tagIds.forEach(tagUtil::findTagEntityById); } + + private void validateMyProduct(final Product product) { + final User me = userUtil.getCurrentUser(); + if (!product.getUser().equals(me)) { + throw new ProductNotFoundException(); + } + } } From 5657523fe29a1a02489cb496cc1664eb65a0f217 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 18:22:38 +0900 Subject: [PATCH 27/35] KL-166/refactor: add final keyword --- .../product/controller/ProductController.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/main/java/taco/klkl/domain/product/controller/ProductController.java b/src/main/java/taco/klkl/domain/product/controller/ProductController.java index f97a0db6..3943a48d 100644 --- a/src/main/java/taco/klkl/domain/product/controller/ProductController.java +++ b/src/main/java/taco/klkl/domain/product/controller/ProductController.java @@ -42,19 +42,19 @@ public class ProductController { @GetMapping @Operation(summary = "상품 목록 조회", description = "상품 목록을 조회합니다.") public PagedResponse findProductsByFilteringAndSorting( - @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable, - @RequestParam(name = "city_id", required = false) Set cityIds, - @RequestParam(name = "subcategory_id", required = false) Set subcategoryIds, - @RequestParam(name = "tag_id", required = false) Set tagIds, - @RequestParam(name = "sort_by", required = false, defaultValue = "created_at") String sortBy, - @RequestParam(name = "sort_direction", required = false, defaultValue = "DESC") String sortDirection + @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) final Pageable pageable, + @RequestParam(name = "city_id", required = false) final Set cityIds, + @RequestParam(name = "subcategory_id", required = false) final Set subcategoryIds, + @RequestParam(name = "tag_id", required = false) final Set tagIds, + @RequestParam(name = "sort_by", required = false, defaultValue = "created_at") final String sortBy, + @RequestParam(name = "sort_direction", required = false, defaultValue = "DESC") final String sortDirection ) { - ProductFilterOptions filterOptions = new ProductFilterOptions( + final ProductFilterOptions filterOptions = new ProductFilterOptions( cityIds, subcategoryIds, tagIds ); - ProductSortOptions sortOptions = new ProductSortOptions( + final ProductSortOptions sortOptions = new ProductSortOptions( sortBy, sortDirection ); @@ -64,12 +64,12 @@ public PagedResponse findProductsByFilteringAndSorting( @GetMapping("/search") @Operation(summary = "제목으로 상품 목록 조회", description = "제목으로 상품 목록을 조회합니다.") public PagedResponse findProductsByPartialNameAndSorting( - @RequestParam(value = "name") @NotBlank String partialName, - @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable, - @RequestParam(name = "sort_by", required = false, defaultValue = "created_at") String sortBy, - @RequestParam(name = "sort_direction", required = false, defaultValue = "DESC") String sortDirection + @RequestParam(value = "name") @NotBlank final String partialName, + @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) final Pageable pageable, + @RequestParam(name = "sort_by", required = false, defaultValue = "created_at") final String sortBy, + @RequestParam(name = "sort_direction", required = false, defaultValue = "DESC") final String sortDirection ) { - ProductSortOptions sortOptions = new ProductSortOptions( + final ProductSortOptions sortOptions = new ProductSortOptions( sortBy, sortDirection ); @@ -79,7 +79,7 @@ public PagedResponse findProductsByPartialNameAndSorting( @GetMapping("/following") @Operation(summary = "내 팔로잉의 상품 목록 조회", description = "내 팔로잉 유저들의 상품 목록을 조회합니다.") public PagedResponse findFollowingProducts( - @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable + @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) final Pageable pageable ) { return productService.findMyFollowingProducts(pageable); } @@ -87,7 +87,7 @@ public PagedResponse findFollowingProducts( @GetMapping("/{productId}") @Operation(summary = "상품 상세 조회", description = "상품 상세 정보를 조회합니다.") public ProductDetailResponse findProductById( - @PathVariable Long productId + @PathVariable final Long productId ) { return productService.findProductById(productId); } @@ -95,18 +95,18 @@ public ProductDetailResponse findProductById( @PostMapping @Operation(summary = "상품 등록", description = "상품을 등록합니다.") public ResponseEntity createProduct( - @Valid @RequestBody ProductCreateUpdateRequest createRequest + @Valid @RequestBody final ProductCreateUpdateRequest createRequest ) { - ProductDetailResponse createdProduct = productService.createProduct(createRequest); - URI location = createResourceLocation(createdProduct.id()); + final ProductDetailResponse createdProduct = productService.createProduct(createRequest); + final URI location = createResourceLocation(createdProduct.id()); return ResponseEntity.created(location).body(createdProduct); } @PutMapping("/{productId}") @Operation(summary = "상품 정보 수정", description = "상품 정보를 수정합니다.") public ProductDetailResponse updateProduct( - @PathVariable Long productId, - @Valid @RequestBody ProductCreateUpdateRequest updateRequest + @PathVariable final Long productId, + @Valid @RequestBody final ProductCreateUpdateRequest updateRequest ) { return productService.updateProduct(productId, updateRequest); } @@ -114,7 +114,7 @@ public ProductDetailResponse updateProduct( @DeleteMapping("/{productId}") @Operation(summary = "상품 삭제", description = "상품을 삭제합니다.") public ResponseEntity deleteProduct( - @PathVariable Long productId + @PathVariable final Long productId ) { productService.deleteProduct(productId); return ResponseEntity.noContent().build(); From a2a901883927c36683cc021bab554417b3ad864c Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 18:51:37 +0900 Subject: [PATCH 28/35] KL-166/feat: filter by following ids --- .../domain/product/controller/ProductController.java | 5 +++-- .../klkl/domain/product/dao/ProductRepository.java | 12 ++++++++++-- .../klkl/domain/product/service/ProductService.java | 10 ++++++---- .../domain/product/service/ProductServiceImpl.java | 11 +++++++++-- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/main/java/taco/klkl/domain/product/controller/ProductController.java b/src/main/java/taco/klkl/domain/product/controller/ProductController.java index 3943a48d..466043e5 100644 --- a/src/main/java/taco/klkl/domain/product/controller/ProductController.java +++ b/src/main/java/taco/klkl/domain/product/controller/ProductController.java @@ -79,9 +79,10 @@ public PagedResponse findProductsByPartialNameAndSorting( @GetMapping("/following") @Operation(summary = "내 팔로잉의 상품 목록 조회", description = "내 팔로잉 유저들의 상품 목록을 조회합니다.") public PagedResponse findFollowingProducts( - @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) final Pageable pageable + @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) final Pageable pageable, + @RequestParam(value = "following_id", required = false) final Set followingIds ) { - return productService.findMyFollowingProducts(pageable); + return productService.findMyFollowingProducts(pageable, followingIds); } @GetMapping("/{productId}") diff --git a/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java b/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java index 92252aa1..4943da24 100644 --- a/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java +++ b/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java @@ -1,5 +1,7 @@ package taco.klkl.domain.product.dao; +import java.util.Set; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -14,6 +16,12 @@ public interface ProductRepository extends JpaRepository { Page findByUserId(final Long userId, final Pageable pageable); - @Query("SELECT p FROM product p WHERE p.user IN (SELECT f.following FROM follow f WHERE f.follower = :user)") - Page findProductsOfFollowedUsers(@Param("user") final User user, final Pageable pageable); + @Query("SELECT p FROM product p WHERE p.user IN " + + "(SELECT f.following FROM follow f WHERE f.follower = :follower " + + "AND (:followingIds IS NULL OR f.following.id IN :followingIds))") + Page findProductsOfFollowedUsers( + @Param("follower") final User follower, + @Param("followingIds") final Set followingIds, + final Pageable pageable + ); } diff --git a/src/main/java/taco/klkl/domain/product/service/ProductService.java b/src/main/java/taco/klkl/domain/product/service/ProductService.java index 04d3d70f..46f9db10 100644 --- a/src/main/java/taco/klkl/domain/product/service/ProductService.java +++ b/src/main/java/taco/klkl/domain/product/service/ProductService.java @@ -1,5 +1,7 @@ package taco.klkl.domain.product.service; +import java.util.Set; + import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -22,12 +24,12 @@ PagedResponse findProductsByFilterOptionsAndSortOptions( ); PagedResponse findProductsByPartialName( - String partialName, - Pageable pageable, - ProductSortOptions sortOptions + final String partialName, + final Pageable pageable, + final ProductSortOptions sortOptions ); - PagedResponse findMyFollowingProducts(final Pageable pageable); + PagedResponse findMyFollowingProducts(final Pageable pageable, final Set followingIds); ProductDetailResponse findProductById(final Long id) throws ProductNotFoundException; diff --git a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java index e121a9e6..7d525eed 100644 --- a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java +++ b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java @@ -120,10 +120,17 @@ public PagedResponse findProductsByPartialName( } @Override - public PagedResponse findMyFollowingProducts(final Pageable pageable) { + public PagedResponse findMyFollowingProducts( + final Pageable pageable, + final Set followingIds + ) { final User me = userUtil.getCurrentUser(); final Pageable sortedPageable = createPageableSortedByCreatedAtDesc(pageable); - final Page followingProducts = productRepository.findProductsOfFollowedUsers(me, sortedPageable); + final Page followingProducts = productRepository.findProductsOfFollowedUsers( + me, + followingIds, + sortedPageable + ); return PagedResponse.of(followingProducts, ProductSimpleResponse::from); } From f06d0d06ee9ab9f8c1b9a453f56b3fea2a4010f1 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 18:51:57 +0900 Subject: [PATCH 29/35] KL-166/chore: add dummy user and product --- src/main/resources/database/data.sql | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/resources/database/data.sql b/src/main/resources/database/data.sql index c613cf4b..ad6f222c 100644 --- a/src/main/resources/database/data.sql +++ b/src/main/resources/database/data.sql @@ -1,7 +1,8 @@ /* User */ INSERT INTO klkl_user(user_id, name, description, created_at) VALUES (1, 'testUser', '테스트입니다.', now()), - (2, 'dummy', '덤덤댄스', now()); + (2, 'dummy', '덤덤댄스', now()), + (3, 'dumdummy', '덤더미댄스', now()); /* Like */ @@ -136,13 +137,14 @@ INSERT INTO product(product_id, user_id, name, description, address, price, like city_id, subcategory_id, currency_id, created_at) VALUES (101, 2, '곤약젤리', '탱글탱글 맛있는 곤약젤리', '신사이바시 메가돈키호테', 1000, 100, 5.0, 414, 311, 438, now()), (102, 2, '여름 원피스', '시원하고 여름 휴양지 느낌의 원피스', '방콕 짜뚜짝 시장', 300, 333, 4.5, 425, 323, 441, now()), + (103, 3, '하오하오 봉지라면 핑크색', '새우맛이 나는 맛있는 라면', '롯데마트 나트랑', 15000, 500, 5.0, 429, 310, 442, now()), (390, 1, '왕족발 보쌈 과자', '맛있는 왕족발 보쌈 과자', '상하이 장충동', 3000, 10, 3.0, 422, 311, 439, now()); /* Comment */ INSERT INTO comment(comment_id, product_id, user_id, content, created_at) VALUES (500, 101, 1, '이거 정말 맛있는데 표현할 방법이 읎네.', now()), (501, 390, 2, '이거 정말 맛없는데 표현할 방법이 읎네.', now()), - (502, 390, 2, '이거 정말 좋은데 표현할 방법이 읎네.', now()); + (502, 390, 3, '이거 정말 좋은데 표현할 방법이 읎네.', now()); /* Notification */ INSERT INTO notification(notification_id, is_read, created_at, comment_id) From 424abb582056547f6f1a817b14d79db3c9b5953c Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 18:54:07 +0900 Subject: [PATCH 30/35] KL-166/fix: checkstyle errors --- .../taco/klkl/domain/product/dao/ProductRepository.java | 8 +++++--- .../java/taco/klkl/domain/user/dao/FollowRepository.java | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java b/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java index 4943da24..f7183e77 100644 --- a/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java +++ b/src/main/java/taco/klkl/domain/product/dao/ProductRepository.java @@ -16,9 +16,11 @@ public interface ProductRepository extends JpaRepository { Page findByUserId(final Long userId, final Pageable pageable); - @Query("SELECT p FROM product p WHERE p.user IN " + - "(SELECT f.following FROM follow f WHERE f.follower = :follower " + - "AND (:followingIds IS NULL OR f.following.id IN :followingIds))") + @Query( + "SELECT p FROM product p WHERE p.user IN " + + "(SELECT f.following FROM follow f WHERE f.follower = :follower " + + "AND (:followingIds IS NULL OR f.following.id IN :followingIds))" + ) Page findProductsOfFollowedUsers( @Param("follower") final User follower, @Param("followingIds") final Set followingIds, diff --git a/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java b/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java index ae6fb79e..4af51659 100644 --- a/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java +++ b/src/main/java/taco/klkl/domain/user/dao/FollowRepository.java @@ -12,7 +12,7 @@ public interface FollowRepository extends JpaRepository { List findByFollowerId(final Long followerId); - boolean existsByFollowerAndFollowing(final User Follower, final User Following); + boolean existsByFollowerAndFollowing(final User follower, final User following); void deleteByFollowerAndFollowing(final User follower, final User following); } From fec7e2f8e61f7e44858bbf45c6643557b06b94fc Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 19:20:44 +0900 Subject: [PATCH 31/35] KL-166/fix: test errors --- .../integration/CommentIntegrationTest.java | 6 ++--- .../NotificationIntegrationTest.java | 2 +- .../service/NotificationServiceTest.java | 12 ++++++--- .../integration/ProductIntegrationTest.java | 27 ++++++++++--------- .../user/integration/UserIntegrationTest.java | 3 ++- 5 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/test/java/taco/klkl/domain/comment/integration/CommentIntegrationTest.java b/src/test/java/taco/klkl/domain/comment/integration/CommentIntegrationTest.java index 1438c89f..9f406b78 100644 --- a/src/test/java/taco/klkl/domain/comment/integration/CommentIntegrationTest.java +++ b/src/test/java/taco/klkl/domain/comment/integration/CommentIntegrationTest.java @@ -35,7 +35,7 @@ public class CommentIntegrationTest { @Autowired private ObjectMapper objectMapper; - private final Long productId = 390L; + private final Long productId = 101L; private final Long commentId = 500L; private final CommentCreateUpdateRequest commentCreateRequestDto = new CommentCreateUpdateRequest( @@ -142,7 +142,7 @@ public void testUpdateCommentWhenProductNotFound() throws Exception { @DisplayName("댓글 수정시 존재하는 상품이지만 댓글에 저장된 상품 Id와 달라 실패하는 경우 테스트") public void testUpdateCommentWhenExistProductButNotMatchWithComment() throws Exception { //given - Long differentProductId = 101L; + Long differentProductId = 102L; //when & given mockMvc.perform(put("/v1/products/{wrongProductId}/comments/{commentId}", differentProductId, commentId) @@ -201,7 +201,7 @@ public void testDeleteCommentWhenProductNotFound() throws Exception { @DisplayName("댓글 삭제시 존재하는 상품이지만 댓글에 저장된 상품 Id와 달라 실패하는 경우 테스트") public void testDeleteCommentWhenExistProductButNotMatchWithComment() throws Exception { //given - Long differentProductId = 101L; + Long differentProductId = 102L; //when & given mockMvc.perform(delete("/v1/products/{wrongProductId}/comments/{commentId}", differentProductId, commentId) diff --git a/src/test/java/taco/klkl/domain/notification/integration/NotificationIntegrationTest.java b/src/test/java/taco/klkl/domain/notification/integration/NotificationIntegrationTest.java index 8c4e705b..66b15288 100644 --- a/src/test/java/taco/klkl/domain/notification/integration/NotificationIntegrationTest.java +++ b/src/test/java/taco/klkl/domain/notification/integration/NotificationIntegrationTest.java @@ -59,7 +59,7 @@ public void testReadAllNotifications() throws Exception { @DisplayName("단일 알림 읽음 테스트 - 성공") public void testReadOneNotification() throws Exception { //given - Long notificationId = 700L; + Long notificationId = 701L; //when & then mockMvc.perform(put("/v1/notifications/{notificationId}/read", notificationId) diff --git a/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java b/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java index bcbb135b..ebe4baee 100644 --- a/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java +++ b/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java @@ -180,7 +180,6 @@ public void testReadAllNotifications() { when(userUtil.getCurrentUser()).thenReturn(mockUser); when(notificationRepository.findByComment_Product_User(mockUser)).thenReturn(notificationList); - when(notificationRepository.count()).thenReturn(2L); //when NotificationUpdateResponse response = notificationService.readAllNotifications(); @@ -188,6 +187,9 @@ public void testReadAllNotifications() { //then assertThat(response.updatedCount()).isEqualTo(2L); verify(notificationRepository).findByComment_Product_User(mockUser); + + assertTrue(notification1.getIsRead()); + assertTrue(notification2.getIsRead()); } @Test @@ -196,14 +198,16 @@ public void testReadNotificationsById() { //given Notification notification = Notification.of(comment); - when(notificationRepository.findById(any(Long.class))).thenReturn(Optional.of(notification)); + when(userUtil.getCurrentUser()).thenReturn(mockUser); + when(notificationRepository.findById(1L)).thenReturn(Optional.of(notification)); //when - NotificationUpdateResponse response = notificationService.readNotificationById(any(Long.class)); + NotificationUpdateResponse response = notificationService.readNotificationById(1L); //then assertThat(response.updatedCount()).isEqualTo(1L); - verify(notificationRepository).findById(any(Long.class)); + verify(notificationRepository).findById(1L); + assertTrue(notification.getIsRead()); } @Test diff --git a/src/test/java/taco/klkl/domain/product/integration/ProductIntegrationTest.java b/src/test/java/taco/klkl/domain/product/integration/ProductIntegrationTest.java index c1c7b980..33e7f770 100644 --- a/src/test/java/taco/klkl/domain/product/integration/ProductIntegrationTest.java +++ b/src/test/java/taco/klkl/domain/product/integration/ProductIntegrationTest.java @@ -492,12 +492,13 @@ public void testGetProductsBySingleSubcategoryId() throws Exception { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.isSuccess", is(true))) - .andExpect(jsonPath("$.data.content", hasSize(2))) - .andExpect(jsonPath("$.data.content[0].name", is(createRamenRequest1.name()))) - .andExpect(jsonPath("$.data.content[1].name", is(createRamenRequest2.name()))) + .andExpect(jsonPath("$.data.content", hasSize(3))) + .andExpect(jsonPath("$.data.content[0].name", is("하오하오 봉지라면 핑크색"))) + .andExpect(jsonPath("$.data.content[1].name", is(createRamenRequest1.name()))) + .andExpect(jsonPath("$.data.content[2].name", is(createRamenRequest2.name()))) .andExpect(jsonPath("$.data.pageNumber", is(0))) .andExpect(jsonPath("$.data.pageSize", is(ProductConstants.DEFAULT_PAGE_SIZE))) - .andExpect(jsonPath("$.data.totalElements", is(2))) + .andExpect(jsonPath("$.data.totalElements", is(3))) .andExpect(jsonPath("$.data.totalPages", is(1))) .andExpect(jsonPath("$.data.last", is(true))) .andExpect(jsonPath("$.timestamp", notNullValue())); @@ -564,13 +565,14 @@ public void testGetProductsByMultipleSubcategoryIds() throws Exception { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.isSuccess", is(true))) - .andExpect(jsonPath("$.data.content", hasSize(3))) - .andExpect(jsonPath("$.data.content[0].name", is(createRamenRequest1.name()))) - .andExpect(jsonPath("$.data.content[1].name", is(createRamenRequest2.name()))) - .andExpect(jsonPath("$.data.content[2].name", is(createShoeRequest.name()))) + .andExpect(jsonPath("$.data.content", hasSize(4))) + .andExpect(jsonPath("$.data.content[0].name", is("하오하오 봉지라면 핑크색"))) + .andExpect(jsonPath("$.data.content[1].name", is(createRamenRequest1.name()))) + .andExpect(jsonPath("$.data.content[2].name", is(createRamenRequest2.name()))) + .andExpect(jsonPath("$.data.content[3].name", is(createShoeRequest.name()))) .andExpect(jsonPath("$.data.pageNumber", is(0))) .andExpect(jsonPath("$.data.pageSize", is(ProductConstants.DEFAULT_PAGE_SIZE))) - .andExpect(jsonPath("$.data.totalElements", is(3))) + .andExpect(jsonPath("$.data.totalElements", is(4))) .andExpect(jsonPath("$.data.totalPages", is(1))) .andExpect(jsonPath("$.data.last", is(true))) .andExpect(jsonPath("$.timestamp", notNullValue())); @@ -1056,9 +1058,10 @@ public void testSortProductsByLikeCountDesc() throws Exception { .andExpect(status().isOk()) .andExpect(jsonPath("$.isSuccess", is(true))) .andExpect(jsonPath("$.data.content", hasSize(all.size()))) - .andExpect(jsonPath("$.data.content[0].name", is("여름 원피스"))) - .andExpect(jsonPath("$.data.content[1].name", is("곤약젤리"))) - .andExpect(jsonPath("$.data.content[2].name", is("왕족발 보쌈 과자"))) + .andExpect(jsonPath("$.data.content[0].name", is("하오하오 봉지라면 핑크색"))) + .andExpect(jsonPath("$.data.content[1].name", is("여름 원피스"))) + .andExpect(jsonPath("$.data.content[2].name", is("곤약젤리"))) + .andExpect(jsonPath("$.data.content[3].name", is("왕족발 보쌈 과자"))) .andExpect(jsonPath("$.data.pageNumber", is(0))) .andExpect(jsonPath("$.data.pageSize", is(ProductConstants.DEFAULT_PAGE_SIZE))) .andExpect(jsonPath("$.data.totalElements", is(all.size()))) diff --git a/src/test/java/taco/klkl/domain/user/integration/UserIntegrationTest.java b/src/test/java/taco/klkl/domain/user/integration/UserIntegrationTest.java index 928c84db..f04a794a 100644 --- a/src/test/java/taco/klkl/domain/user/integration/UserIntegrationTest.java +++ b/src/test/java/taco/klkl/domain/user/integration/UserIntegrationTest.java @@ -30,7 +30,8 @@ public class UserIntegrationTest { @Autowired UserRepository userRepository; - UserUtil userUtil; + @Autowired + private UserUtil userUtil; @Test public void testUserMe() throws Exception { From 97aaa543207a62ebb04c6cc62fb4ba2014872e90 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 19:33:55 +0900 Subject: [PATCH 32/35] KL-166/chore: rename variables --- .../taco/klkl/domain/user/controller/UserController.java | 6 +++--- .../klkl/domain/user/dto/request/UserFollowRequest.java | 4 ++-- .../java/taco/klkl/domain/user/service/UserServiceImpl.java | 2 +- .../global/common/constants/UserValidationMessages.java | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/taco/klkl/domain/user/controller/UserController.java b/src/main/java/taco/klkl/domain/user/controller/UserController.java index 9946f522..961427da 100644 --- a/src/main/java/taco/klkl/domain/user/controller/UserController.java +++ b/src/main/java/taco/klkl/domain/user/controller/UserController.java @@ -94,9 +94,9 @@ public UserFollowResponse followUser(@Valid @RequestBody final UserFollowRequest } @Operation(summary = "유저 팔로우 취소", description = "유저 팔로우를 취소합니다.") - @DeleteMapping("/following/{targetUserId}") - public UserFollowResponse cancelUserFollow(@PathVariable final Long targetUserId) { - return userService.removeUserFollow(targetUserId); + @DeleteMapping("/following/{userId}") + public UserFollowResponse cancelUserFollow(@PathVariable final Long userId) { + return userService.removeUserFollow(userId); } @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") diff --git a/src/main/java/taco/klkl/domain/user/dto/request/UserFollowRequest.java b/src/main/java/taco/klkl/domain/user/dto/request/UserFollowRequest.java index c87eb47d..5487726f 100644 --- a/src/main/java/taco/klkl/domain/user/dto/request/UserFollowRequest.java +++ b/src/main/java/taco/klkl/domain/user/dto/request/UserFollowRequest.java @@ -4,7 +4,7 @@ import taco.klkl.global.common.constants.UserValidationMessages; public record UserFollowRequest( - @NotNull(message = UserValidationMessages.TARGET_USER_ID_NOT_NULL) - Long targetUserId + @NotNull(message = UserValidationMessages.USER_ID_NOT_NULL) + Long userId ) { } diff --git a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java index fa782a80..bf007459 100644 --- a/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java +++ b/src/main/java/taco/klkl/domain/user/service/UserServiceImpl.java @@ -96,7 +96,7 @@ public User createUser(final UserCreateRequest createRequest) { @Transactional public UserFollowResponse createUserFollow(final UserFollowRequest followRequest) { final User follower = userUtil.getCurrentUser(); - final User following = userRepository.findById(followRequest.targetUserId()) + final User following = userRepository.findById(followRequest.userId()) .orElseThrow(UserNotFoundException::new); if (isFollowPresent(follower, following)) { return UserFollowResponse.of(true, follower, following); diff --git a/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java b/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java index 6dd75e9c..943015a2 100644 --- a/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java +++ b/src/main/java/taco/klkl/global/common/constants/UserValidationMessages.java @@ -3,7 +3,7 @@ public final class UserValidationMessages { public static final String NAME_NOT_BLANK = "이름은 비워둘 수 없습니다."; - public static final String TARGET_USER_ID_NOT_NULL = "대상 유저 ID는 필수 항목입니다."; + public static final String USER_ID_NOT_NULL = "유저 ID는 필수 항목입니다."; private UserValidationMessages() { } From f0fe22ca81acfc35712637fe5e9b79f5699dbbfb Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 19:38:08 +0900 Subject: [PATCH 33/35] KL-166/refactor: use CREATED for post responses --- .../comment/controller/CommentController.java | 6 +++--- .../image/controller/ImageController.java | 12 +++++++---- .../like/controller/LikeController.java | 3 +++ .../product/controller/ProductController.java | 3 +++ .../user/controller/UserController.java | 21 +++++++++++-------- 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/main/java/taco/klkl/domain/comment/controller/CommentController.java b/src/main/java/taco/klkl/domain/comment/controller/CommentController.java index 35855bdf..3fb20b66 100644 --- a/src/main/java/taco/klkl/domain/comment/controller/CommentController.java +++ b/src/main/java/taco/klkl/domain/comment/controller/CommentController.java @@ -37,8 +37,8 @@ public List findCommentsByProductId(@PathVariable final Long pr } @PostMapping - @Operation(summary = "댓글 등록", description = "작성한 댓글을 저장합니다.") @ResponseStatus(HttpStatus.CREATED) + @Operation(summary = "댓글 등록", description = "작성한 댓글을 저장합니다.") public CommentResponse addComment( @PathVariable final Long productId, @RequestBody @Valid final CommentCreateUpdateRequest commentCreateRequestDto @@ -50,8 +50,8 @@ public CommentResponse addComment( } @PutMapping("/{commentId}") - @Operation(summary = "댓글 수정", description = "작성한 댓글을 수정합니다.") @ResponseStatus(HttpStatus.OK) + @Operation(summary = "댓글 수정", description = "작성한 댓글을 수정합니다.") public CommentResponse updateComment( @PathVariable final Long productId, @PathVariable final Long commentId, @@ -65,8 +65,8 @@ public CommentResponse updateComment( } @DeleteMapping("/{commentId}") - @Operation(summary = "댓글 삭제", description = "작성한 댓글을 삭제합니다.") @ResponseStatus(HttpStatus.NO_CONTENT) + @Operation(summary = "댓글 삭제", description = "작성한 댓글을 삭제합니다.") public ResponseEntity deleteComment( @PathVariable final Long productId, @PathVariable final Long commentId diff --git a/src/main/java/taco/klkl/domain/image/controller/ImageController.java b/src/main/java/taco/klkl/domain/image/controller/ImageController.java index e3334168..fec40a31 100644 --- a/src/main/java/taco/klkl/domain/image/controller/ImageController.java +++ b/src/main/java/taco/klkl/domain/image/controller/ImageController.java @@ -2,9 +2,11 @@ import java.util.List; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; @@ -29,22 +31,24 @@ public class ImageController { private final ImageService imageService; + @PostMapping("/v1/users/me/upload-url") + @ResponseStatus(HttpStatus.CREATED) @Operation( summary = "유저 이미지 업로드 Presigned URL 생성", description = "유저 이미지 업로드를 위한 Presigned URL를 생성합니다." ) - @PostMapping("/v1/users/me/upload-url") public PresignedUrlResponse createUserImageUploadUrl( @Valid @RequestBody final SingleImageUploadRequest request ) { return imageService.createUserImageUploadUrl(request); } + @PostMapping("/v1/products/{productId}/upload-url") + @ResponseStatus(HttpStatus.CREATED) @Operation( summary = "상품 이미지 업로드 Presigned URL 생성", description = "상품 이미지 업로드를 위한 Presigned URL를 생성합니다." ) - @PostMapping("/v1/products/{productId}/upload-url") public List createProductImageUploadUrls( @PathVariable final Long productId, @Valid @RequestBody final MultipleImagesUploadRequest request @@ -52,22 +56,22 @@ public List createProductImageUploadUrls( return imageService.createProductImageUploadUrls(productId, request); } + @PostMapping("/v1/users/me/upload-complete") @Operation( summary = "유저 이미지 업로드 완료 처리", description = "유저 이미지 업로드를 완료 처리합니다." ) - @PostMapping("/v1/users/me/upload-complete") public SingleUploadCompleteResponse uploadCompleteUserImage( @Valid @RequestBody final SingleImageUpdateRequest request ) { return imageService.uploadCompleteUserImage(request); } + @PostMapping("/v1/products/{productId}/upload-complete") @Operation( summary = "상품 이미지 업로드 완료 처리", description = "상품 이미지 업로드를 완료 처리합니다." ) - @PostMapping("/v1/products/{productId}/upload-complete") public MultipleUploadCompleteResponse uploadCompleteProductImages( @PathVariable final Long productId, @Valid @RequestBody final MultipleImagesUpdateRequest request diff --git a/src/main/java/taco/klkl/domain/like/controller/LikeController.java b/src/main/java/taco/klkl/domain/like/controller/LikeController.java index 89e45c36..fa5dad86 100644 --- a/src/main/java/taco/klkl/domain/like/controller/LikeController.java +++ b/src/main/java/taco/klkl/domain/like/controller/LikeController.java @@ -1,9 +1,11 @@ package taco.klkl.domain.like.controller; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; @@ -23,6 +25,7 @@ public class LikeController { private final LikeService likeService; @PostMapping + @ResponseStatus(HttpStatus.CREATED) @Operation(summary = "좋아요 누르기", description = "상품에 좋아요를 누릅니다.") public LikeResponse addLike(@PathVariable final Long productId) { return likeService.createLike(productId); diff --git a/src/main/java/taco/klkl/domain/product/controller/ProductController.java b/src/main/java/taco/klkl/domain/product/controller/ProductController.java index 466043e5..267d4423 100644 --- a/src/main/java/taco/klkl/domain/product/controller/ProductController.java +++ b/src/main/java/taco/klkl/domain/product/controller/ProductController.java @@ -5,6 +5,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -14,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; @@ -94,6 +96,7 @@ public ProductDetailResponse findProductById( } @PostMapping + @ResponseStatus(HttpStatus.CREATED) @Operation(summary = "상품 등록", description = "상품을 등록합니다.") public ResponseEntity createProduct( @Valid @RequestBody final ProductCreateUpdateRequest createRequest diff --git a/src/main/java/taco/klkl/domain/user/controller/UserController.java b/src/main/java/taco/klkl/domain/user/controller/UserController.java index 961427da..d3467204 100644 --- a/src/main/java/taco/klkl/domain/user/controller/UserController.java +++ b/src/main/java/taco/klkl/domain/user/controller/UserController.java @@ -4,6 +4,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -11,6 +12,7 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import io.swagger.v3.oas.annotations.Operation; @@ -40,21 +42,21 @@ public class UserController { private final UserService userService; private final UserUtil userUtil; - @Operation(summary = "내 정보 조회", description = "내 정보를 조회합니다.") @GetMapping("/me") + @Operation(summary = "내 정보 조회", description = "내 정보를 조회합니다.") public UserDetailResponse getMe() { final User me = userUtil.getCurrentUser(); return userService.getUserById(me.getId()); } - @Operation(summary = "유저 정보 조회", description = "유저 정보를 조회합니다.") @GetMapping("/{userId}") + @Operation(summary = "유저 정보 조회", description = "유저 정보를 조회합니다.") public UserDetailResponse getUser(@PathVariable final Long userId) { return userService.getUserById(userId); } - @Operation(summary = "내 상품 목록 조회", description = "내 상품 목록을 조회합니다.") @GetMapping("/me/products") + @Operation(summary = "내 상품 목록 조회", description = "내 상품 목록을 조회합니다.") public PagedResponse getMyProducts( @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable ) { @@ -62,8 +64,8 @@ public PagedResponse getMyProducts( return userService.getUserProductsById(me.getId(), pageable); } - @Operation(summary = "유저의 상품 목록 조회", description = "유저의 상품 목록을 조회합니다.") @GetMapping("/{userId}/products") + @Operation(summary = "유저의 상품 목록 조회", description = "유저의 상품 목록을 조회합니다.") public PagedResponse getUserProducts( @PathVariable final Long userId, @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable @@ -71,8 +73,8 @@ public PagedResponse getUserProducts( return userService.getUserProductsById(userId, pageable); } - @Operation(summary = "내 종아요 목록 조회", description = "내 좋아요 목록을 조회합니다.") @GetMapping("/me/likes") + @Operation(summary = "내 종아요 목록 조회", description = "내 좋아요 목록을 조회합니다.") public PagedResponse getMyLikes( @PageableDefault(size = ProductConstants.DEFAULT_PAGE_SIZE) Pageable pageable ) { @@ -80,27 +82,28 @@ public PagedResponse getMyLikes( return userService.getUserLikesById(me.getId(), pageable); } - @Operation(summary = "내 팔로잉 목록 조회", description = "내 팔로잉 목록을 조회합니다.") @GetMapping("/following") + @Operation(summary = "내 팔로잉 목록 조회", description = "내 팔로잉 목록을 조회합니다.") public List getMyFollowing() { final User me = userUtil.getCurrentUser(); return userService.getUserFollowingById(me.getId()); } - @Operation(summary = "유저 팔로우", description = "유저를 팔로우합니다.") @PostMapping("/following") + @ResponseStatus(HttpStatus.CREATED) + @Operation(summary = "유저 팔로우", description = "유저를 팔로우합니다.") public UserFollowResponse followUser(@Valid @RequestBody final UserFollowRequest request) { return userService.createUserFollow(request); } - @Operation(summary = "유저 팔로우 취소", description = "유저 팔로우를 취소합니다.") @DeleteMapping("/following/{userId}") + @Operation(summary = "유저 팔로우 취소", description = "유저 팔로우를 취소합니다.") public UserFollowResponse cancelUserFollow(@PathVariable final Long userId) { return userService.removeUserFollow(userId); } - @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") @PutMapping("/me") + @Operation(summary = "내 정보 수정", description = "내 정보를 수정합니다.") public UserDetailResponse updateMe(@Valid @RequestBody final UserUpdateRequest request) { return userService.updateUser(request); } From 7a66599e914f48c1ca0d5f539ef0f81b6cdb06e2 Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 20:13:03 +0900 Subject: [PATCH 34/35] KL-166/test: fix test errors --- ...{CommentServiceTest.java => CommentServiceImplTest.java} | 2 +- .../klkl/domain/like/controller/LikeControllerTest.java | 2 +- .../klkl/domain/like/integration/LikeIntegrationTest.java | 6 +++--- ...ionServiceTest.java => NotificationServiceImplTest.java} | 2 +- .../klkl/domain/product/service/ProductServiceImplTest.java | 2 ++ .../taco/klkl/domain/user/service/UserServiceImplTest.java | 4 +++- 6 files changed, 11 insertions(+), 7 deletions(-) rename src/test/java/taco/klkl/domain/comment/service/{CommentServiceTest.java => CommentServiceImplTest.java} (99%) rename src/test/java/taco/klkl/domain/notification/service/{NotificationServiceTest.java => NotificationServiceImplTest.java} (99%) diff --git a/src/test/java/taco/klkl/domain/comment/service/CommentServiceTest.java b/src/test/java/taco/klkl/domain/comment/service/CommentServiceImplTest.java similarity index 99% rename from src/test/java/taco/klkl/domain/comment/service/CommentServiceTest.java rename to src/test/java/taco/klkl/domain/comment/service/CommentServiceImplTest.java index 61ae240b..510017ff 100644 --- a/src/test/java/taco/klkl/domain/comment/service/CommentServiceTest.java +++ b/src/test/java/taco/klkl/domain/comment/service/CommentServiceImplTest.java @@ -31,7 +31,7 @@ @ExtendWith(MockitoExtension.class) @Transactional -public class CommentServiceTest { +public class CommentServiceImplTest { @Mock private CommentRepository commentRepository; diff --git a/src/test/java/taco/klkl/domain/like/controller/LikeControllerTest.java b/src/test/java/taco/klkl/domain/like/controller/LikeControllerTest.java index 292d66d5..39c815f7 100644 --- a/src/test/java/taco/klkl/domain/like/controller/LikeControllerTest.java +++ b/src/test/java/taco/klkl/domain/like/controller/LikeControllerTest.java @@ -48,7 +48,7 @@ void testPostLike() throws Exception { // when & then mockMvc.perform(post("/v1/products/{productId}/likes", productId)) - .andExpect(status().isOk()) + .andExpect(status().isCreated()) .andExpect(jsonPath("$.isSuccess", is(true))) .andExpect(jsonPath("$.data.isLiked", is(true))) .andExpect(jsonPath("$.data.likeCount", is(1))); diff --git a/src/test/java/taco/klkl/domain/like/integration/LikeIntegrationTest.java b/src/test/java/taco/klkl/domain/like/integration/LikeIntegrationTest.java index 5c18859b..67a8fac4 100644 --- a/src/test/java/taco/klkl/domain/like/integration/LikeIntegrationTest.java +++ b/src/test/java/taco/klkl/domain/like/integration/LikeIntegrationTest.java @@ -75,7 +75,7 @@ void afterEach() { void testPostLike() throws Exception { // when & then mockMvc.perform(post("/v1/products/{productId}/likes", product.getId())) - .andExpect(status().isOk()) + .andExpect(status().isCreated()) .andExpect(jsonPath("$.data.isLiked", is(true))) .andExpect(jsonPath("$.data.likeCount", is(1))); @@ -97,12 +97,12 @@ void testDeleteLike() throws Exception { void testPostLikeMultiple() throws Exception { // when & then mockMvc.perform(post("/v1/products/{productId}/likes", product.getId())) - .andExpect(status().isOk()) + .andExpect(status().isCreated()) .andExpect(jsonPath("$.data.isLiked", is(true))) .andExpect(jsonPath("$.data.likeCount", is(1))); mockMvc.perform(post("/v1/products/{productId}/likes", product.getId())) - .andExpect(status().isOk()) + .andExpect(status().isCreated()) .andExpect(jsonPath("$.data.isLiked", is(true))) .andExpect(jsonPath("$.data.likeCount", is(1))); diff --git a/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java b/src/test/java/taco/klkl/domain/notification/service/NotificationServiceImplTest.java similarity index 99% rename from src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java rename to src/test/java/taco/klkl/domain/notification/service/NotificationServiceImplTest.java index ebe4baee..ec04c9b1 100644 --- a/src/test/java/taco/klkl/domain/notification/service/NotificationServiceTest.java +++ b/src/test/java/taco/klkl/domain/notification/service/NotificationServiceImplTest.java @@ -50,7 +50,7 @@ @ExtendWith(MockitoExtension.class) @Transactional -public class NotificationServiceTest { +public class NotificationServiceImplTest { @Mock private NotificationRepository notificationRepository; diff --git a/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java b/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java index 9d3b8b26..8dc9ef7d 100644 --- a/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java +++ b/src/test/java/taco/klkl/domain/product/service/ProductServiceImplTest.java @@ -413,6 +413,7 @@ void testCreateProduct() { void testUpdateProduct() { // Given when(productRepository.findById(1L)).thenReturn(Optional.of(testProduct)); + when(userUtil.getCurrentUser()).thenReturn(user); when(cityUtil.findCityEntityById(1L)).thenReturn(city); when(subcategoryUtil.findSubcategoryEntityById(1L)).thenReturn(subcategory); when(currencyUtil.findCurrencyEntityById(1L)).thenReturn(currency); @@ -441,6 +442,7 @@ void testUpdateProduct_NotFound() { void testDeleteProduct() { // Given when(productRepository.findById(1L)).thenReturn(Optional.of(testProduct)); + when(userUtil.getCurrentUser()).thenReturn(user); // When productService.deleteProduct(1L); diff --git a/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java b/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java index de97210e..19d4413e 100644 --- a/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java +++ b/src/test/java/taco/klkl/domain/user/service/UserServiceImplTest.java @@ -3,6 +3,8 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import java.util.Optional; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -38,10 +40,10 @@ public void testGetUserById() { // given User user = mock(User.class); - when(userUtil.getCurrentUser()).thenReturn(user); when(user.getId()).thenReturn(1L); when(user.getName()).thenReturn("testUser"); when(user.getDescription()).thenReturn("테스트입니다."); + when(userRepository.findById(1L)).thenReturn(Optional.of(user)); // when UserDetailResponse userDto = userServiceImpl.getUserById(1L); From 8a47033b6b54428eb8cbf46947daab0d8e066d9f Mon Sep 17 00:00:00 2001 From: ohhamma Date: Mon, 9 Sep 2024 20:13:16 +0900 Subject: [PATCH 35/35] KL-166/style: format code --- .../klkl/domain/product/service/ProductServiceImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java index 7d525eed..0216d8f0 100644 --- a/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java +++ b/src/main/java/taco/klkl/domain/product/service/ProductServiceImpl.java @@ -167,8 +167,10 @@ public int decreaseLikeCount(Product product) { @Override @Transactional - public ProductDetailResponse updateProduct(final Long id, final ProductCreateUpdateRequest updateRequest) - throws ProductNotFoundException { + public ProductDetailResponse updateProduct( + final Long id, + final ProductCreateUpdateRequest updateRequest + ) throws ProductNotFoundException { final Product product = productRepository.findById(id) .orElseThrow(ProductNotFoundException::new); validateMyProduct(product);