diff --git a/src/main/java/org/sopt/confeti/api/auth/dto/request/OnboardRequest.java b/src/main/java/org/sopt/confeti/api/auth/dto/request/OnboardRequest.java index 00a32c90..5623b755 100644 --- a/src/main/java/org/sopt/confeti/api/auth/dto/request/OnboardRequest.java +++ b/src/main/java/org/sopt/confeti/api/auth/dto/request/OnboardRequest.java @@ -2,7 +2,9 @@ import java.util.List; +@Deprecated public record OnboardRequest( - List favoriteArtists + List favoriteArtists ) { + } diff --git a/src/main/java/org/sopt/confeti/api/auth/facade/AuthFacade.java b/src/main/java/org/sopt/confeti/api/auth/facade/AuthFacade.java index ddf7c941..94b7af36 100644 --- a/src/main/java/org/sopt/confeti/api/auth/facade/AuthFacade.java +++ b/src/main/java/org/sopt/confeti/api/auth/facade/AuthFacade.java @@ -68,12 +68,13 @@ public void logout(Long userId) { logoutService.logout(userId); } + @Deprecated @Transactional public void onboard(long userId, OnboardDTO onboardDTO) { User user = userService.findById(userId); Set favoriteArtistIds = onboardDTO.favoriteArtists().stream() - .map(OnboardArtistDTO::artistId) - .collect(Collectors.toSet()); + .map(OnboardArtistDTO::artistId) + .collect(Collectors.toSet()); onboardService.validateFavoriteArtistCount(favoriteArtistIds); artistFavoriteService.addFavorites(user, favoriteArtistIds); @@ -81,7 +82,7 @@ public void onboard(long userId, OnboardDTO onboardDTO) { } public void flushCachedTopArtists(long userId) { - userOnboardService.flushCachedTopArtists(userId); + userOnboardService.flushCachedOnboardArtists(userId); } @Transactional diff --git a/src/main/java/org/sopt/confeti/api/user/controller/UserOnboardControllerV4.java b/src/main/java/org/sopt/confeti/api/user/controller/UserOnboardControllerV4.java index 27bc6c77..91842fae 100644 --- a/src/main/java/org/sopt/confeti/api/user/controller/UserOnboardControllerV4.java +++ b/src/main/java/org/sopt/confeti/api/user/controller/UserOnboardControllerV4.java @@ -118,6 +118,19 @@ public ResponseEntity> getFavor UserOnboardFavoriteArtistsResponse.from(favoriteArtists)); } + /** + * 개발을 위해 임시로 Role.GENERAL 접근 허용 + */ + @Permission(role = {Role.ONBOARDING, Role.GENERAL}) + @PostMapping() + public ResponseEntity> onboard( + @UserId Long userId + ) { + userOnboardFacade.onboard(userId); + userOnboardFacade.flushCachedOnboardArtists(userId); + return ApiResponseUtil.success(SuccessMessage.SUCCESS); + } + /** * 개발을 위해 임시로 Role.GENERAL 접근 허용 */ diff --git a/src/main/java/org/sopt/confeti/api/user/controller/docs/UserOnboardControllerV4Docs.java b/src/main/java/org/sopt/confeti/api/user/controller/docs/UserOnboardControllerV4Docs.java index 86bb2c41..0a0fcb52 100644 --- a/src/main/java/org/sopt/confeti/api/user/controller/docs/UserOnboardControllerV4Docs.java +++ b/src/main/java/org/sopt/confeti/api/user/controller/docs/UserOnboardControllerV4Docs.java @@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import org.sopt.confeti.api.user.dto.request.PatchOnboardFavoriteArtistsRequest; import org.sopt.confeti.api.user.dto.response.onboard.UserOnboardFavoriteArtistsResponse; +import org.sopt.confeti.global.annotation.UserId; import org.sopt.confeti.global.common.BaseResponse; import org.sopt.confeti.global.common.swagger.AuthErrorResponses; import org.sopt.confeti.global.common.swagger.CommonErrorResponses; @@ -29,6 +30,29 @@ ResponseEntity> getFavoriteArti Long userId ); + @Operation( + summary = "회원가입한 유저의 온보딩 완료 요청", + description = + """ + V4 변경사항 + - RequestBody 로 favoriteArtistId 목록을 받아서 처리하던 부분이 사라짐 + - 서버에서 내부적으로 온보딩 시 사용된 favoriteArtistId 를 관리하므로 해당 데이터를 사용해 온보딩 완료 로직을 진행함 + """ + ) + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "성공" + ) + } + ) + @CommonErrorResponses + @AuthErrorResponses + ResponseEntity> onboard( + @UserId Long userId + ); + @Operation( summary = "온보딩 진행 중 favorite 으로 선택했던 아티스트 목록 수정", description = diff --git a/src/main/java/org/sopt/confeti/api/user/facade/UserOnboardFacade.java b/src/main/java/org/sopt/confeti/api/user/facade/UserOnboardFacade.java index 3a42aef5..00d09202 100644 --- a/src/main/java/org/sopt/confeti/api/user/facade/UserOnboardFacade.java +++ b/src/main/java/org/sopt/confeti/api/user/facade/UserOnboardFacade.java @@ -16,10 +16,13 @@ import org.sopt.confeti.api.user.facade.dto.response.onboard.UserOnboardCacheDTO; import org.sopt.confeti.api.user.facade.dto.response.onboard.UserOnboardFavoriteArtistsDTO; import org.sopt.confeti.api.user.facade.dto.response.onboard.UserOnboardRelatedArtistsDTO; +import org.sopt.confeti.domain.artist_favorite.application.ArtistFavoriteService; +import org.sopt.confeti.domain.user.User; import org.sopt.confeti.domain.user.application.UserOnboardService; import org.sopt.confeti.domain.user.application.UserService; import org.sopt.confeti.domain.user.constant.Role; import org.sopt.confeti.global.annotation.Facade; +import org.sopt.confeti.global.exception.BadRequestException; import org.sopt.confeti.global.exception.NotFoundException; import org.sopt.confeti.global.message.ErrorMessage; import org.sopt.confeti.global.resolver.music_api.artist.vo.ConfetiArtist; @@ -45,6 +48,7 @@ public class UserOnboardFacade { private final UserOnboardService userOnboardService; private final RedisTemplate redisTemplate; private final ObjectMapper objectMapper; + private final ArtistFavoriteService artistFavoriteService; public UserOnboardRelatedArtistsDTO getArtistsRelatedTerm(long userId, String term, int limit) { Set topArtistIds = userOnboardService.getCachedExposedArtistIds(userId); @@ -150,6 +154,22 @@ public UserOnboardFavoriteArtistsDTO getFavoriteArtists(long userId) { return UserOnboardFavoriteArtistsDTO.from(favoriteArtists); } + @Transactional + public void onboard(long userId) { + UserOnboardCacheDTO cachedArtists = userOnboardService.getCachedArtists(userId); + validOnboardArtists(cachedArtists); + + Set favoriteArtistIds = cachedArtists.favoriteArtistIds(); + User user = userService.findById(userId); + + artistFavoriteService.addFavorites(user, favoriteArtistIds); + user.setRole(Role.GENERAL); + } + + public void flushCachedOnboardArtists(long userId) { + userOnboardService.flushCachedOnboardArtists(userId); + } + public void cacheTopArtists(List topArtists) { redisTemplate.opsForValue().set(RedisKey.MUSIC_TOP_ARTISTS.get(), topArtists); } @@ -219,4 +239,12 @@ private void cacheRelatedArtists( UserOnboardCacheDTO.of(newFavoriteArtistIds, newExposedArtistIds)); } + private void validOnboardArtists(UserOnboardCacheDTO userOnboardCacheDTO) { + Set favoriteArtistIds = userOnboardCacheDTO.favoriteArtistIds(); + + if (favoriteArtistIds == null || favoriteArtistIds.isEmpty()) { + throw new BadRequestException(ErrorMessage.BAD_REQUEST); + } + } + } diff --git a/src/main/java/org/sopt/confeti/domain/user/application/UserOnboardService.java b/src/main/java/org/sopt/confeti/domain/user/application/UserOnboardService.java index 882a3498..7a99b172 100644 --- a/src/main/java/org/sopt/confeti/domain/user/application/UserOnboardService.java +++ b/src/main/java/org/sopt/confeti/domain/user/application/UserOnboardService.java @@ -52,7 +52,7 @@ public void cacheOnboardArtists(long userId, UserOnboardCacheDTO artistsDTO) { .set(generateRedisKey(userId), artistsDTO, REDIS_TTL_DAY, TimeUnit.DAYS); } - public void flushCachedTopArtists(long userId) { + public void flushCachedOnboardArtists(long userId) { redisTemplate.delete(generateRedisKey(userId)); } } diff --git a/src/main/java/org/sopt/confeti/global/exception/BadRequestException.java b/src/main/java/org/sopt/confeti/global/exception/BadRequestException.java new file mode 100644 index 00000000..9bbb9f31 --- /dev/null +++ b/src/main/java/org/sopt/confeti/global/exception/BadRequestException.java @@ -0,0 +1,10 @@ +package org.sopt.confeti.global.exception; + +import org.sopt.confeti.global.message.ErrorMessage; + +public class BadRequestException extends ConfetiException { + + public BadRequestException(ErrorMessage message) { + super(message); + } +} diff --git a/src/main/java/org/sopt/confeti/global/exception/GlobalExceptionHandler.java b/src/main/java/org/sopt/confeti/global/exception/GlobalExceptionHandler.java index ce3778b2..23d951b3 100644 --- a/src/main/java/org/sopt/confeti/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/org/sopt/confeti/global/exception/GlobalExceptionHandler.java @@ -12,6 +12,13 @@ @RestControllerAdvice public class GlobalExceptionHandler { + @ExceptionHandler(BadRequestException.class) + public ResponseEntity> handleIllegalArgumentException( + BadRequestException e, HttpServletRequest request) { + request.setAttribute("exception", e); + return ApiResponseUtil.failure(ErrorMessage.BAD_REQUEST); + } + @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity> handleIllegalArgumentException( IllegalArgumentException e, HttpServletRequest request) {