diff --git a/src/main/java/TtattaBackend/ttatta/apiPayload/code/status/ErrorStatus.java b/src/main/java/TtattaBackend/ttatta/apiPayload/code/status/ErrorStatus.java index 356460d0..1d35b425 100644 --- a/src/main/java/TtattaBackend/ttatta/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/TtattaBackend/ttatta/apiPayload/code/status/ErrorStatus.java @@ -59,6 +59,7 @@ public enum ErrorStatus implements BaseErrorCode { ITEM_NOT_EQUIPPED(HttpStatus.BAD_REQUEST,"ITEM_5004","아이템을 착용하고 있지 않습니다."), ITEM_ALREADY_EQUIPPED(HttpStatus.BAD_REQUEST,"ITEM_5005","동일한 아이템을 이미 착용하고 있습니다."), ITEM_NOT_BUY(HttpStatus.BAD_REQUEST,"ITEM_5006","구매한 아이템이 아닙니다."), + ITEM_BODYPART_QUERY_STRING_INVALID(HttpStatus.BAD_REQUEST,"ITEM_5007","bodyPart 쿼리 스트링이 올바르지 않습니다."), // 챌린지 관련 응답 6000 CHALLENGE_FULL(HttpStatus.BAD_REQUEST,"CHANLLENGE_6001","챌린지 3개가 이미 생성되어 있어 새로운 챌린지를 생성할 수 없습니다."), diff --git a/src/main/java/TtattaBackend/ttatta/domain/enums/BodyPart.java b/src/main/java/TtattaBackend/ttatta/domain/enums/BodyPart.java index 271c064b..1c6cfd6b 100644 --- a/src/main/java/TtattaBackend/ttatta/domain/enums/BodyPart.java +++ b/src/main/java/TtattaBackend/ttatta/domain/enums/BodyPart.java @@ -1,5 +1,5 @@ package TtattaBackend.ttatta.domain.enums; public enum BodyPart { - HEAD, TORSO + HEAD, EYES, TORSO } diff --git a/src/main/java/TtattaBackend/ttatta/repository/ItemRepository.java b/src/main/java/TtattaBackend/ttatta/repository/ItemRepository.java index 3ceff7fa..8f1ed2a0 100644 --- a/src/main/java/TtattaBackend/ttatta/repository/ItemRepository.java +++ b/src/main/java/TtattaBackend/ttatta/repository/ItemRepository.java @@ -14,6 +14,21 @@ @Repository public interface ItemRepository extends JpaRepository { + @Query("SELECT i FROM Items i " + + "WHERE i.bodyPart = :bodyPart " + + "AND NOT EXISTS (SELECT o FROM OwnedItems o WHERE o.users = :user AND o.items.id = i.id)") + List getShopItemByBodyPartHead(@Param("user") Users user, @Param("bodyPart") Optional bodyPart); + + @Query("SELECT i FROM Items i " + + "WHERE i.bodyPart = :bodyPart " + + "AND NOT EXISTS (SELECT o FROM OwnedItems o WHERE o.users = :user AND o.items.id = i.id)") + List getShopItemByBodyPartEyes(@Param("user") Users user, @Param("bodyPart") Optional bodyPart); + + @Query("SELECT i FROM Items i " + + "WHERE i.bodyPart = :bodyPart " + + "AND NOT EXISTS (SELECT o FROM OwnedItems o WHERE o.users = :user AND o.items.id = i.id)") + List getShopItemByBodyPartTorso(@Param("user") Users user, @Param("bodyPart") Optional bodyPart); + @Query("SELECT i FROM Items i " + "WHERE NOT EXISTS (SELECT o FROM OwnedItems o WHERE o.users = :user AND o.items.id = i.id)") List getShopItem(@Param("user") Users user); diff --git a/src/main/java/TtattaBackend/ttatta/service/ItemService/ItemQueryService.java b/src/main/java/TtattaBackend/ttatta/service/ItemService/ItemQueryService.java index 2d1dad52..a480ebed 100644 --- a/src/main/java/TtattaBackend/ttatta/service/ItemService/ItemQueryService.java +++ b/src/main/java/TtattaBackend/ttatta/service/ItemService/ItemQueryService.java @@ -1,13 +1,14 @@ package TtattaBackend.ttatta.service.ItemService; import TtattaBackend.ttatta.domain.Items; +import TtattaBackend.ttatta.domain.enums.BodyPart; import TtattaBackend.ttatta.domain.mapping.OwnedItems; import java.util.List; +import java.util.Optional; public interface ItemQueryService { - List getShopItem(); + List getShopItem(Optional bodyPart); List getMyItem(); List getEquippedItem(); - } diff --git a/src/main/java/TtattaBackend/ttatta/service/ItemService/ItemQueryServiceImpl.java b/src/main/java/TtattaBackend/ttatta/service/ItemService/ItemQueryServiceImpl.java index 1403c042..f00c9765 100644 --- a/src/main/java/TtattaBackend/ttatta/service/ItemService/ItemQueryServiceImpl.java +++ b/src/main/java/TtattaBackend/ttatta/service/ItemService/ItemQueryServiceImpl.java @@ -1,9 +1,11 @@ package TtattaBackend.ttatta.service.ItemService; +import TtattaBackend.ttatta.apiPayload.code.status.ErrorStatus; import TtattaBackend.ttatta.apiPayload.exception.handler.ExceptionHandler; import TtattaBackend.ttatta.config.security.SecurityUtil; import TtattaBackend.ttatta.domain.Items; import TtattaBackend.ttatta.domain.Users; +import TtattaBackend.ttatta.domain.enums.BodyPart; import TtattaBackend.ttatta.domain.mapping.OwnedItems; import TtattaBackend.ttatta.repository.ItemRepository; import TtattaBackend.ttatta.repository.OwnedItemRepository; @@ -13,8 +15,10 @@ import org.springframework.stereotype.Service; import java.util.List; +import java.util.Optional; import static TtattaBackend.ttatta.apiPayload.code.status.ErrorStatus.USER_NOT_FOUND; +import static TtattaBackend.ttatta.domain.enums.BodyPart.*; @Slf4j @Service @@ -22,18 +26,29 @@ public class ItemQueryServiceImpl implements ItemQueryService{ private final UserRepository userRepository; - private final ItemRepository itemRepository; - private final OwnedItemRepository ownedItemRepository; @Override - public List getShopItem() { + public List getShopItem(Optional bodyPart) { Long userId = SecurityUtil.getCurrentUserId(); Users user = userRepository.findById(userId) .orElseThrow(() -> new ExceptionHandler(USER_NOT_FOUND)); - return itemRepository.getShopItem(user); + // bodyPart에 따른 아이템 조회 + if (bodyPart.isPresent()) { + if (bodyPart.get() == HEAD) + return itemRepository.getShopItemByBodyPartHead(user, bodyPart); + else if (bodyPart.get() == EYES) + return itemRepository.getShopItemByBodyPartEyes(user, bodyPart); + else if (bodyPart.get() == TORSO) + return itemRepository.getShopItemByBodyPartTorso(user, bodyPart); + else if (bodyPart.get() == null) + return itemRepository.getShopItem(user); + else + throw new ExceptionHandler(ErrorStatus.ITEM_BODYPART_QUERY_STRING_INVALID); + } else + return itemRepository.getShopItem(user); } @Override diff --git a/src/main/java/TtattaBackend/ttatta/service/UserService/UserCommandServiceImpl.java b/src/main/java/TtattaBackend/ttatta/service/UserService/UserCommandServiceImpl.java index 9692642c..96ee4212 100644 --- a/src/main/java/TtattaBackend/ttatta/service/UserService/UserCommandServiceImpl.java +++ b/src/main/java/TtattaBackend/ttatta/service/UserService/UserCommandServiceImpl.java @@ -11,12 +11,10 @@ import TtattaBackend.ttatta.domain.Users; import TtattaBackend.ttatta.domain.UsersWithdrawals; import TtattaBackend.ttatta.domain.enums.*; +import TtattaBackend.ttatta.domain.mapping.OwnedItems; import TtattaBackend.ttatta.jwt.JwtUtils; import TtattaBackend.ttatta.oidc.*; -import TtattaBackend.ttatta.repository.DiaryCategoryRepository; -import TtattaBackend.ttatta.repository.DiaryRepository; -import TtattaBackend.ttatta.repository.UserRepository; -import TtattaBackend.ttatta.repository.UserWithdrawalRepository; +import TtattaBackend.ttatta.repository.*; import TtattaBackend.ttatta.web.dto.DiaryCategoryRequestDTO; import TtattaBackend.ttatta.web.dto.UserRequestDTO; import TtattaBackend.ttatta.web.dto.UserResponseDTO; @@ -40,9 +38,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; -import java.util.Collections; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.concurrent.TimeUnit; import static TtattaBackend.ttatta.apiPayload.code.status.ErrorStatus.*; @@ -52,19 +48,14 @@ @Slf4j public class UserCommandServiceImpl implements UserCommandService { - private final OauthOIDCHelper oauthOIDCHelper; - private final JwtAuthenticationFilter jwtAuthenticationFilter; @Value("${jwt.ACCESS_EXP_TIME}") private int accessExpTime; @Value("${jwt.REFRESH_EXP_TIME}") private int refreshExpTime; - @Value("${oidc.iss}") private String iss; - @Value("${oidc.aud}") private String aud; - private final UserRepository userRepository; private final DiaryRepository diaryRepository; private final DiaryCategoryRepository diaryCategoryRepository; @@ -79,6 +70,10 @@ public class UserCommandServiceImpl implements UserCommandService { private final KakaoOauthHelper kakaoOauthHelper; private final JwtOIDCProvider jwtOIDCProvider; private final AmazonS3Manager s3Manager; + private final OauthOIDCHelper oauthOIDCHelper; + private final JwtAuthenticationFilter jwtAuthenticationFilter; + private final ItemRepository itemRepository; + private final OwnedItemRepository ownedItemRepository; @Override public Users createTestUser() { @@ -101,19 +96,40 @@ public Users createTestUser() { @Override @Transactional // ??? public Users signUp(UserRequestDTO.SignUpRequestDTO request) { - // 아이디 중복 확인 + Users newUser = UserConverter.toUsers(request); IsAvailable usernameAvailable = verifyUsernameOverlap(request.getUsername()); + + // 아이디 중복 확인 if (usernameAvailable.equals(IsAvailable.UNAVAILABLE)) { throw new ExceptionHandler(ErrorStatus.USERNAME_ALREADY_EXIST); } - - Users newUser = UserConverter.toUsers(request); newUser.encodePassword(passwordEncoder.encode(request.getPassword())); // 일상 카테고리 생성 createDefaultCategory(newUser); + // 기본 아이템 착용 + saveAndEquipDefaultOwnedItems(newUser); + return userRepository.save(newUser); } + private void saveAndEquipDefaultOwnedItems(Users newUser) { + List ownedItemsList = new ArrayList<>(); + + ownedItemsList.add(createDefaultOwnedItems(newUser, 1L)); + ownedItemsList.add(createDefaultOwnedItems(newUser, 4L)); + ownedItemsList.add(createDefaultOwnedItems(newUser, 7L)); + ownedItemsList.add(createDefaultOwnedItems(newUser, 9L)); + ownedItemRepository.saveAll(ownedItemsList); + } + + private OwnedItems createDefaultOwnedItems(Users newUser, Long itemId) { + return OwnedItems.builder() + .users(newUser) + .items(itemRepository.findById(itemId).get()) // 머리 + .isEquipped(true) + .build(); + } + @Override @Transactional public UserResponseDTO.IsPendingResultDTO checkIsPending() { @@ -182,6 +198,10 @@ public UserResponseDTO.KaKaoFinalSignUpResultDTO kakaoSignUp(UserRequestDTO.Sign Long userId = SecurityUtil.getCurrentUserId(); Users savedUser = userRepository.findById(userId) .orElseThrow(() -> new ExceptionHandler(ErrorStatus.USER_NOT_FOUND)); + // 액세스 토큰 및 리프레시 토큰 생성 + String key = "users:" + savedUser.getId().toString(); + String accessToken = generateAccessToken(savedUser.getId(), accessExpTime); + String refreshToken = generateAndSaveRefreshToken(key, refreshExpTime); // 해당 닉네임을 업데이트 savedUser.updateNickname(request.getNickname()); @@ -189,11 +209,9 @@ public UserResponseDTO.KaKaoFinalSignUpResultDTO kakaoSignUp(UserRequestDTO.Sign savedUser.updateStatus(UserStatus.ACTIVE); // 일상 카테고리 생성 createDefaultCategory(savedUser); + // 기본 아이템 착용 + saveAndEquipDefaultOwnedItems(savedUser); - // 액세스 토큰 및 리프레시 토큰 생성 - String key = "users:" + savedUser.getId().toString(); - String accessToken = generateAccessToken(savedUser.getId(), accessExpTime); - String refreshToken = generateAndSaveRefreshToken(key, refreshExpTime); return UserConverter.toUserKaKaoFinalSignUpResultDTO(accessToken, refreshToken, savedUser); } diff --git a/src/main/java/TtattaBackend/ttatta/web/controller/ItemController.java b/src/main/java/TtattaBackend/ttatta/web/controller/ItemController.java index ffe4834a..5d5ad3b3 100644 --- a/src/main/java/TtattaBackend/ttatta/web/controller/ItemController.java +++ b/src/main/java/TtattaBackend/ttatta/web/controller/ItemController.java @@ -3,6 +3,7 @@ import TtattaBackend.ttatta.apiPayload.ApiResponse; import TtattaBackend.ttatta.converter.ItemConverter; import TtattaBackend.ttatta.domain.Items; +import TtattaBackend.ttatta.domain.enums.BodyPart; import TtattaBackend.ttatta.domain.mapping.OwnedItems; import TtattaBackend.ttatta.service.ItemService.ItemCommandService; import TtattaBackend.ttatta.service.ItemService.ItemQueryService; @@ -13,6 +14,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Optional; @RestController @RequiredArgsConstructor @@ -62,8 +64,10 @@ public ApiResponse disrobe (@PathVariable @Operation(summary = "미소유 아이템 (shop) api", description = "shop 화면에서 사용자가 구매하지 않은 아이템을 반환하는 API 입니다.") @GetMapping("/shop") - public ApiResponse shop () { - List itemsList = itemQueryService.getShopItem(); + public ApiResponse shop ( + @RequestParam(required = false) Optional bodyPart + ) { + List itemsList = itemQueryService.getShopItem(bodyPart); Long point = userCommandService.getUserPoint(); return ApiResponse.onSuccess(